commit 031ca812ad091dfcf43e9b6c561d153819523053 Author: audioprog Date: Wed Aug 13 22:05:17 2025 +0200 init diff --git a/ABOUT-NLS b/ABOUT-NLS new file mode 100644 index 0000000..b1de1b6 --- /dev/null +++ b/ABOUT-NLS @@ -0,0 +1,1282 @@ +1 Notes on the Free Translation Project +*************************************** + +Free software is going international! The Free Translation Project is +a way to get maintainers of free software, translators, and users all +together, so that free software will gradually become able to speak many +languages. A few packages already provide translations for their +messages. + + If you found this `ABOUT-NLS' file inside a distribution, you may +assume that the distributed package does use GNU `gettext' internally, +itself available at your nearest GNU archive site. But you do _not_ +need to install GNU `gettext' prior to configuring, installing or using +this package with messages translated. + + Installers will find here some useful hints. These notes also +explain how users should proceed for getting the programs to use the +available translations. They tell how people wanting to contribute and +work on translations can contact the appropriate team. + +1.1 INSTALL Matters +=================== + +Some packages are "localizable" when properly installed; the programs +they contain can be made to speak your own native language. Most such +packages use GNU `gettext'. Other packages have their own ways to +internationalization, predating GNU `gettext'. + + By default, this package will be installed to allow translation of +messages. It will automatically detect whether the system already +provides the GNU `gettext' functions. Installers may use special +options at configuration time for changing the default behaviour. The +command: + + ./configure --disable-nls + +will _totally_ disable translation of messages. + + When you already have GNU `gettext' installed on your system and run +configure without an option for your new package, `configure' will +probably detect the previously built and installed `libintl' library +and will decide to use it. If not, you may have to to use the +`--with-libintl-prefix' option to tell `configure' where to look for it. + + Internationalized packages usually have many `po/LL.po' files, where +LL gives an ISO 639 two-letter code identifying the language. Unless +translations have been forbidden at `configure' time by using the +`--disable-nls' switch, all available translations are installed +together with the package. However, the environment variable `LINGUAS' +may be set, prior to configuration, to limit the installed set. +`LINGUAS' should then contain a space separated list of two-letter +codes, stating which languages are allowed. + +1.2 Using This Package +====================== + +As a user, if your language has been installed for this package, you +only have to set the `LANG' environment variable to the appropriate +`LL_CC' combination. If you happen to have the `LC_ALL' or some other +`LC_xxx' environment variables set, you should unset them before +setting `LANG', otherwise the setting of `LANG' will not have the +desired effect. Here `LL' is an ISO 639 two-letter language code, and +`CC' is an ISO 3166 two-letter country code. For example, let's +suppose that you speak German and live in Germany. At the shell +prompt, merely execute `setenv LANG de_DE' (in `csh'), +`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). +This can be done from your `.login' or `.profile' file, once and for +all. + + You might think that the country code specification is redundant. +But in fact, some languages have dialects in different countries. For +example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The +country code serves to distinguish the dialects. + + The locale naming convention of `LL_CC', with `LL' denoting the +language and `CC' denoting the country, is the one use on systems based +on GNU libc. On other systems, some variations of this scheme are +used, such as `LL' or `LL_CC.ENCODING'. You can get the list of +locales supported by your system for your language by running the +command `locale -a | grep '^LL''. + + Not all programs have translations for all languages. By default, an +English message is shown in place of a nonexistent translation. If you +understand other languages, you can set up a priority list of languages. +This is done through a different environment variable, called +`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' +for the purpose of message handling, but you still need to have `LANG' +set to the primary language; this is required by other parts of the +system libraries. For example, some Swedish users who would rather +read translations in German than English for when Swedish is not +available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. + + Special advice for Norwegian users: The language code for Norwegian +bokma*l changed from `no' to `nb' recently (in 2003). During the +transition period, while some message catalogs for this language are +installed under `nb' and some older ones under `no', it's recommended +for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and +older translations are used. + + In the `LANGUAGE' environment variable, but not in the `LANG' +environment variable, `LL_CC' combinations can be abbreviated as `LL' +to denote the language's main dialect. For example, `de' is equivalent +to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' +(Portuguese as spoken in Portugal) in this context. + +1.3 Translating Teams +===================== + +For the Free Translation Project to be a success, we need interested +people who like their own language and write it well, and who are also +able to synergize with other translators speaking the same language. +Each translation team has its own mailing list. The up-to-date list of +teams can be found at the Free Translation Project's homepage, +`http://translationproject.org/', in the "Teams" area. + + If you'd like to volunteer to _work_ at translating messages, you +should become a member of the translating team for your own language. +The subscribing address is _not_ the same as the list itself, it has +`-request' appended. For example, speakers of Swedish can send a +message to `sv-request@li.org', having this message body: + + subscribe + + Keep in mind that team members are expected to participate +_actively_ in translations, or at solving translational difficulties, +rather than merely lurking around. If your team does not exist yet and +you want to start one, or if you are unsure about what to do or how to +get started, please write to `coordinator@translationproject.org' to +reach the coordinator for all translator teams. + + The English team is special. It works at improving and uniformizing +the terminology in use. Proven linguistic skills are praised more than +programming skills, here. + +1.4 Available Packages +====================== + +Languages are not equally supported in all packages. The following +matrix shows the current state of internationalization, as of June +2010. The matrix shows, in regard of each package, for which languages +PO files have been submitted to translation coordination, with a +translation percentage of at least 50%. + + Ready PO files af am an ar as ast az be be@latin bg bn_IN bs ca + +--------------------------------------------------+ + a2ps | [] [] | + aegis | | + ant-phone | | + anubis | | + aspell | [] [] | + bash | | + bfd | | + bibshelf | [] | + binutils | | + bison | | + bison-runtime | [] | + bluez-pin | [] [] | + bombono-dvd | | + buzztard | | + cflow | | + clisp | | + coreutils | [] [] | + cpio | | + cppi | | + cpplib | [] | + cryptsetup | | + dfarc | | + dialog | [] [] | + dico | | + diffutils | [] | + dink | | + doodle | | + e2fsprogs | [] | + enscript | [] | + exif | | + fetchmail | [] | + findutils | [] | + flex | [] | + freedink | | + gas | | + gawk | [] [] | + gcal | [] | + gcc | | + gettext-examples | [] [] [] [] | + gettext-runtime | [] [] | + gettext-tools | [] [] | + gip | [] | + gjay | | + gliv | [] | + glunarclock | [] [] | + gnubiff | | + gnucash | [] | + gnuedu | | + gnulib | | + gnunet | | + gnunet-gtk | | + gnutls | | + gold | | + gpe-aerial | | + gpe-beam | | + gpe-bluetooth | | + gpe-calendar | | + gpe-clock | [] | + gpe-conf | | + gpe-contacts | | + gpe-edit | | + gpe-filemanager | | + gpe-go | | + gpe-login | | + gpe-ownerinfo | [] | + gpe-package | | + gpe-sketchbook | | + gpe-su | [] | + gpe-taskmanager | [] | + gpe-timesheet | [] | + gpe-today | [] | + gpe-todo | | + gphoto2 | | + gprof | [] | + gpsdrive | | + gramadoir | | + grep | | + grub | [] [] | + gsasl | | + gss | | + gst-plugins-bad | [] | + gst-plugins-base | [] | + gst-plugins-good | [] | + gst-plugins-ugly | [] | + gstreamer | [] [] [] | + gtick | | + gtkam | [] | + gtkorphan | [] | + gtkspell | [] [] [] | + gutenprint | | + hello | [] | + help2man | | + hylafax | | + idutils | | + indent | [] [] | + iso_15924 | | + iso_3166 | [] [] [] [] [] [] [] | + iso_3166_2 | | + iso_4217 | | + iso_639 | [] [] [] [] | + iso_639_3 | | + jwhois | | + kbd | | + keytouch | [] | + keytouch-editor | | + keytouch-keyboa... | [] | + klavaro | [] | + latrine | | + ld | [] | + leafpad | [] [] | + libc | [] [] | + libexif | () | + libextractor | | + libgnutls | | + libgpewidget | | + libgpg-error | | + libgphoto2 | | + libgphoto2_port | | + libgsasl | | + libiconv | [] | + libidn | | + lifelines | | + liferea | [] [] | + lilypond | | + linkdr | [] | + lordsawar | | + lprng | | + lynx | [] | + m4 | | + mailfromd | | + mailutils | | + make | | + man-db | | + man-db-manpages | | + minicom | | + mkisofs | | + myserver | | + nano | [] [] | + opcodes | | + parted | | + pies | | + popt | | + psmisc | | + pspp | [] | + pwdutils | | + radius | [] | + recode | [] [] | + rosegarden | | + rpm | | + rush | | + sarg | | + screem | | + scrollkeeper | [] [] [] | + sed | [] [] | + sharutils | [] [] | + shishi | | + skencil | | + solfege | | + solfege-manual | | + soundtracker | | + sp | | + sysstat | | + tar | [] | + texinfo | | + tin | | + unicode-han-tra... | | + unicode-transla... | | + util-linux-ng | [] | + vice | | + vmm | | + vorbis-tools | | + wastesedge | | + wdiff | | + wget | [] [] | + wyslij-po | | + xchat | [] [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] | + +--------------------------------------------------+ + af am an ar as ast az be be@latin bg bn_IN bs ca + 6 0 1 2 3 19 1 10 3 28 3 1 38 + + crh cs da de el en en_GB en_ZA eo es et eu fa + +-------------------------------------------------+ + a2ps | [] [] [] [] [] [] [] | + aegis | [] [] [] | + ant-phone | [] () | + anubis | [] [] | + aspell | [] [] [] [] [] | + bash | [] [] [] | + bfd | [] | + bibshelf | [] [] [] | + binutils | [] | + bison | [] [] | + bison-runtime | [] [] [] [] | + bluez-pin | [] [] [] [] [] [] | + bombono-dvd | [] | + buzztard | [] [] [] | + cflow | [] [] | + clisp | [] [] [] [] | + coreutils | [] [] [] [] | + cpio | | + cppi | | + cpplib | [] [] [] | + cryptsetup | [] | + dfarc | [] [] [] | + dialog | [] [] [] [] [] | + dico | | + diffutils | [] [] [] [] [] [] | + dink | [] [] [] | + doodle | [] | + e2fsprogs | [] [] [] | + enscript | [] [] [] | + exif | () [] [] | + fetchmail | [] [] () [] [] [] | + findutils | [] [] [] | + flex | [] [] | + freedink | [] [] [] | + gas | [] | + gawk | [] [] [] | + gcal | [] | + gcc | [] [] | + gettext-examples | [] [] [] [] | + gettext-runtime | [] [] [] [] | + gettext-tools | [] [] [] | + gip | [] [] [] [] | + gjay | [] | + gliv | [] [] [] | + glunarclock | [] [] | + gnubiff | () | + gnucash | [] () () () () | + gnuedu | [] [] | + gnulib | [] [] | + gnunet | | + gnunet-gtk | [] | + gnutls | [] [] | + gold | [] | + gpe-aerial | [] [] [] [] | + gpe-beam | [] [] [] [] | + gpe-bluetooth | [] [] | + gpe-calendar | [] | + gpe-clock | [] [] [] [] | + gpe-conf | [] [] [] | + gpe-contacts | [] [] [] | + gpe-edit | [] [] | + gpe-filemanager | [] [] [] | + gpe-go | [] [] [] [] | + gpe-login | [] [] | + gpe-ownerinfo | [] [] [] [] | + gpe-package | [] [] [] | + gpe-sketchbook | [] [] [] [] | + gpe-su | [] [] [] [] | + gpe-taskmanager | [] [] [] [] | + gpe-timesheet | [] [] [] [] | + gpe-today | [] [] [] [] | + gpe-todo | [] [] [] | + gphoto2 | [] [] () [] [] [] | + gprof | [] [] [] | + gpsdrive | [] [] [] | + gramadoir | [] [] [] | + grep | [] | + grub | [] [] | + gsasl | [] | + gss | | + gst-plugins-bad | [] [] [] [] [] | + gst-plugins-base | [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] | + gtick | [] () [] | + gtkam | [] [] () [] [] | + gtkorphan | [] [] [] [] | + gtkspell | [] [] [] [] [] [] [] | + gutenprint | [] [] [] | + hello | [] [] [] [] | + help2man | [] | + hylafax | [] [] | + idutils | [] [] | + indent | [] [] [] [] [] [] [] | + iso_15924 | [] () [] [] | + iso_3166 | [] [] [] [] () [] [] [] () | + iso_3166_2 | () | + iso_4217 | [] [] [] () [] [] | + iso_639 | [] [] [] [] () [] [] | + iso_639_3 | [] | + jwhois | [] | + kbd | [] [] [] [] [] | + keytouch | [] [] | + keytouch-editor | [] [] | + keytouch-keyboa... | [] | + klavaro | [] [] [] [] | + latrine | [] () | + ld | [] [] | + leafpad | [] [] [] [] [] [] | + libc | [] [] [] [] | + libexif | [] [] () | + libextractor | | + libgnutls | [] | + libgpewidget | [] [] | + libgpg-error | [] [] | + libgphoto2 | [] () | + libgphoto2_port | [] () [] | + libgsasl | | + libiconv | [] [] [] [] [] | + libidn | [] [] [] | + lifelines | [] () | + liferea | [] [] [] [] [] | + lilypond | [] [] [] | + linkdr | [] [] [] | + lordsawar | [] | + lprng | | + lynx | [] [] [] [] | + m4 | [] [] [] [] | + mailfromd | | + mailutils | [] | + make | [] [] [] | + man-db | | + man-db-manpages | | + minicom | [] [] [] [] | + mkisofs | | + myserver | | + nano | [] [] [] | + opcodes | [] [] | + parted | [] [] | + pies | | + popt | [] [] [] [] [] | + psmisc | [] [] [] | + pspp | [] | + pwdutils | [] | + radius | [] | + recode | [] [] [] [] [] [] | + rosegarden | () () () | + rpm | [] [] [] | + rush | | + sarg | | + screem | | + scrollkeeper | [] [] [] [] [] | + sed | [] [] [] [] [] [] | + sharutils | [] [] [] [] | + shishi | | + skencil | [] () [] | + solfege | [] [] [] | + solfege-manual | [] [] | + soundtracker | [] [] [] | + sp | [] | + sysstat | [] [] [] | + tar | [] [] [] [] | + texinfo | [] [] [] | + tin | [] [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux-ng | [] [] [] [] | + vice | () () | + vmm | [] | + vorbis-tools | [] [] | + wastesedge | [] | + wdiff | [] [] | + wget | [] [] [] | + wyslij-po | | + xchat | [] [] [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] [] [] | + +-------------------------------------------------+ + crh cs da de el en en_GB en_ZA eo es et eu fa + 5 64 105 117 18 1 8 0 28 89 18 19 0 + + fi fr ga gl gu he hi hr hu hy id is it ja ka kn + +----------------------------------------------------+ + a2ps | [] [] [] [] | + aegis | [] [] | + ant-phone | [] [] | + anubis | [] [] [] [] | + aspell | [] [] [] [] | + bash | [] [] [] [] | + bfd | [] [] [] | + bibshelf | [] [] [] [] [] | + binutils | [] [] [] | + bison | [] [] [] [] | + bison-runtime | [] [] [] [] [] [] | + bluez-pin | [] [] [] [] [] [] [] [] | + bombono-dvd | [] | + buzztard | [] | + cflow | [] [] [] | + clisp | [] | + coreutils | [] [] [] [] [] | + cpio | [] [] [] [] | + cppi | [] [] | + cpplib | [] [] [] | + cryptsetup | [] [] [] | + dfarc | [] [] [] | + dialog | [] [] [] [] [] [] [] | + dico | | + diffutils | [] [] [] [] [] [] [] [] [] | + dink | [] | + doodle | [] [] | + e2fsprogs | [] [] | + enscript | [] [] [] [] | + exif | [] [] [] [] [] [] | + fetchmail | [] [] [] [] | + findutils | [] [] [] [] [] [] | + flex | [] [] [] | + freedink | [] [] [] | + gas | [] [] | + gawk | [] [] [] [] () [] | + gcal | [] | + gcc | [] | + gettext-examples | [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] | + gettext-tools | [] [] [] [] | + gip | [] [] [] [] [] [] | + gjay | [] | + gliv | [] () | + glunarclock | [] [] [] [] | + gnubiff | () [] () | + gnucash | () () () () () [] | + gnuedu | [] [] | + gnulib | [] [] [] [] [] [] | + gnunet | | + gnunet-gtk | [] | + gnutls | [] [] | + gold | [] [] | + gpe-aerial | [] [] [] | + gpe-beam | [] [] [] [] | + gpe-bluetooth | [] [] [] [] | + gpe-calendar | [] [] | + gpe-clock | [] [] [] [] [] | + gpe-conf | [] [] [] [] | + gpe-contacts | [] [] [] [] | + gpe-edit | [] [] [] | + gpe-filemanager | [] [] [] [] | + gpe-go | [] [] [] [] [] | + gpe-login | [] [] [] | + gpe-ownerinfo | [] [] [] [] [] | + gpe-package | [] [] [] | + gpe-sketchbook | [] [] [] [] | + gpe-su | [] [] [] [] [] [] | + gpe-taskmanager | [] [] [] [] [] | + gpe-timesheet | [] [] [] [] [] | + gpe-today | [] [] [] [] [] [] [] | + gpe-todo | [] [] [] | + gphoto2 | [] [] [] [] [] [] | + gprof | [] [] [] [] | + gpsdrive | [] [] [] | + gramadoir | [] [] [] | + grep | [] [] | + grub | [] [] [] [] | + gsasl | [] [] [] [] [] | + gss | [] [] [] [] [] | + gst-plugins-bad | [] [] [] [] [] [] | + gst-plugins-base | [] [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] | + gtick | [] [] [] [] [] | + gtkam | [] [] [] [] [] | + gtkorphan | [] [] [] | + gtkspell | [] [] [] [] [] [] [] [] [] | + gutenprint | [] [] [] [] | + hello | [] [] [] | + help2man | [] [] | + hylafax | [] | + idutils | [] [] [] [] [] [] | + indent | [] [] [] [] [] [] [] [] | + iso_15924 | [] () [] [] | + iso_3166 | [] () [] [] [] [] [] [] [] [] [] [] | + iso_3166_2 | () [] [] [] | + iso_4217 | [] () [] [] [] [] | + iso_639 | [] () [] [] [] [] [] [] [] | + iso_639_3 | () [] [] | + jwhois | [] [] [] [] [] | + kbd | [] [] | + keytouch | [] [] [] [] [] [] | + keytouch-editor | [] [] [] [] [] | + keytouch-keyboa... | [] [] [] [] [] | + klavaro | [] [] | + latrine | [] [] [] | + ld | [] [] [] [] | + leafpad | [] [] [] [] [] [] [] () | + libc | [] [] [] [] [] | + libexif | [] | + libextractor | | + libgnutls | [] [] | + libgpewidget | [] [] [] [] | + libgpg-error | [] [] | + libgphoto2 | [] [] [] | + libgphoto2_port | [] [] [] | + libgsasl | [] [] [] [] [] | + libiconv | [] [] [] [] [] [] | + libidn | [] [] [] [] | + lifelines | () | + liferea | [] [] [] [] | + lilypond | [] [] | + linkdr | [] [] [] [] [] | + lordsawar | | + lprng | [] | + lynx | [] [] [] [] [] | + m4 | [] [] [] [] [] [] | + mailfromd | | + mailutils | [] [] | + make | [] [] [] [] [] [] [] [] [] | + man-db | [] [] | + man-db-manpages | [] | + minicom | [] [] [] [] [] | + mkisofs | [] [] [] [] | + myserver | | + nano | [] [] [] [] [] [] | + opcodes | [] [] [] [] | + parted | [] [] [] [] | + pies | | + popt | [] [] [] [] [] [] [] [] [] | + psmisc | [] [] [] | + pspp | | + pwdutils | [] [] | + radius | [] [] | + recode | [] [] [] [] [] [] [] [] | + rosegarden | () () () () () | + rpm | [] [] | + rush | | + sarg | [] | + screem | [] [] | + scrollkeeper | [] [] [] [] | + sed | [] [] [] [] [] [] [] [] | + sharutils | [] [] [] [] [] [] [] | + shishi | [] | + skencil | [] | + solfege | [] [] [] [] | + solfege-manual | [] [] | + soundtracker | [] [] | + sp | [] () | + sysstat | [] [] [] [] [] | + tar | [] [] [] [] [] [] [] | + texinfo | [] [] [] [] | + tin | [] | + unicode-han-tra... | | + unicode-transla... | [] [] | + util-linux-ng | [] [] [] [] [] [] | + vice | () () () | + vmm | [] | + vorbis-tools | [] | + wastesedge | () () | + wdiff | [] | + wget | [] [] [] [] [] [] [] [] | + wyslij-po | [] [] [] | + xchat | [] [] [] [] [] [] [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] [] | + +----------------------------------------------------+ + fi fr ga gl gu he hi hr hu hy id is it ja ka kn + 105 121 53 20 4 8 3 5 53 2 120 5 84 67 0 4 + + ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne + +-----------------------------------------------+ + a2ps | [] | + aegis | | + ant-phone | | + anubis | [] [] | + aspell | [] | + bash | | + bfd | | + bibshelf | [] [] | + binutils | | + bison | [] | + bison-runtime | [] [] [] [] [] | + bluez-pin | [] [] [] [] [] | + bombono-dvd | | + buzztard | | + cflow | | + clisp | | + coreutils | [] | + cpio | | + cppi | | + cpplib | | + cryptsetup | | + dfarc | [] | + dialog | [] [] [] [] [] | + dico | | + diffutils | [] [] | + dink | | + doodle | | + e2fsprogs | | + enscript | | + exif | [] | + fetchmail | | + findutils | | + flex | | + freedink | [] | + gas | | + gawk | | + gcal | | + gcc | | + gettext-examples | [] [] [] [] | + gettext-runtime | [] | + gettext-tools | [] | + gip | [] [] | + gjay | | + gliv | | + glunarclock | [] | + gnubiff | | + gnucash | () () () () | + gnuedu | | + gnulib | | + gnunet | | + gnunet-gtk | | + gnutls | [] | + gold | | + gpe-aerial | [] | + gpe-beam | [] | + gpe-bluetooth | [] [] | + gpe-calendar | [] | + gpe-clock | [] [] [] [] [] | + gpe-conf | [] [] | + gpe-contacts | [] [] | + gpe-edit | [] | + gpe-filemanager | [] [] | + gpe-go | [] [] [] | + gpe-login | [] | + gpe-ownerinfo | [] [] | + gpe-package | [] [] | + gpe-sketchbook | [] [] | + gpe-su | [] [] [] [] [] [] | + gpe-taskmanager | [] [] [] [] [] [] | + gpe-timesheet | [] [] | + gpe-today | [] [] [] [] | + gpe-todo | [] [] | + gphoto2 | | + gprof | [] | + gpsdrive | | + gramadoir | | + grep | | + grub | | + gsasl | | + gss | | + gst-plugins-bad | [] [] [] [] | + gst-plugins-base | [] [] | + gst-plugins-good | [] [] | + gst-plugins-ugly | [] [] [] [] [] | + gstreamer | | + gtick | | + gtkam | [] | + gtkorphan | [] [] | + gtkspell | [] [] [] [] [] [] [] | + gutenprint | | + hello | [] [] [] | + help2man | | + hylafax | | + idutils | | + indent | | + iso_15924 | [] [] | + iso_3166 | [] [] () [] [] [] [] [] | + iso_3166_2 | | + iso_4217 | [] [] | + iso_639 | [] [] | + iso_639_3 | [] | + jwhois | [] | + kbd | | + keytouch | [] | + keytouch-editor | [] | + keytouch-keyboa... | [] | + klavaro | [] | + latrine | [] | + ld | | + leafpad | [] [] [] | + libc | [] | + libexif | | + libextractor | | + libgnutls | [] | + libgpewidget | [] [] | + libgpg-error | | + libgphoto2 | | + libgphoto2_port | | + libgsasl | | + libiconv | | + libidn | | + lifelines | | + liferea | | + lilypond | | + linkdr | | + lordsawar | | + lprng | | + lynx | | + m4 | | + mailfromd | | + mailutils | | + make | [] | + man-db | | + man-db-manpages | | + minicom | [] | + mkisofs | | + myserver | | + nano | [] [] | + opcodes | | + parted | | + pies | | + popt | [] [] [] | + psmisc | | + pspp | | + pwdutils | | + radius | | + recode | | + rosegarden | | + rpm | | + rush | | + sarg | | + screem | | + scrollkeeper | [] [] | + sed | | + sharutils | | + shishi | | + skencil | | + solfege | [] | + solfege-manual | | + soundtracker | | + sp | | + sysstat | [] | + tar | [] | + texinfo | [] | + tin | | + unicode-han-tra... | | + unicode-transla... | | + util-linux-ng | | + vice | | + vmm | | + vorbis-tools | | + wastesedge | | + wdiff | | + wget | [] | + wyslij-po | | + xchat | [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] | + +-----------------------------------------------+ + ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne + 20 5 10 1 13 48 4 2 2 4 24 10 20 3 1 + + nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr + +---------------------------------------------------+ + a2ps | [] [] [] [] [] [] [] [] | + aegis | [] [] [] | + ant-phone | [] [] | + anubis | [] [] [] | + aspell | [] [] [] [] [] | + bash | [] [] | + bfd | [] | + bibshelf | [] [] | + binutils | [] [] | + bison | [] [] [] | + bison-runtime | [] [] [] [] [] [] [] | + bluez-pin | [] [] [] [] [] [] [] [] | + bombono-dvd | [] () | + buzztard | [] [] | + cflow | [] | + clisp | [] [] | + coreutils | [] [] [] [] [] [] | + cpio | [] [] [] | + cppi | [] | + cpplib | [] | + cryptsetup | [] | + dfarc | [] | + dialog | [] [] [] [] | + dico | [] | + diffutils | [] [] [] [] [] [] | + dink | () | + doodle | [] [] | + e2fsprogs | [] [] | + enscript | [] [] [] [] [] | + exif | [] [] [] () [] | + fetchmail | [] [] [] [] | + findutils | [] [] [] [] [] | + flex | [] [] [] [] [] | + freedink | [] [] | + gas | | + gawk | [] [] [] [] | + gcal | | + gcc | [] | + gettext-examples | [] [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] [] [] [] | + gettext-tools | [] [] [] [] [] [] | + gip | [] [] [] [] [] | + gjay | | + gliv | [] [] [] [] [] [] | + glunarclock | [] [] [] [] [] | + gnubiff | [] () | + gnucash | [] () () () | + gnuedu | [] | + gnulib | [] [] [] [] | + gnunet | | + gnunet-gtk | | + gnutls | [] [] | + gold | | + gpe-aerial | [] [] [] [] [] [] [] | + gpe-beam | [] [] [] [] [] [] [] | + gpe-bluetooth | [] [] | + gpe-calendar | [] [] [] [] | + gpe-clock | [] [] [] [] [] [] [] [] | + gpe-conf | [] [] [] [] [] [] [] | + gpe-contacts | [] [] [] [] [] | + gpe-edit | [] [] [] | + gpe-filemanager | [] [] [] | + gpe-go | [] [] [] [] [] [] [] [] | + gpe-login | [] [] | + gpe-ownerinfo | [] [] [] [] [] [] [] [] | + gpe-package | [] [] | + gpe-sketchbook | [] [] [] [] [] [] [] | + gpe-su | [] [] [] [] [] [] [] [] | + gpe-taskmanager | [] [] [] [] [] [] [] [] | + gpe-timesheet | [] [] [] [] [] [] [] [] | + gpe-today | [] [] [] [] [] [] [] [] | + gpe-todo | [] [] [] [] [] | + gphoto2 | [] [] [] [] [] [] [] [] | + gprof | [] [] [] | + gpsdrive | [] [] | + gramadoir | [] [] | + grep | [] [] [] [] | + grub | [] [] [] | + gsasl | [] [] [] [] | + gss | [] [] [] | + gst-plugins-bad | [] [] [] [] [] [] | + gst-plugins-base | [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] | + gtick | [] [] [] | + gtkam | [] [] [] [] [] [] | + gtkorphan | [] | + gtkspell | [] [] [] [] [] [] [] [] [] [] | + gutenprint | [] [] | + hello | [] [] [] [] | + help2man | [] [] | + hylafax | [] | + idutils | [] [] [] [] [] | + indent | [] [] [] [] [] [] [] | + iso_15924 | [] [] [] [] | + iso_3166 | [] [] [] [] [] () [] [] [] [] [] [] [] [] | + iso_3166_2 | [] [] [] | + iso_4217 | [] [] [] [] [] [] [] [] | + iso_639 | [] [] [] [] [] [] [] [] [] | + iso_639_3 | [] [] | + jwhois | [] [] [] [] | + kbd | [] [] [] | + keytouch | [] [] [] | + keytouch-editor | [] [] [] | + keytouch-keyboa... | [] [] [] | + klavaro | [] [] | + latrine | [] [] | + ld | | + leafpad | [] [] [] [] [] [] [] [] [] | + libc | [] [] [] [] | + libexif | [] [] () [] | + libextractor | | + libgnutls | [] [] | + libgpewidget | [] [] [] | + libgpg-error | [] [] | + libgphoto2 | [] [] | + libgphoto2_port | [] [] [] [] [] | + libgsasl | [] [] [] [] [] | + libiconv | [] [] [] [] [] | + libidn | [] [] | + lifelines | [] [] | + liferea | [] [] [] [] [] () () [] | + lilypond | [] | + linkdr | [] [] [] | + lordsawar | | + lprng | [] | + lynx | [] [] [] | + m4 | [] [] [] [] [] | + mailfromd | [] | + mailutils | [] | + make | [] [] [] [] | + man-db | [] [] [] | + man-db-manpages | [] [] [] | + minicom | [] [] [] [] | + mkisofs | [] [] [] | + myserver | | + nano | [] [] [] [] | + opcodes | [] [] | + parted | [] [] [] [] | + pies | [] | + popt | [] [] [] [] | + psmisc | [] [] [] | + pspp | [] [] | + pwdutils | [] | + radius | [] [] [] | + recode | [] [] [] [] [] [] [] [] | + rosegarden | () () | + rpm | [] [] [] | + rush | [] [] | + sarg | | + screem | | + scrollkeeper | [] [] [] [] [] [] [] [] | + sed | [] [] [] [] [] [] [] [] [] | + sharutils | [] [] [] [] | + shishi | [] | + skencil | [] [] | + solfege | [] [] [] [] | + solfege-manual | [] [] [] | + soundtracker | [] | + sp | | + sysstat | [] [] [] [] | + tar | [] [] [] [] | + texinfo | [] [] [] [] | + tin | [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux-ng | [] [] [] [] [] | + vice | [] | + vmm | [] | + vorbis-tools | [] [] | + wastesedge | [] | + wdiff | [] [] | + wget | [] [] [] [] [] [] [] | + wyslij-po | [] [] [] | + xchat | [] [] [] [] [] [] [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] | + +---------------------------------------------------+ + nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr + 135 10 4 7 105 1 29 62 47 91 3 54 46 9 37 + + sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW + +---------------------------------------------------+ + a2ps | [] [] [] [] [] | 27 + aegis | [] | 9 + ant-phone | [] [] [] [] | 9 + anubis | [] [] [] [] | 15 + aspell | [] [] [] | 20 + bash | [] [] [] | 12 + bfd | [] | 6 + bibshelf | [] [] [] | 16 + binutils | [] [] | 8 + bison | [] [] | 12 + bison-runtime | [] [] [] [] [] [] | 29 + bluez-pin | [] [] [] [] [] [] [] [] | 37 + bombono-dvd | [] | 4 + buzztard | [] | 7 + cflow | [] [] [] | 9 + clisp | | 10 + coreutils | [] [] [] [] | 22 + cpio | [] [] [] [] [] [] | 13 + cppi | [] [] | 5 + cpplib | [] [] [] [] [] [] | 14 + cryptsetup | [] [] | 7 + dfarc | [] | 9 + dialog | [] [] [] [] [] [] [] | 30 + dico | [] | 2 + diffutils | [] [] [] [] [] [] | 30 + dink | | 4 + doodle | [] [] | 7 + e2fsprogs | [] [] [] | 11 + enscript | [] [] [] [] | 17 + exif | [] [] [] | 16 + fetchmail | [] [] [] | 17 + findutils | [] [] [] [] [] | 20 + flex | [] [] [] [] | 15 + freedink | [] | 10 + gas | [] | 4 + gawk | [] [] [] [] | 18 + gcal | [] [] | 5 + gcc | [] [] [] | 7 + gettext-examples | [] [] [] [] [] [] [] | 34 + gettext-runtime | [] [] [] [] [] [] [] | 29 + gettext-tools | [] [] [] [] [] [] | 22 + gip | [] [] [] [] | 22 + gjay | [] | 3 + gliv | [] [] [] | 14 + glunarclock | [] [] [] [] [] | 19 + gnubiff | [] [] | 4 + gnucash | () [] () [] () | 10 + gnuedu | [] [] | 7 + gnulib | [] [] [] [] | 16 + gnunet | [] | 1 + gnunet-gtk | [] [] [] | 5 + gnutls | [] [] [] | 10 + gold | [] | 4 + gpe-aerial | [] [] [] | 18 + gpe-beam | [] [] [] | 19 + gpe-bluetooth | [] [] [] | 13 + gpe-calendar | [] [] [] [] | 12 + gpe-clock | [] [] [] [] [] | 28 + gpe-conf | [] [] [] [] | 20 + gpe-contacts | [] [] [] | 17 + gpe-edit | [] [] [] | 12 + gpe-filemanager | [] [] [] [] | 16 + gpe-go | [] [] [] [] [] | 25 + gpe-login | [] [] [] | 11 + gpe-ownerinfo | [] [] [] [] [] | 25 + gpe-package | [] [] [] | 13 + gpe-sketchbook | [] [] [] | 20 + gpe-su | [] [] [] [] [] | 30 + gpe-taskmanager | [] [] [] [] [] | 29 + gpe-timesheet | [] [] [] [] [] | 25 + gpe-today | [] [] [] [] [] [] | 30 + gpe-todo | [] [] [] [] | 17 + gphoto2 | [] [] [] [] [] | 24 + gprof | [] [] [] | 15 + gpsdrive | [] [] [] | 11 + gramadoir | [] [] [] | 11 + grep | [] [] [] | 10 + grub | [] [] [] | 14 + gsasl | [] [] [] [] | 14 + gss | [] [] [] | 11 + gst-plugins-bad | [] [] [] [] | 26 + gst-plugins-base | [] [] [] [] [] | 24 + gst-plugins-good | [] [] [] [] | 24 + gst-plugins-ugly | [] [] [] [] [] | 29 + gstreamer | [] [] [] [] | 22 + gtick | [] [] [] | 13 + gtkam | [] [] [] | 20 + gtkorphan | [] [] [] | 14 + gtkspell | [] [] [] [] [] [] [] [] [] | 45 + gutenprint | [] | 10 + hello | [] [] [] [] [] [] | 21 + help2man | [] [] | 7 + hylafax | [] | 5 + idutils | [] [] [] [] | 17 + indent | [] [] [] [] [] [] | 30 + iso_15924 | () [] () [] [] | 16 + iso_3166 | [] [] () [] [] () [] [] [] () | 53 + iso_3166_2 | () [] () [] | 9 + iso_4217 | [] () [] [] () [] [] | 26 + iso_639 | [] [] [] () [] () [] [] [] [] | 38 + iso_639_3 | [] () | 8 + jwhois | [] [] [] [] [] | 16 + kbd | [] [] [] [] [] | 15 + keytouch | [] [] [] | 16 + keytouch-editor | [] [] [] | 14 + keytouch-keyboa... | [] [] [] | 14 + klavaro | [] | 11 + latrine | [] [] [] | 10 + ld | [] [] [] [] | 11 + leafpad | [] [] [] [] [] [] | 33 + libc | [] [] [] [] [] | 21 + libexif | [] () | 7 + libextractor | [] | 1 + libgnutls | [] [] [] | 9 + libgpewidget | [] [] [] | 14 + libgpg-error | [] [] [] | 9 + libgphoto2 | [] [] | 8 + libgphoto2_port | [] [] [] [] | 14 + libgsasl | [] [] [] | 13 + libiconv | [] [] [] [] | 21 + libidn | () [] [] | 11 + lifelines | [] | 4 + liferea | [] [] [] | 21 + lilypond | [] | 7 + linkdr | [] [] [] [] [] | 17 + lordsawar | | 1 + lprng | [] | 3 + lynx | [] [] [] [] | 17 + m4 | [] [] [] [] | 19 + mailfromd | [] [] | 3 + mailutils | [] | 5 + make | [] [] [] [] | 21 + man-db | [] [] [] | 8 + man-db-manpages | | 4 + minicom | [] [] | 16 + mkisofs | [] [] | 9 + myserver | | 0 + nano | [] [] [] [] | 21 + opcodes | [] [] [] | 11 + parted | [] [] [] [] [] | 15 + pies | [] [] | 3 + popt | [] [] [] [] [] [] | 27 + psmisc | [] [] | 11 + pspp | | 4 + pwdutils | [] [] | 6 + radius | [] [] | 9 + recode | [] [] [] [] | 28 + rosegarden | () | 0 + rpm | [] [] [] | 11 + rush | [] [] | 4 + sarg | | 1 + screem | [] | 3 + scrollkeeper | [] [] [] [] [] | 27 + sed | [] [] [] [] [] | 30 + sharutils | [] [] [] [] [] | 22 + shishi | [] | 3 + skencil | [] [] | 7 + solfege | [] [] [] [] | 16 + solfege-manual | [] | 8 + soundtracker | [] [] [] | 9 + sp | [] | 3 + sysstat | [] [] | 15 + tar | [] [] [] [] [] [] | 23 + texinfo | [] [] [] [] [] | 17 + tin | | 4 + unicode-han-tra... | | 0 + unicode-transla... | | 2 + util-linux-ng | [] [] [] [] | 20 + vice | () () | 1 + vmm | [] | 4 + vorbis-tools | [] | 6 + wastesedge | | 2 + wdiff | [] [] | 7 + wget | [] [] [] [] [] | 26 + wyslij-po | [] [] | 8 + xchat | [] [] [] [] [] [] | 36 + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] | 63 + xkeyboard-config | [] [] [] | 22 + +---------------------------------------------------+ + 85 teams sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW + 178 domains 119 1 3 3 0 10 65 51 155 17 98 7 41 2618 + + Some counters in the preceding matrix are higher than the number of +visible blocks let us expect. This is because a few extra PO files are +used for implementing regional variants of languages, or language +dialects. + + For a PO file in the matrix above to be effective, the package to +which it applies should also have been internationalized and +distributed as such by its maintainer. There might be an observable +lag between the mere existence a PO file and its wide availability in a +distribution. + + If June 2010 seems to be old, you may fetch a more recent copy of +this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date +matrix with full percentage details can be found at +`http://translationproject.org/extra/matrix.html'. + +1.5 Using `gettext' in new packages +=================================== + +If you are writing a freely available program and want to +internationalize it you are welcome to use GNU `gettext' in your +package. Of course you have to respect the GNU Library General Public +License which covers the use of the GNU `gettext' library. This means +in particular that even non-free programs can use `libintl' as a shared +library, whereas only free software can use `libintl' as a static +library or use modified versions of `libintl'. + + Once the sources are changed appropriately and the setup can handle +the use of `gettext' the only thing missing are the translations. The +Free Translation Project is also available for packages which are not +developed inside the GNU project. Therefore the information given above +applies also for every other Free Software Project. Contact +`coordinator@translationproject.org' to make the `.pot' files available +to the translation teams. + diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..e03b84c --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Daniel Nöthen (butt@danielnoethen.de) diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..c339803 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,555 @@ + +Version 1.45.0 (2025-04-19) +--------------------------- +* Add support for custom URLs and mountpoints for listener statistics +* Add seperate MIDI commands for START/STOP Broadcasting and Recording +* Add support for controlling BUTT via MIDI NOTE_ON messages +* Fix a crash when connecting to a Shoutcast server that is configued with streamhidestats=all +* Fix an issue where "Listeners: 0" was shown after connecting to servers that don’t provide listener statistics +* Fix several German translation issues +* Update credentials for existing radio.co servers when re-adding them + + +Version 1.44.0-1 (2025-01-17) +----------------------------- +The following change does only apply to the Linux source tar ball: + +* Fix a compilation error if --disable-aac is passed to the configure script + +Version 1.44.0 (2024-12-03) +--------------------------- +* BUTT can now request the current song from an URL (website) +* It is now possible to instruct BUTT to overwrite existing recordings +* Add a new display mode which shows "On Air" and if available the current listeners +* Fix memory corruption after canceling a connection attempt when using a different application language than English +* Improve compatibility of UTF-8 in song names with some servers by making the update request compliant to RFC3986 +* Increase font size of the "Listeners" label to improve readability from far distances +* Change the default answer from "Yes" to "Cancel" when asked to overwrite existing recordings to prevent accidental overwriting of existing recordings + +Version 1.43.0 (2024-08-05) +--------------------------- +* Recording: When file splitting is active, no samples between files are lost anymore +* Recording: Fix compatibility issue with older MP3 decoders +* Improve song update for Opus streams +* Add more advanced MP3 encoder options: + - Force minimum VBR bitrate + - low-/highpass cutoff frequency + - low-/highpass width + - Resampling +* Allow the user to pass floating point values like 0.5 to the -m/-M/-o/-O commands +* Fix crash when connecting to an icecast server if the description field of the ICY information is empty +* Fix an issue with Let's Encrypt TLS certificates +* Fix an issue that can cause a connection attempt not to be canceled by a single stop button press + +Version 1.42.0 (2024-05-25) +--------------------------- +* Add WebRTC (WHIP) support (Thanks to Matt from codec.live) +* Add setting to define the listeners update interval +* Include ice-bitrate property to the HTTP header so the icecast status page shows the stream bit rate +* Fix "Update devices" button +* Improve VU-meter visibility +* Let the user select the VU-meter colors and thresholds +* Use momentary peak for the peak hold bar instead of an average peak +* Assure that the signal detection still works after a recording failed to start +* The threshold time for automatic streaming/recording can now be as low as 0.1 seconds +* The signal detection level is now always based on the stream volume +* Activating automatic streaming/recording did not work if the threshold time was set to 0 seconds +* Reduce CPU usage on macOS +* Pressing CMD+q on macOS now closes BUTT +* Add a "manual" and "YouTube" button to the settings window for easier access +* Make it easier for the user to go to the AAC install instructions after selecting the AAC codec +* Improve the order of GUI element selection when pressing the tab key + + +Version 1.41.1 (2024-04-25) +--------------------------- +* Important: Fix a bug that could result in a corrupted configuration file after adding a server or stream info +* Change versioning scheme to account for bugfix-only releases + +Version 0.1.41 (2024-03-17) +--------------------------- +* Add support for controlling BUTT via MIDI CC messages +* EQ and compressor can now be enabled independently for the stream and record path +* You can now use %N as a placeholder for the current server name in your record file/path +* Prevent BUTT from being disconnected by the server when using FLAC and the audio signal is 100% silent +* The signal and silence detection can now by activated/deactivated with a checkbox instead of simply setting the value to 0 +* Add -L parameter to get a list of available audio devices +* The ICY name and ICY description now support the same placeholders as the record file/path (activate the "expand variables" checkbox) +* Add Arabic language support (Thanks to Magd) +* Fix an issue that could lead BUTT to freeze on startup if no internet connection is available +* Overall stability improvements + +Version 0.1.40 (2023-11-24) +--------------------------- +* Support higher bitrates for AAC, Vorbis and Opus +* Add support for Plexamp on Linux +* Add Dutch language support (thanks to Timothy) +* Fix an issue with audio device names that contain special characters +* Fix possible buffer underflow when the connection to a shoutcast server fails + +Version 0.1.39 (2023-09-20) +--------------------------- +* Fix a bug that can cause the listener count to no longer be updated +* Fix a bug that can cause the split record file function to stop working +* Fix a bug that can cause butt not to reconnect after a connection loss +* Fix a bug that can cause undefined behaviour +* Clear song name if song file is empty + + +Version 0.1.38 (2023-08-05) +--------------------------- +* Users can now define a custom window title +* Add option to set a delay between automatic reconnects +* Add option to use the older Icecast SOURCE protocol instead of the newer PUT protocol +* Increase robustness of the config file importer +* Increase robustness of the show listeners function +* Use green instead of yellow to indicate a valid streaming connection +* Fix memory leak when using Icecast and showing the number of listeners +* Fix UI drawing issues +* Fix issue with the main window size on Windows 11 +* Fix issues with the tray agent on Windows + +Version 0.1.37 (2022-12-24) +--------------------------- +* Add support for a second audio device +* Streaming and recording volume can be set independently +* Add support for icecast-kh listener statistics +* Highlight connect and record buttons when active +* Restore window size if "Remember main window position" is active +* Increase size of slider knobs +* Start with default values in case the config file is damaged +* Always overwrite existing files when recording is started automatically or via butt client +* Do not stop recording if a butt client sends a disconnect command while butt is offline +* Fix an issue were butt mistakenly says "Connecting..." +* Fix memory leak if "Show listeners" is activate + +Version 0.1.36 (2022-10-03) +--------------------------- +* Number of current listeners can be displayed on the LCD (works only with original Icecast and Shoutcast implementations) +* Fix connection issue with AIS streaming server +* Fix connection issue with Icecast servers older than version 2.4.0 +* Fix issue with Shoutcast if mountpoint is already in use + + +Version 0.1.35 (2022-06-19) +--------------------------- +* Gain slider can be disabled to prevent inadvertently changing the volume +* Audio device initialization can be skipped by holding down CTRL during startup +* Fix crash if audio device can not be opened +* Fix crash if no default audio device can be found +* Fix wrong password detection for certain liquidsoap Shoutcast implementations +* Fix crash of command client and command server when very long song names are specified + +Version 0.1.34 (2022-04-21) +--------------------------- +* Added equalizer presets +* Added Spanish translation +* Use 32 bit float for internal audio processing instead of 16 bit integer +* FLAC can now be broadcasted and recorded as 16 bit or 24 bit +* WAV can now be recorded as 16 bit, 24 bit or 32 bit +* Massively improved client/server implementation for butt commands +* Fixed bug that caused overwriting the first wav samples of a recording +* Fixed read song name from Music.app for MacOS >= 11.0 +* Fixed record folder creation if folder contains format variables +* butt commands can now also be sent via UDP +* Added new fields to the server status message: + - stream seconds, stream kBytes + - record seconds, record kBytes + - volume left/right + - current song + - record path + +Version 0.1.33 (2022-02-06) +--------------------------- +* Windows: You can broadcast what's playing on your computer (audio device must support WASAPI) +* Windows/Linux: New butt-client for controlling running butt instances (Thanks to Hossam) +* Added support for higher samplerates (88.2 kHz and 96 kHz) +* Added Portuguese (Brazil) translation (Thanks to Bruno) +* Added signal and silence detection flags to the status information +* Time thresholds for signal detection can be changed via control commands (Thanks to Hossam) +* Format place holders (%Y %m %d etc.) can also be used in the folder name +* Song title update support for OPUS +* Fixed wrong file size in wav header +* Fixed compilation if --disable-ssl or --disable-aac was passed to ./configure + +Version 0.1.32 (2021-10-28) +--------------------------- +* Radio.co stations can now be easily added to butt +* Advanced codec settings for mp3, aac, ogg/vorbis and opus can now be adjusted +* The recordings folder may now contain environment variables like ~, $HOME and %USERPROFILE% +* Fixed issue with characters like $,%,&,§ in the song name +* Fixed connection issue in case the server domain has IPv4+6 addresses but Icecast is only listening on IPv4 +* Fixed missing song duration information in FLAC recordings + +Version 0.1.31 (2021-07-12) +--------------------------- +* A delay can now be added to the automatic song title update +* Increased equalizer from 5 to 10 frequency bands +* Fixed positioning issues on multi screen setups +* Maximum number of supported audio devices has been increased from 100 to 256 + +Version 0.1.30 (2021-05-14) +--------------------------- +* Added support for IPv6 +* Added French translation +* Right click on a slider knob brings up an input field where you can type in the slider value with the keyboard +* The selected audio device can now be remembered by device name instead by device id +* You can now rescan for new audio devices manually (no butt restart needed anymore after plugging in a new audio device) +* Holding the shift key during butt startup allows you to start with a fresh configuration file +* Updated Portaudio to version v19.7.0 +* Windows: Added support for WASAPI audio driver +* MacOS: Updated FLTK to version 1.3.6 +* MacOS: Native support for Apple Silicon (arm64) + +Version 0.1.29 (2021-03-28) +--------------------------- +* Added a new tool (butt Agent) which helps to minimize butt to tray and much more (Big thanks to Ivan Radolovic) +* Added an indicator to the compressor which lights up if the threshold is exceeded +* Added "Aggressive Mode" to the compressor. If activated, the signal power for threshold detection is not averraged +* Added new command line options: -q (quit) -n (split recording) -u (update song name) +* Added donation addresses for Bitcoin, Monero and Dash +* Fixed crash when butt can not find any input channels +* Fixed crash when reading song names from an UTF-8 formatted file that contains a BOM +* Fixed issue with icecast-kh14+ when connecting to a mountpoint which is already in use +* Fixed issue if both checkboxes "start recording after launch" and "start recording when connected" are checked +* Fixed butt.desktop file. Icon was not shown on GNOME panel +* Attack and Release compressor labels now have 2 decimal places instead of only 1 +* butt does not send bitrate information to the icecast server anymore if FLAC is used +* butt now searches for a free command server port if default port is already in use +* butt can now be started in minimized state +* The recording file name can now contain any well known date format specifier +* The window class name has been renamed from FLTK to butt_FLTK + +Version 0.1.28 (2021-02-07) +--------------------------- +* Fixed compressor issues +* Fixed song update when using Strawberry audio player +* The order of song update from an music app can be changed from "Title - Artist" to "Artist - Title" +* Increased accuracy of recording split timer +* VU-meter appearance can be changed to solid colors for better readability +* Log window can be vertically resized +* Windows: Changed default installation folder to %LOCALAPPDATA%\butt instead of %LOCALAPPDATA\butt- + + +Version 0.1.27 (2020-12-26) +--------------------------- +* Fixed loading of AAC codec selection from configuration file +* Fixed crash when using opus with a samplerate not equal to 48000 Hz + +Version 0.1.26 (2020-12-24) +--------------------------- +* Added ASIO support +* Added support for multi-channel audio devices +* Added multi-language support (i18n) +* Added German translation +* Added option to force reconnection regardless of the server response +* Added support for Strawberry audio player (Thanks to Stefan S.) +* Added config parameter to disable dithering (set disable_dithering=1 in cfg file) +* Fixed possible crash if server is not reachable +* Fixed possible crash when reconnecting +* Fixed possible crash when using FLAC and song update +* Fixed unwanted rounding of compressor values +* Fixed overwriting of a DSP setting if it was set to -1.0 +* Improved CPU usage +* Improved mono/stereo handling +* Improved overall song update implementation +* Compiles on FreeBSD (Thanks to Per G. and Tobias C. B.) + + +Version 0.1.25 (2020-10-26) +--------------------------- +* Added the ability to extend the song name with a prefix and a suffix +* Fixed issue with automatic song update from text files +* Fixed recording in FLAC + +Version 0.1.24 (2020-10-14) +--------------------------- +* VU-meter has been redesigned +* Fixed issues with usernames that contain special characters +* The port of the command server can be specified via command line +* Commands can be received via network +* It is possible to connect to a particular streaming server when sending the connect command +* You can ask a butt instance about its current status with the -S command +* butt can automatically check for updates after launch +* Update of song name works with FLAC +* Thresholds for signal detection can be specified +* Added -h command line option to get an overview of all available commands +* Updated the manual + +Version 0.1.23 (2020-09-27) +--------------------------- +* Fixed crash if the server is not reachable (e.g. unstable internet connections) +* Fixed issue with transfering song meta data from music apps to butt (MacOS) +* Improved handling of mic permissions dialog on MacOS + +Version 0.1.22 (2020-07-09) +--------------------------- +* Added Dynamic Range Compressor (thanks to Thomas P.) +* Added ability to check for new versions +* butt can now be controlled via command line +* Replaced experimental portaudio version with the stable portaudio version +* Fixed issue with stereo audio when using the Equalizer (thanks to Thomas P.) +* Fixed traffic calculation when using OPUS +* Fixed issue with OPUS encoding under some circumstances + +Version 0.1.21 (2020-05-26) +--------------------------- +* Streaming and recording can now be started automatically if an audio signal is present +* Fixed reconnection issue on unreliable network connections. Should now behave like 0.1.19 again +* wav recordings can now be up to 4 GB large +* Removed advanced section from the Audio tab. Buffer time can still be set in the configuration file if you need to + +Version 0.1.20 (2020-04-21) +--------------------------- +* Added SSL/TLS support for icecast +* Recording can now automatically be stopped if the user disconnects from the server +* Fixed icecast connection issue (mostly occurring on mobile internet connections like 4G/LTE) +* Fixed wrong password detection for liquidsoap based setups +* Fixed configuration export on MacOS +* Fixed logfile selection on MacOS +* Song name is not updated on reconnect anymore if the manual song name input field has been cleared +* Upgraded FLTK to version 1.3.5 + +Version 0.1.19 (2019-12-30) +--------------------------- +* The song name can now be read from the last line instead from the first line of a file +* Streaming and recording can now be automatically stopped after silence has been detected +* The last window position can be remembered. Useful when running multiple instances +* butt can now be started with hidden info window +* The vu-meter runs smoother and needs less cpu +* VU-meter peak hold is only active for the red light +* Closing butt while streaming or recording must be confirmed now +* Changes are now saved without asking for confirmation when closing the app +* Removed a new line character from the server name in the title bar +* Fixed recceiving song information from iTunes/Music in MacOS Catalina +* Fixed wrong counting of sent bytes when using AAC + + +Version 0.1.18 (2019-05-12) +--------------------------- +* Added support for automatic recording after starting butt +* Enabled AAC afterburner (improves audio quality) +* Fixed issue with configure.ac and s390x architecture +* Updated the FSF address in COPYING +* AAC libs are not delivered with the setup files anymore (read the manual on how to activate AAC support again) + + +Version 0.1.17 (2018-12-27) +--------------------------- +* Added support for FLAC streaming (icecast only) +* Added 5-band equalizer (thanks to Melchor Garau Madrigal) +* Added the ability to read song informations from several apps on MacOS and Linux (thanks to Melchor Garau Madrigal) +* Window title is automatically renamed to the connected server (useful when running multiple instances) +* Fixed connection issue with airtime +* Fixed integer overflow when gain is set too high +* Fixed compilation error on ubuntu 18 +* Changed color of windows icon from black to yellow. So people using Win10 can now find butt in their black taskbar ;-) + + +Version 0.1.16 (2017-09-17) +--------------------------- +* Fixed compatibility issues with shoutcast v2.5.5.732 +* Replaced portaudio by newest stable version v190600_20161030 +* When using AAC+ the best AAC profile for the current bitrate is selected automatically + + AAC+v2: bitrate < 48kBit/s (aac_aot = 29) + + AAC+v1: 48 kBit/s \<= bitrate < 96kBit/s (aac_aot = 5) + + AAC-LC: bitrate >= 96kBit/s (aac_aot = 2) + +* You can force the AAC codec to a specific profile by setting + aac_overwrite_aot = 1 and aac_aot to the appropriate aot value {2,5,29} in buttrc + + +Version 0.1.15 (2016-05-28) +--------------------------- +* Added AAC+ support +* Added a "Split now" button to instantly start a new recording file +* Improved look&feel on retina displays on OSX +* Improved compatibility with proxies/load balancers (thanks to boyska) +* Fixed handling of newline characters when reading the song name file +* Fixed evlauation of time/date variables when automatic file splitting is enabled +* Fixed compatibility with airtime servers +* Fixed ogg and opus support for ShoutCast + +Version 0.1.14 (2014-12-27) +--------------------------- +* Added FLAC support for recording +* Added Opus support (thanks to oneman) +* Added logfile support (thanks to mikko) +* Added support for more variables in the filename (%H %M %S) (thanks to mikko) +* Automatic file splitting can be synced to full hour now (thanks to mikko) +* LCD info can automatically rotate every 5 seconds now (thanks to mikko) +* Added ability to change audio buffer size +* Uncluttered LCD (thanks to mikko) +* File extension of record filename gets automatically updated now +* Dropped support of different samplerate/channels for stream and record +* Resorted settings elements/widgets +* Removed possible memleaks +* Connecting to an unreachable server does not freeze the GUI anymore +* Fixed icecast and shoutcast meta data handling +* ;ade update song from file more robust +* "update song name manually" reacts on Enter button now + +Version 0.1.13 (2014-05-02) +--------------------------- +* Has an icon now! - Thanks to Subrat (ipapuna) Nayak +* Added support for lower bitrates (24k, 16k, 8k) +* Added support for user defined configuration path e.g. "butt -c " +* Added support for user names in Icecast +* Added gain slider. This slider multiplies the audio input samples with the given factor +* Added .manifest file to disable the VirtualStore on Windows Vista and higher +* Added the ability to automatically split the recording every 'n' minutes +* Added feature for importing and exporting configuration files +* Compiles with Xcode 5 on OS X Mavericks +* Compiles with traditional GNU autoconf/automake environment on linux and mingw +* Improved robustness against faulty config files +* Improved compatibility to ShoutCast v2 servers +* Improved look&feel +* Fixed samplerate issues +* Fixed mono playback/recording +* Changed data volume information vom kBytes to MBytes +* Changed default recording path to users home folder +* Sends audio information (bitrate etc.) to Icecast server - Thanks to Dominik Durner +* Reimplemented VU-Meter with peak hold +* Comes with as an ubuntu package +* Windows: can be installed as user without admin rights +* Windows: uninstallation process also removes the configuration file +* Instead of canceling the automatic song update in case the given file is not +readable, butt now tries to reread the file every 5 seconds + +Version 0.1.12 (2010-04-10) +--------------------------- +* butt is now able to connect automatically after startup +* Shortened time between connect attempts (fixes Shouted.FM connection problems) +* Improved wrong password detection for shoutcast + +Version 0.1.11-2 (2008-12-14) +----------------------------- +* Fixed display info after automatic reconnection + +Version 0.1.11-1 (2008-11-09) +----------------------------- +* Fixed segfault if there is no '.' in the filename + +Version 0.1.11 (2008-10-26) +--------------------------- +* Fixed unintended disconnects +* Fixed recording problems +* Removed buffer overrun messages +* Recording can be now stopped with the stop-button +* Replaced pcm recording by wav recording +* Recording as ogg is now possible +* Added "stay on top" checkbox +* Fixed possible crash when changing mp3 settings while streaming + +Version 0.1.10 (2008-05-25) +--------------------------- +* Removed xrun "led". Instead the msg window informs the user about overruns +* Added dB values to the vu-meter +* Fixed bitrate/samplerate selection for ogg +* Network backend works with non-blocking sockets now +* libshout is not needed anymore +* Songname can be updated from a textfile now +* More samplerates are supported now +* Fixed samplerate selection problems +* Fixed crash when connecting to icecast server on MacOS 10.4 +* Fixed crash when changing the server type from shoutcast to icecast +* Some cosmetic changes (buttons, LEDs) + +Version 0.1.9 (2008-04-10) +-------------------------- +* Minor GUI makeup +* Made butt more verbose +* Fixed possible segfault when trying to EDIT stream info +* Fixed automatic reconnection +* Filenames can be indexed with the %i variable now +* Renamed "rec not until connected" checkbox to "start rec. when connected" +* Added orange record icon for "armed" state ("start rec. when connected" = 1) +* butt starts recording as soon as connected, when in "armed" state + +Version 0.1.8 (2008-03-30) +-------------------------- + +* Text/bg color can be changed in the [GUI] tab +* Removed the "Config saved" popup message +* Added pcm recording +* Improoved record handling +* The config menu is more user friendly now +* Fixed crash when connection loss +* The user may select the samplerate now +* The config window can be attached to the main window now +* Fixed bitrate and codec ShoutCast info + +Version 0.1.7rc1 (2008-01-04) +----------------------------- +* butt runs on MacOS 10.4 and 10.5 now! +* Added recording time to the display info +* Fixed bug with '&' in the song string +* Changing the display mode works only when connected now +* Added a checkbox which lets the user decide if the recording should start +right after selecting the output file or when connected +* Added a msg box which ask the user if he wants to stop the recording +when disconnecting + + +Version 0.1.6 (2007-12-08) +--------------------------- +* Added status symbols to the display +* Recording runs with a seperate thread now! +* Added a button for showing/hiding the server password + +Version 0.1.5 (2007-11-22) +--------------------------- +* Minor GUI changes +* Fixed streaming/recording with mp3 320kb/s +* Fixed segfault in Fl_ILM216.cpp +* The user may change the display colors now (right click on the display) +* The "connecting" info on the display updates faster now +* Changed default display colors to white/blue + +Version 0.1.5rc1 (2007-11-16) +----------------------------- +* Replaced ALSA by PortAudio -> OSS is supported now +* Ported butt to Microsoft Windows (tested with win2k and win xp) +* butt reminds the user about unsaved changes when closing now +* Starting the recording is possible at any time now +* Added mono encoding for OGG +* Improved some GUI stuff +* Improved CPU usage + +Version 0.1.4rc2 (2007-11-03) +----------------------------- +* butt should compile on more machines now + +Version 0.1.4rc1 (2007-11-01) +----------------------------- +* Added IceCast support (ogg and mp3) +* Added ./configure script +* butt is now able to send the "Current Song" value to the ShoutCast/IceCast server +* Changed stereo mode from joint-stereo to real-stereo +* Code cleanup + +Version 0.1.3 (2007-10-08) +--------------------------- +* Bugfix: butt crashed if you press "apply" in the server/icy tab without +having an server/ICY-entry +* Bugfix: butt crashed if you change the bitrate without having an ICY-entry +* Bugfix: there was some uncommented code in the [DEL]-server callback-routine +which shouldn't be uncommented +* Facelift: if you delete all server/ICY-entries, the input fields in the server/ICY +still showed the values of the last server/ICY-entry + +Version 0.1.2 (2007-10-07) +-------------------------- +* Added a GUI for configuring butt +* Comments behind config entries are not allowed anymore. +* Removed the network init part. It was nonsense +* Fixed mono playblack +* Fixed recording problems +* ICY entries can now be empty without causing butt to crash +* butt shows the real port in its "connecting to..."-info line now and the "pseudeo" port in parenthesis +* Fixed a bug which causes pcm data loss in some cases + +Version 0.1.1 (2007-09-16) +-------------------------- +* Added recording feature +* Fixed seg fault on startup when compiled with gcc-4.1.2 +* Fixed seg fault when encoding with high bitrates diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..4ac573c --- /dev/null +++ b/INSTALL @@ -0,0 +1,47 @@ +Installation: +------------- +OS X: +Mount the butt-.dmg by double clicking and +drop the butt file into the Applications folder. + +WINDOWS: +Just run the butt--setup.exe as usual and go through the +installer pages. +The default installation path might be unusual, but this way it is possible to install +butt without administration rights. + +Linux/MinGW (Windows): +First of all the following libraries have to be installed on your system +fltk-1.3, portaudio19, libmp3lame, libvorbis, libogg, libflac, +libopus, libsamplerate, libfdk-aac, libdbus-1, libcurl, libssl, portmidi +They are quite common and should be included in every popular linux distribution. + +On Ubuntu you can install them with +sudo apt-get install libfltk1.3-dev portaudio19-dev libopus-dev libmp3lame-dev libvorbis-dev \ +libogg-dev libflac-dev libfdk-aac-dev libdbus-1-dev libsamplerate0-dev \ +libssl-dev libcurl4-openssl-dev libportmidi-dev \ + +On openSUSE you can install them with +sudo zypper in fltk-devel portaudio-devel libmp3lame-devel libvorbis-devel libogg-devel flac-devel \ +libfdk-aac-devel libopus-devel libopenssl-devel libopus-devel libsamplerate-devel dbus-1-devel \ +libcurl-devel portmidi-devel + +On Distributions which don't have libfdk-aac like Debian you can compile without aac support: +./configure --disable-aac + +For compiling on Windows I recommend the msys2 x64 (www.msys2.org) environment. +They have all the needed packages in their pacman repository. Additionally you need to install the libwinpthread-git package. +Make sure that you select the x64 version of each package. + +After installing the above libraries you can install butt from source as usual: + +tar -xzf butt-.tar.gz +cd butt- +./configure +make +sudo make install + + +In case the included configure script or the make process fails on your system, try to create a new configure script by invoking: +autoreconf -i and start with ./configure again. + diff --git a/KNOWN_BUGS b/KNOWN_BUGS new file mode 100644 index 0000000..733a06f --- /dev/null +++ b/KNOWN_BUGS @@ -0,0 +1 @@ +Please report bugs to butt@danielnoethen.de diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..c8170f4 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,20 @@ +AUTOMAKE_OPTIONS = foreign +if CLIENT_ONLY +SUBDIRS = src +else +SUBDIRS = po src +endif +EXTRA_DIST = config.rpath m4/ChangeLog src/aac_dll.h src/xpm config.h src/butt.manifest player_plugins icons usr ChangeLog \ + AUTHORS THANKS KNOWN_BUGS INSTALL README COPYING NEWS src/FLTK/flgui.fl \ + src/FLTK/Fl_My_Native_File_Chooser_MAC.mm src/FLTK/Fl_My_Native_File_Chooser_WIN32.cxx \ + src/FLTK/Fl_My_Native_File_Chooser_FLTK.cxx src/FLTK/Fl_My_Native_File_Chooser_common.cxx \ + src/FLTK/Fl_My_Native_File_Chooser_GTK.cxx src/AskForMicPermission.m src/AskForMicPermission.h \ + butt.1 gettext.h + + +ACLOCAL_AMFLAGS = -I m4 + +#install-exec-hook: +# cp po/de.gmo locale/de/LC_MESSAGES/butt.mo +# cp po/fr.gmo locale/fr/LC_MESSAGES/butt.mo +# cp po/pt_BR.gmo locale/pt_BR/LC_MESSAGES/butt.mo diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..9eaa4ee --- /dev/null +++ b/Makefile.in @@ -0,0 +1,840 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir distdir-am dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ + config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +DIST_SUBDIRS = po src +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + ABOUT-NLS AUTHORS COPYING ChangeLog INSTALL NEWS README THANKS \ + compile config.guess config.rpath config.sub depcomp \ + install-sh missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +DIST_TARGETS = dist-gzip +# Exists only to be overridden by the user if desired. +AM_DISTCHECK_DVI_TARGET = dvi +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_LIBS = @DBUS_LIBS@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FLTKCONFIG = @FLTKCONFIG@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSUB = @POSUB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = foreign +@CLIENT_ONLY_FALSE@SUBDIRS = po src +@CLIENT_ONLY_TRUE@SUBDIRS = src +EXTRA_DIST = config.rpath m4/ChangeLog src/aac_dll.h src/xpm config.h src/butt.manifest player_plugins icons usr ChangeLog \ + AUTHORS THANKS KNOWN_BUGS INSTALL README COPYING NEWS src/FLTK/flgui.fl \ + src/FLTK/Fl_My_Native_File_Chooser_MAC.mm src/FLTK/Fl_My_Native_File_Chooser_WIN32.cxx \ + src/FLTK/Fl_My_Native_File_Chooser_FLTK.cxx src/FLTK/Fl_My_Native_File_Chooser_common.cxx \ + src/FLTK/Fl_My_Native_File_Chooser_GTK.cxx src/AskForMicPermission.m src/AskForMicPermission.h \ + butt.1 gettext.h + +ACLOCAL_AMFLAGS = -I m4 +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-zstd: distdir + tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + *.tar.zst*) \ + zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile config.h +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) all install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ + dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ + dist-zstd distcheck distclean distclean-generic distclean-hdr \ + distclean-tags distcleancheck distdir distuninstallcheck dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am + +.PRECIOUS: Makefile + + +#install-exec-hook: +# cp po/de.gmo locale/de/LC_MESSAGES/butt.mo +# cp po/fr.gmo locale/fr/LC_MESSAGES/butt.mo +# cp po/pt_BR.gmo locale/pt_BR/LC_MESSAGES/butt.mo + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..a2918b9 --- /dev/null +++ b/NEWS @@ -0,0 +1 @@ +See ChangeLog for more diff --git a/README b/README new file mode 100644 index 0000000..09bc6f0 --- /dev/null +++ b/README @@ -0,0 +1,953 @@ +//// +execute as "asciidoctor manual.txt" +//// + +BUTT (1.45.0) Manual +==================== +:author: Daniel Nöthen +:doctype: book +:toc2: +:numbered: +:lang: en +:email: butt at danielnoethen dot de +:encoding: utf-8 + +About +----- +BUTT (Broadcast Using This Tool) is an easy to use, multi OS streaming tool. + +It supports Icecast, Shoutcast and WebRTC and runs on Windows, macOS and Linux. + +The main purpose of BUTT is to stream live audio data from your computers microphone or line input + +to an Icecast, Shoutcast or WebRTC (WHIP) server. If you want you can also record your broadcast locally + +on your computer. + +With BUTT you can not directly stream audio files. However, with the help of tools like + +Voicemeeter (Windows), Blackhole (macOS) and PulseAudio (Linux) you can also stream audio files + +directly from your favorite music player. + +Install +------- +.OS X: +Mount the *butt-.dmg* by double clicking and + +drop the butt file on the Applications folder. + + +.Windows: +Just run the *butt--setup.exe* and follow the installer pages. + +The default installation path might be unusual, but this way it is possible to install + +BUTT without administration rights. + + +[#Install_Linux] +.Linux/MinGW (Windows): +Note: If you want to only install the butt-client, skip directly to the butt-client section below. + +First of all the following libraries have to be installed on your system + +'fltk-1.3', 'portaudio19', 'libmp3lame', 'libvorbis', 'libogg', 'libflac', + +'libopus', 'libsamplerate', 'libfdk-aac', + +'libdbus-1, 'libcurl', libssl', 'portmidi + +They are quite common and should be included in every popular linux distribution. + + +On *Ubuntu* you can install them with + +`sudo apt-get install libfltk1.3-dev portaudio19-dev libopus-dev libmp3lame-dev libvorbis-dev +libogg-dev libflac-dev libfdk-aac-dev libdbus-1-dev libsamplerate0-dev +libssl-dev libcurl4-openssl-dev libportmidi-dev` + +On *openSUSE* you can install them with + +`sudo zypper in fltk-devel portaudio-devel libmp3lame-devel libvorbis-devel libogg-devel flac-devel +libfdk-aac-devel libopus-devel libopenssl-devel libopus-devel libsamplerate-devel dbus-1-devel libcurl-devel portmidi-devel` + +On Distributions which don't have libfdk-aac like *debian* +you can compile without aac support with: + +`./configure --disable-aac` + +For compiling on *Windows* I recommend the msys2 x64 (www.msys2.org) environment. + +They have all the needed packages in their pacman repository. Additionally you need to install the `libwinpthread-git` package. + +Make sure that you select the x64 version of each package. + +After installing the above libraries you can install BUTT from source as usual: + +- +tar -xzf butt-.tar.gz+ + +- +cd butt-+ + +- +autoreconf -i+ (only on Windows/MSYS2) + +- +./configure+ + +- +make+ + +- +sudo make install+ + +In case the included configure script or the make process fails on your system, try to create a new configure script by invoking: +`autoreconf -i` +and start with `./configure` again. + +butt-client +----------- +butt-client is a minimal binary which can be used to send commands to a running BUTT instance. + +There are two ways to build butt-client: + +1. Configure the build by adding --with-client to the configure command. + +2. Configure it by adding --without-butt. + +The first option builds both BUTT and butt-client and it requires all system dependencies. + +The second option builds butt-client only and it requires none of the system dependencies. + +This is the recommended option if you only need butt-client, especially if you are installing + +it on a different machine. This is because the resulting binary is much smaller and it does + +not link with any system dependencies, except the standard ones, which means that it is portable + +as long as you copy it to another machine which shares the same operating system as the one you are building it on. + + + +Quick start +----------- +When you start BUTT the first time, it will create a default configuration + +file in in your home directory ('~/.buttrc') on Linux and macOS or at + +'C:\Users\\AppData\Roaming\buttrc' on Windows. + + +In order to connect to a server, you need to add a new server in the config window. + +Just open the settings window and click on [ADD]. + +Now fill in the input fields with the server credentials and click on the [ADD] at +the lower right corner. + +To connect to the server just press the play button in the main window and enjoy + +your broadcast. + +Install AAC libraries +--------------------- +.Windows: +1. Download libfdk-aac-2.dll from link:https://danielnoethen.de/butt/release/1.45.0/AAC/libfdk-aac-2.dll[here] +2. Go to the installation directory of BUTT by typing %LOCALAPPDATA%\butt into the file explorer +3. Copy libfdk-aac-2.dll into the installation directory of BUTT +4. Restart BUTT +5. Enjoy AAC streaming + +.MacOS: +1. Download and install butt_libfdkaac_macOS.pkg from link:https://danielnoethen.de/butt/release/1.45.0/AAC/butt_libfdkaac_macOS.pkg[here] +2. Restart BUTT +3. Enjoy AAC streaming + +Note: The installer will install libfdk-aac.2.dylib into /Library/Application Support/butt/ + +.Linux: +In case your Linux distribution ships BUTT without AAC support, + +you need to install BUTT from source. Please refer to the <> section for more + +information on that. + + +Configuration +------------- +The command line option +-c + allows you to define a new standard configuration path. + +This makes it possible to have multiple instances with different configurations + +running. In case the file does not exists, BUTT will create a default file for you. + +A tutorial on how to use the -c command line option to run multiple BUTT +instances can be found +http://danielnoethen.de/butt/howtos/multiple_servers.html[here]. + +[Save]: Saves your current settings to the standard configuration + +file or to the file that was passed to the -c option + +[Export]: Saves your current settings to the given file + +[Import]: Loads the selected file and applies the settings + + +CAUTION: If you use the -c command line option and import another configuration file + +by using the import function, pressing [Save] will overwrite the file that was passed to the -c option. + +TIP: In some cases the configuration file can become damaged and BUTT will not be +able to start correctly. In that case you can hold down the shift key during +BUTT startup to create a new configuration file. + + +Main Window +----------- +The dot matrix display shows you the current state of the BUTT software. + +The states are: idle, streaming, recording. + +When in streaming and/or recording state you can cycle through the information by clicking on the display. + +You can choose between online duration, data sent, recording duration, data recorded and On Air state + + +The [>] symbol shines yellow if BUTT is connected to a server. + +The [O] symbol shines orange if the +[start rec. when connected]+ checkbox is activated. + +The [O] symbol shines red if BUTT is currently recording. + + +Additionally the play and record buttons change their color to yellow and red when BUTT is connected or recording. + +Gain slider: +The slider is only visible when to log window is visible as well. + +With this slider you can attenuate and amplify the input signal between '-24 dB' and '+24 dB', respectively. + +Double clicking the slider handle resets the gain to '0 dB'. Use this slider only to fine tune your input signal. + +To enter the gain as a number with your keyboard, right click the slider handle. +The slider does not change the operating systems input volume setting. Instead, the input signal is multiplied + +by the given factor. Thus, adding too much gain will also add lots of noise. + + +VU meter: +The vu meter shows the current streaming or recording volume in dBFS. + +Audio Mixer +----------- +Click on +[Mixer]+ to open the Audio Mixer. The mixer allows you to individually adjust the volume of + +your audio devices and have different volumes for streaming and recording. The Master Gain slider is coupled with the + +gain slider on the main window. + +The crossfader allows you to blend volumes between the primary and secondary audio device. Moving it + +from the center to one side lowers the volume of the other side. + + +Audio +----- +The audio settings tab allows you to select your primary and secondary audio interface and the desired sample rate. + +If you have a multi-channel audio device you may also select the desired input channels for the left and + +right audio channel. + +If you want to stream in stereo, make sure that the left and right channels are mapped to different input channels + +like 1 and 2. Otherwise you will only stream a mono signal. + +With the channel mode setting you tell BUTT if the audio stream shall be encoded to stereo or mono. + +This brings us to 4 possible combinations. + +.Channel mode = *Stereo* and *different input channels* are selected for Left and Right: +This is probably the most used combination. + +Left and Right channels are encoded into a stereo stream. + +.Channel mode = *Stereo* and the *same input channel* is selected for Left and Right: +The selected input channel is used for the left and right channel in a stereo stream. + +.Channel mode = *Mono* and *different input channels* are selected for Left and Right: +Left and Right channels are averaged into a mono stream. + +.Channel mode = *Mono* and the *same channel* is selected for Left and Right: +The selected channel is used as mono channel in a mono stream. + +The "Remember Device by" setting lets you choose if BUTT remembers the current device by its ID + +or its name. As the ID may change when changing the number of connected audio devices on your computer + +or when updating your operating system, it is recommended to let BUTT remember the audio device by its name. + +Clicking on +[Update devices]+ will rescan the system for audio devices and update the Primary and Secondary + +audio device list accordingly. + +Within the Streaming and Recording section you can select invididual audio codecs and corresponding bitrate + +for streaming and recording. Advanced users have the ability to change codec settings by clicking the gear symbol. + +The Signal dection levels define at which level BUTT should treat the signal as present or absent. + +These levels are used by the auto connect/disconnect or recording feature described below. + + +Streaming +--------- +Before you can start streaming you need to add a server first. If you have not added a server yet, + +please refere to the quick start section of this manual. + +To start streaming just click the play symbol. + +BUTT will try to connect to the server until you press the stop button. + +If the connection gets lost, BUTT will try to reconnect until the stop button is pressed + + +You can stream in 5 different audio codecs: mp3, aac+, ogg/vorbis, ogg/opus and ogg/FLAC. + +In case opus is selected the sample rate is always resampled to 48 kHz. + +If you want to prevent BUTT from resampling, you should select 48 kHz as the device sample rate. + +.Song name: +If you want to inform the listener about which song is currently playing you + +can do that on the +[Stream]+ tab. + +You only need to type the song into the +Song Name+ input field + +and hit Enter or click +[OK]+. + +BUTT can also update the song automatically from a text file. + +The first or the last line of the file must be the name of the song. + +As soon as BUTT detects that the file has been changed, it updates the + +name of the song on the server. + + +To retrieve the current song name from an URL you can enter the URL into the + +'Update song name from URL' field and enable the 'Activate' checkbox. + +Set the 'Update interval' to the number of seconds you want BUTT to check for a new song name. + +BUTT uses the first line from the server response for the song name update. + +HTML tags are not parsed nor removed, so it is recommended use a URL that returns a + +simple text file instead of a HTML formatted website. + +If you run BUTT on macOS or Linux you can even transfer the current + +song name from an audio player to BUTT. + +Supported audio players: + +Linux: Rhythmbox, Banshee, Clementine, Cantana, Spotify + +MacOS: iTunes/Music, Vox, Spotify +Windows: Not supported + +As broadcasting with Icecast and Shoutcast is not realtime, the + +listener receives the audio content with a few seconds of delay. + +This delay introduces an offset between the current song name and + +the actual song that is playing. To prevent confusion on the listeners side + +you can add a delay to the automatic song update. + +In case you want to add a prefix and/or a suffix to your song name + +you can do that by entering the desired text into the corresponding + +input field. + +.Stream infos: +In the +[Main]+ settings window you can add stream infos. + +This allows you to deliver more details about your stream. + +For example the genre of your music, description of your station, web address etc. + + +Unfortunately, it is not possible to update stream infos during a broadcast. + +You need to reconnect for updating the stream infos. + + +For the name and description fields you may use the same placeholder variables as you can + +in the recording file/path. Activate the 'Expand variables' checkbox to enable it. + +.Automatic streaming: +If you activate the checkbox 'Start streaming after launch' BUTT will + +automatically connect to the server as soon as the application has been started. + +BUTT can also connect and disconnect depending on the audio signal level: + + +To connect automatically if a signal is present for a certain amount of time + +enter an integral number larger than 0 into the 'Start if signal is present for [...] seconds' field + +and activate the checkbox. + +To disconnect automatically if the signal is absent for a certain amount of time + +enter an integral number larger than 0 into the 'Stop if signal is absent for [...] seconds' field + +and activate the checkbox. + +The default signal detection levels are set to -50.0 dB and can be independently changed + +for the present and absent signal cases in the +[Audio]+ tab. + +Shoutcast +--------- +Basically BUTT is a Shoutcast 1 source client and does not support the native Shoutcast 2 protocol. + +However, Shoutcast 2 servers are compatible with Shoutcast 1 client by default. So you can also + +connect to Shoutcast 2 servers with BUTT. + + +To add a Shoutcast server, open the settings and click on [ADD]. Now enter the server address, port and + +password. If you did not setup the Shoutcast server by your own, you will get the required information from + +your streaming hoster. + + +If you need to enter Shoutcast 2 specific login data like a user name or a stream ID you can add this + +to your password as follows: + + +Let's assume your user name is *MyUser*, your password is *MyPassword* and the *stream ID* is *3*. + +To add the user name to the password field enter the following: + + +MyUser:MyPassword + +The stream ID 3 can be appended after the password like this: + + +MyUser:MyPassword:#3 + + +Icecast +------- +To add an Icecast server open the settings and click on [ADD]. Now enter the server address, port and + +credentials like, user, password and mounpoint. If you did not setup the Icecast server by your own, + +you will get the required information from your streaming hoster. + + +Secure Connection over SSL/TLS (Icecast only) +--------------------------------------------- +To enable encryption for an icecast server, you only have to activate the + +'Use SSL/TLS' checkbox in the server settings. Please bear in mind that the + +server must be configured with SSL/TLS support in order to make this working. + +The connection will fail if you activate SSL/TLS for a server which does not + +support encryption. + +If the certficicate validation fails, BUTT will ask you if you want to trust + +that certificate anyway. If you click on +[TRUST]+ BUTT will establish the + +connection and remembers the decision for that certificate and server. + +By pressing the button '[Revoke certificate trust]' you can revoke that + +decision. + +If you want to specify your own file or folder with CA certificates, + +you can enter the path to the file or folder in the +[TLS]+ tab of the + +settings window. Usually you should not need to enter any information there. + + +WebRTC (WHIP) +------------- +Since version 1.42.0 BUTT is able to stream to a WebRTC WHIP server. + +WebRTC is a relatively new technology for realtime peer-to-peer communication for + +video and audio. Although WebRTC is point-to-point by default, with the additional WHIP protocol + +it is also possible to have a client/server connection like it is used by Icecast and Shoutcast. + + +The biggest advantage of using WebRTC is its low latency which can be lower than 200 ms. However, + +to accomblish such a low latency, the WebRTC protocol has to make use of certain techniques that + +require a perfectly stable connection to the server. Otherwise small interruptions of the audio signal + +may occur or the audio signal may sound speed up or slowed down for a short period of time. + +Because of this, it is not recommanded to use WebRTC for streaming music but rather use it + +for situations where you need near real time voice broadcasting like for a live commentary of a sports event. + +To add a WebRTC server open the settings and click on [ADD]. Now select WebRTC and enter your WHIP URL. + +If needed you can also enter a STUN or TURN server address into the ICE server field and a Bearer Authentication Token. + + +WebRTC does only work with opus, so please make sure that you have opus selected als streaming codec. + + +Recording +--------- +BUTT is able to record and stream simultaneously in different bit rates. + +For example you can stream with 96 kbit and record with 192 kbit. + +Recording is possible in mp3, aac+, ogg/vorbis, ogg/opus, FLAC or wav. + +To record your session you first need to select the destination folder and specify a file name + +in the +[Record]+ tab. + +BUTT will replace specific date variables with the current time and date. +For example +rec_(%m_%d_%y).mp3+ expands to +rec_(03_28_2008).mp3+. + +Other possible time variables are +%H+ (hours) +%M+ (minutes) +%S+ (seconds). +Refer to the table below for more supported date variables. + +With the +%i+ variable you can add an index number to your file name. + +This means with +rec_%i.mp3+ BUTT first tries to record to +rec_0.mp3+. In case that + +file already exists, BUTT tries +rec_1.mp3+ ... + + +To manually start the recording simply press the record symbol. + +To stop recording just click on the record symbol again. + + +.Automatic recording: +If the 'start recording when connected' checkbox is activated BUTT starts the + +recording immediately after a connection with the server has been established. + +Vice versa BUTT will stop the recording if the 'Stop recording when disconnected' checkbox + +is active. + +Additionally you can tell BUTT to immediately start recording after the application has been + +launched by checking the 'Start recording after launch' box. + + +To start recording automatically if a signal is present for a certain amount of time + +enter an integral number larger than 0 into the 'Start if signal is present for [...] seconds' field. + +To stop recording automatically if the signal is absent for a certain amount of time + +enter an integral number larger than 0 into the 'Stop if signal is absent for [...] seconds' field. + +The default signal detection levels are set to -50.0 dB and can be independently changed + +for the present and absent signal cases in the +[Audio]+ tab. + +You can also tell BUTT to split your recording into + +separate files every *n* minutes. Just enter a number higher than 0 + +into the 'Split file every [..] minutes' field. + + +Let's assume your file name is +rec_(%m_%d_%y)\_%i.mp3+ Then the first file is + +expanded to +rec\_(03_28_2008)\_0-1.mp3+, the second after *n* minutes to + ++rec_(03_28_2008)\_0-2.mp3+, the third to +rec_(03_28_2008)_0-3.mp3+, you got it. + + +If the 'sync to full hour' checkbox is activated the automatic file splitting + +is synchronized to the full hour. This means if the current time is '8:55' and file + +splitting is set to '15 minutes', the second file starts at '9:00' and the third + +at '9:15'. + +If you want to split the recording now, just click the '[Split now]' button. + +*Supported variables:* +[cols="1,8"] +|=== +|Variable|Meaning + +|%N +|Server name + +|%a +|abbreviated weekday name (e.g. Fri) + +|%A +|full weekday name (e.g. Friday) + +|%b +|abbreviated month name (e.g. Oct) + +|%B +|full month name (e.g. October) + +|%d +|day of the month, as a number (1-31) + +|%H +|hour, 24 hour format (0-23) + +|%I +|hour, 12 hour format (1-12) + +|%j +|day of the year, as a number (1-366) + +|%m +|month as a number (1-12). + +|%M +|minute as a number (0-59) + +|%p +|AM or PM + +|%S +|second as a number (0-59) + +|%U +|week of the year, (0-53), where week 1 has the first Sunday + +|%w +|weekday as a decimal (0-6), where Sunday is 0 + +|%W +|week of the year, (0-53), where week 1 has the first Monday + +|%y +|year in decimal, without the century (0-99) + +|%Y +|year in decimal, with the century + +|%Z +|time zone name +|=== + +DSP +--- +The DSP section contains two sound processors. A 10-band EQ and a Dynamic Range Compressor. + +With the 'Stream' and the 'Rec' checkboxes you can decide if a sound processor should be activated + +for the streaming and/or recording signal chain. + +.10-Band Equalizer: +The equalizer allows you to change the gain of certain frequency bands from -15 dB to 15 dB. + +Note for professionals: The equalizer uses a Q of 2 on each frequency band. + +.Dynamic Range Compressor: +Dynamic range compression is used to reduce the difference between + +loud and quiet parts of the signal, and thus provide a more consistent + +experience for listeners. It is used by virtually all professional + +radio stations. + + +The recommended procedure for configuring the compressor is as follows: + + +1. Start playing the loudest audio source you intend to broadcast + +(typically music), and line it up with the master gain slider. + + +2. Enable the compressor, and adjust the threshold and gain to suit. + +The attack and release times can generally be kept as they are, unless + +you have a particular reason to change them. You will notice that the + +overall signal level goes down, as it is being compressed. + + +3. Adjust the makeup gain to bring the signal back to its original level. + + +4. Now test with a quieter audio source (such as your voice), and see + +that the level of that is boosted in comparison. If the quieter source + +is still too quiet, reset the makeup gain to 0 and repeat from step 2 + +onwards, until you have a satisfactory result. + + +This procedure can take some time to find the optimum settings, which + +are determined by listening as much as by metering, but it generally + +only needs to be done once - BUTT will save your settings, so once you + +have values that work well for your content, you probably don't need + +to adjust them again. + + +As a rough guide, music should be compressed relatively subtly, with a + +fairly high threshold and a ratio typically between 2 and 3. Pure + +speech content can be compressed much more dramatically, with a low + +threshold and a ratio of 5 or more; this will make the speech easier + +for the listener to understand, and will also reduce the differences + +between different speakers or by not keeping a very consistent + +distance from the microphone. + + +For mixed speech and music broadcasting, it is recommended to set + +BUTT's compression as for music, and then have an additional + +compressor (typically a hardware module) between the microphones and + +the final mix. + + +To check if the signal power exceeds the threshold, the compressor usually + +averages the signal power over time and compares it with the threshold. + +This averaging process reduces the speed of the compressor. In case you need + +a very fast responding compressor you can activate the 'Aggressive Mode' option. + +With this option enabled the compressor does not average the signal power + +over time anymore. + +MIDI +---- +In the +[MIDI]+ tab you can set up a MIDI device to control BUTT via MIDI CC and + +NOTE ON messages. + + +To activate the MIDI interface simply select your MIDI device from the 'MIDI Device' + +drop down menu. + + +The 'MIDI indicator light' will blink if BUTT receives a MIDI message. This allows +you to verify the connection between BUTT and your MIDI device. + + +The 'MIDI Command' list shows you which parts of BUTT can be controlled via CC and NOTE ON + +messages. By default all commands are disabled. To enable a command select the command from + +the list and click on *Enable*. + + +*MIDI implementation table for CC messages* +[cols="3,2,3"] +|=== +|Command|CC value|Action + +|Start/Stop broadcasting +|> 63 + +< 64 +|Starts broadcasting + +Stops broadcasting + +|Start broadcasting +|Any +|Starts broadcasting + +|Stop broadcasting +|Any +|Stops broadcasting + +|Start/Stop recording +|> 63 + +< 64 +| Starts recording + +Stops recording + +|Start recording +|Any +|Starts recording + +|Stop recording +|Any +|Stops recording + +|Master Gain +|0-127 (absolute mode) +|Scales linearly between -24 dB and +24 dB + +|Streaming Gain +|0-127 (absolute mode) +|Scales linearly between -18 dB and +18 dB + +|Recording Gain +|0-127 (absolute mode) +|Scales linearly between -18 dB and +18 dB + +|Primary Device Gain +|0-127 (absolute mode) +|Scales linearly between -18 dB and +18 dB + +|Secondary Device Gain +|0-127 (absolute mode) +|Scales linearly between -18 dB and +18 dB + +|Cross fader +|0-127 (absolute mode) +|Blends between Primary (0) and Secondary (127) Device + +|Mute/Unmute Primary Device +| Any +| Toggles mute state + +|Mute/Unmute Secondary Device +| Any +| Toggles mute state + +|=== + + +*MIDI implementation table for NOTE ON messages* + + +Instead of a NOTE OFF message, some MIDI devices send a NOTE ON message with a value + +lower than 64 when a key is released. Therefore, BUTT does only accept MIDI ON + +messages with a value higher than 63 to prevent reacting falsely on key releases. + + +[cols="3,2,3"] +|=== +|Command|NOTE ON value|Action + +|Start/Stop broadcasting +|> 63 +|Toggles broadcasting state + +|Start broadcasting +|> 63 +|Starts broadcasting + +|Stop broadcasting +|> 63 +|Stops broadcasting + +|Start/Stop recording +|> 63 +|Toggles recording state + +|Start recording +|> 63 +|Starts recording + +|Stop recording +|> 63 +|Stops recording + +|Master Gain (not supported) +|Any +|Not supported + +|Streaming Gain (not supported) +|Any +|Not supported + +|Recording Gain (not supported) +|Any +|Not supported + +|Primary Device Gain (not supported) +|Any +|Not supported + +|Secondary Device Gain (not supported) +|Any +|Not supported + +|Cross fader (not supported) +|Any +|Not supported + +|Mute/Unmute Primary Device +| Any +| Toggles mute state + +|Mute/Unmute Secondary Device +| Any +| Toggles mute state + +|=== + +There are several options available to adapt BUTT to your MIDI controller: + +.Channel: +Select the channel where your MIDI controller sends MIDI messages to. + +.CC: +Type in a number from 0 to 127 which corresponds to the control element (button, knob, slider) + +of your MIDI controller. + +.Learn: +If you don't know the channel of your MIDI device or the CC number of your control element + +you can activate the *learning mode*. After pressing the '[Learn]' button, BUTT will + +wait for an incoming CC message and set the channel and CC number for you automatically. + + +.CC Mode: +Volume controls can be controlled in two different ways: + +1. In *absolute mode* BUTT maps the incoming CC values 0-127 linearly to its internal range. +In case of a volume slider this means 0 maps to min and 127 to max volume. + ++ +If you switch back and forth between controlling a slider via the mouse and via your MIDI controller + +the UI and your MIDI controller will get out of sync which will cause value jumps when + +controlling a slider via MIDI after you changed the slider position via mouse before. + +To prevent those jumps activate the *Soft takeover* option. + + +2. The *relative modes* interpret the incoming CC values as increments or decrements. + +Select the relative mode that fits to your MIDI controller. + + +GUI settings +------------ +Within the +[GUI]+ settings you can change certain settings to your personal + +preferences. + +.Language: +In case BUTT does not correctly detect your system language or you prefere a + +different one you can select your preferred language here. + +After changing the language a restart of BUTT is required. + +.Display Color: +Change the text and background color of the main display to your favorite color. + +.VU meter: +Select between gradient or solid colors for VU meter. For better visibility + +the solid colors mode is recommended. + +If the 'Always show tabs' checkbox is unchecked the Streaming and Recording tabs + +on the VU meter are only visible if you hover your mouse over the meter. + + +.Attach settings window to main window: +If checked, the settings window will stick to the right side of the BUTT window. + +.Stay always on top: +If checked, BUTT will always be on top of other application windows. + +.Remember main window position: +If checked, BUTT will open on the previous position and screen. + +In case the previous screen is not available BUTT will open on the default screen. + +Additionally, this function also remembers the size of the log window. + +.Hide log window after start up: +If checked, BUTT will open with the log window hidden. + +.Change display mode every 5 seconds: +If checked, the display rotates automatically through the states + +online duration, data sent, recording duration and data recorded. + +.Start minimized: +If checked, BUTT will start minimized to your Taskbar or Dock (macOS). + +.Disable gain control: +If checked, the gain control slider on the main window will be disabled. + +This prevents users from accidentally changing the volume. + +.Show listeners: +If checked, BUTT retrieves the number of current listeners from + +your server every 3 seconds. + +If available the number of listeners are shown on the lower right corner at the display. + + +NOTE: BUTT derives the URL for listener statistics from the server settings. + +Usually this works only if you have a plain Icecast or Shoutcast server. + +In case you are using a stream hoster they usually have a more complex setup + +which provides the listener stats on a different mountpoint or URL. + +For these situation you can enter a specific mountpoint or URL which BUTT will use + +instead. + +For example if you connect to the mountpoint */stream* but you want the listeners + +from mountpoint */live*, simply enter */live* into the *Custom listener mountpoint* + +field in the server settings. + + + +If you are unsure which URL or mountpoint to use, please contact your stream hoster. + + +The BUTT agent (Windows only) +----------------------------- +With version 0.1.29 a little helper tool called BUTT agent was introduced. + +The main purpose of the BUTT agent is to make it possible to minimize BUTT + +into the windows system tray. + +Minimizing to tray is not the only feature, though. You also have the + +ability to let it display balloon notifications for connects/disconnects + +and for song updates. If you want to start BUTT at windows start you can + +also enable/disable this with the agent. + +BUTT starts the agent automatically if the checkbox 'Minimize to tray' + +is enabled. If you want to use the balloon notifications you should activate + +the 'Start agent at startup' checkbox in the +[Main]+ settings tab. + +Once the agent has been started you will find it in the system tray. + +From here you can manage the minimized BUTT instances and activate the + +features mentioned above. A left click on the tray icon minimizes or raises + +the last BUTT instance. A right click opens up a context menu with more + +options. + +The BUTT agent closes itself if no more BUTT instance is running. + + + +Command line control +-------------------- +BUTT can be controlled from command line. + +If you want you can even control BUTT from a remote computer. + +Please refer to the section below for more information on that. + + +Command line options +-------------------- +BUTT has several command line options which can be seperated into two modes + +which are the operating mode and control mode. + +.Operating Mode: +These options change the behaviour of the instance you are about to start. + + +'-c :' + +This option allows you to select a different configuration path. It is useful if you + +want to run several BUTT instances with different configurations. Just pass a different + +configuration file with the -c option for every instance. + + +'-L:' + +Prints available audio devices. + +'-A:' + +This option tells BUTT to accept control commands from your network or even the internet. + + +CAUTION: When using this option everyone in your network or even internet may + +control your BUTT instance. Please use this option only if you have secured your network appropriately. + +'-U:' + +(uppercase U) + +The command server will use UDP instead of TCP. If you pass the -U flag here +you also need to pass it when sending control commands. + +'-x:' + +Use this option if you do not want to run a command server at all. This will also disable +receiving commands from your local machine. + +'-p :' + +With this option you can define the port of the command server. The default port is 1256. +Use this option for example if you have several BUTT instances that you want to control from +command line. + +.Control Mode: +With these options you can send control commands to a running BUTT instance. + +Note that you can send these commands from either BUTT or butt-client binaries. + + +'-s [name]:' + +(lowercase s) + +This command tells BUTT to connect to the server 'name'. If the 'name' parameter is omitted, +BUTT will connect to the currently selected server. + +'-d:' + +When receiving this command, BUTT will disconnect from the current server. + +'-r:' + +This command starts the recording engine. + +'-t:' + +Use this option to stop the recording. + +'-n:' + +In case a recording session is active this option splits the current file + +like it would if you press the +[Split now]+ button in the user interface. + +'-q:' + +Closes BUTT gracefully. + +'-u :' + +(lowercase u) + +Sends a new song name to the server. + +'-M :' + +Sends a new streaming signal threshold time to the server. + +Minimum value is 0.1. Send 0 to disable automatic stream start. + +'-m :' + +Sends a new streaming silence threshold time to the server. + +Minimum value is 0.1. Send 0 to disable automatic stream stop. + +'-O :' + +Sends a new recording signal threshold time to the server. + +Minimum value is 0.1. Send 0 to disable automatic recording start. + +'-o :' + +Sends a new recording silence threshold time to the server. + +Minimum value is 0.1. Send 0 to disable automatic recording stop. + +'-S:' + +(uppercase S) + +Requests a status information packet. The answer will be of the form: + +`connected: 1` + +`connecting: 0` + +`recording: 1` + +`signal present: 1` + +`signal absent: 0` + +`stream seconds: 10` + +`stream kBytes: 164` + +`record seconds: 38` + +`record kBytes: 3581` + +`volume left: -6.2` + +`volume right: -6.2` + +`song: Stanley Clarke Trio - Under the Bridge` + +`record path: /home/butt/recordings/recording_20220312.flac` + +`listeners: 256` + + + +'-a
:' + +Use this option to control a BUTT instance that is running on a remote computer. + +In order to control a remote BUTT instance the BUTT instance must have been + +started with the -A option. The parameter 'address' can be either a IP address or a hostname. + +'-p :' + +This should be set to the same port that has been given to the BUTT instance you want to control. + +By default the command will be sent to port 1256. + + +'-U:' + +(uppercase U) + +Use this option to send commands via UDP instead of TCP. + + +Uninstall +--------- +.MacOS: +Delete the *butt.app* from your 'Application' folder and + +remove the configuration file from '/Users//.buttrc' + + +.Windows: +Run the Uninstaller from the BUTT folder in your windows start menu. + + +.Linux/MinGW: +Run +sudo make uninstall+ from the source tree and + +remove the configuration file from '/home//.buttrc' + + + +Contact +------- +butt at danielnoethen dot de + + +Donate +------ +Paypal: +https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=LTRSQNTWN4L6L&source=url[paypal@danielnoethen.de] + +Patreon: https://www.patreon.com/bePatron?u=31552247[Become a Patron] + +Apple Pay, Google Pay and more: https://donorbox.org/butt[Donorbox] + + +.Cryptocurrencies: + +Bitcoin: bc1q4uq7h464rsu2cudrmuuqmc4tcr98d0edrhe5au + +Litecoin: Ld9gntf8fsYpmVcbstFkzz5R3sNPC3AhTx + +Monero: 85u8DacasxPNvKzY5kEiprBnbydDqg26yGAVEw7mdwccNFsrXMWCE4VQnV2JVfh5BTRheNnpDJqYjbqPrVRLEPAKP3dsYgc + + +If you want to use a different cryptocurrency please contact me. diff --git a/THANKS b/THANKS new file mode 100644 index 0000000..b21988a --- /dev/null +++ b/THANKS @@ -0,0 +1,22 @@ +butt THANKS file + +butt has originally been written by Daniel Nöthen. Many people have further +contributed to butt by reporting problems, suggesting various improvements, +writing tutorials or even submitting code. Thanks to all of you! + +Special thanks go to: +Heinrich Unrau, for suggestion me the name "butt" +Thomas Ziebura, for teaching me C +Jorge Suárez de Lis, for creating ubuntu packages +Dominik Durner, for creating a patch for icecast stream infos +Subrat (ipapuna) Nayak, for creating the icon and releasing it under cc +Mikko Pikarinen, for writing a huge patch with some nice features +Melchor Garau Madrigal, for forking butt and releasing it on github with new features +Thomas Preece, for adding the dynamic range compressor +Ivan Radolovic, for developing the butt agent +Hossam Hammady, for adding threshold limit control commands and butt-client + +Not to forget the developers of all the libraries butt depends on! + +Drop me a mail in case I forgot to mention you ;-) + diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..10b44ce --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,1435 @@ +# generated automatically by aclocal 1.16.5 -*- Autoconf -*- + +# Copyright (C) 1996-2021 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],, +[m4_warning([this file was generated for autoconf 2.71. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 12 (pkg-config-0.29.2) + +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.2]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $2]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +# Copyright (C) 2002-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.16' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.16.5], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.16.5])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + AS_CASE([$CONFIG_FILES], + [*\'*], [eval set x "$CONFIG_FILES"], + [*], [set x $CONFIG_FILES]) + shift + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf + do + # Strip MF so we end up with the name of the file. + am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`AS_DIRNAME(["$am_mf"])` + am_filepart=`AS_BASENAME(["$am_mf"])` + AM_RUN_LOG([cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles]) || am_rc=$? + done + if test $am_rc -ne 0; then + AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE="gmake" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking).]) + fi + AS_UNSET([am_dirpart]) + AS_UNSET([am_filepart]) + AS_UNSET([am_mf]) + AS_UNSET([am_rc]) + rm -f conftest-deps.mk +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking is enabled. +# This creates each '.Po' and '.Plo' makefile fragment that we'll need in +# order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +m4_ifdef([_$0_ALREADY_INIT], + [m4_fatal([$0 expanded multiple times +]m4_defn([_$0_ALREADY_INIT]))], + [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +# Variables for tags utilities; see am/tags.am +if test -z "$CTAGS"; then + CTAGS=ctags +fi +AC_SUBST([CTAGS]) +if test -z "$ETAGS"; then + ETAGS=etags +fi +AC_SUBST([ETAGS]) +if test -z "$CSCOPE"; then + CSCOPE=cscope +fi +AC_SUBST([CSCOPE]) + +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check whether make has an 'include' directive that can support all +# the idioms we need for our automatic dependency tracking code. +AC_DEFUN([AM_MAKE_INCLUDE], +[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) +cat > confinc.mk << 'END' +am__doit: + @echo this is the am__doit target >confinc.out +.PHONY: am__doit +END +am__include="#" +am__quote= +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) + AS_CASE([$?:`cat confinc.out 2>/dev/null`], + ['0:this is the am__doit target'], + [AS_CASE([$s], + [BSD], [am__include='.include' am__quote='"'], + [am__include='include' am__quote=''])]) + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +AC_MSG_RESULT([${_am_result}]) +AC_SUBST([am__include])]) +AC_SUBST([am__quote])]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + MISSING="\${SHELL} '$am_aux_dir/missing'" +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 2001-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([m4/gettext.m4]) +m4_include([m4/iconv.m4]) +m4_include([m4/intlmacosx.m4]) +m4_include([m4/lib-ld.m4]) +m4_include([m4/lib-link.m4]) +m4_include([m4/lib-prefix.m4]) +m4_include([m4/nls.m4]) +m4_include([m4/po.m4]) +m4_include([m4/progtest.m4]) diff --git a/butt.1 b/butt.1 new file mode 100644 index 0000000..ce4222a --- /dev/null +++ b/butt.1 @@ -0,0 +1,180 @@ +'\" t +.\" Title: butt +.\" Author: [see the "AUTHOR(S)" section] +.\" Generator: Asciidoctor 2.0.10 +.\" Date: 2022-04-20 +.\" Manual: BUTT +.\" Source: BUTT +.\" Language: English +.\" +.TH "BUTT" "1" "2022-04-20" "BUTT" "BUTT" +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.ss \n[.ss] 0 +.nh +.ad l +.de URL +\fI\\$2\fP <\\$1>\\$3 +.. +.als MTO URL +.if \n[.g] \{\ +. mso www.tmac +. am URL +. ad l +. . +. am MTO +. ad l +. . +. LINKSTYLE blue R < > +.\} +.SH "NAME" +butt \- Easy to use, multi OS streaming tool +.SH "SYNOPSIS" +.sp +\fBbutt\fP [\-h | \-v | \-s [name] | \-u | \-M | \-m | \-O | \-o | \-Sdrtqn | \-c ] [\-A | \-U | \-x] [\-a ] [\-p ] +.SH "DESCRIPTION" +.sp +\fBbutt\fP (broadcast using this tool) is an easy to use, multi OS streaming tool. +It supports ShoutCast and IceCast and runs on Linux, MacOS and Windows. +The main purpose of \fBbutt\fP is to stream live audio data from your computers Mic or Line input +to an Shoutcast or Icecast server. Recording is also possible. +It is NOT intended to be a server by itself or automatically stream a set of audio files. +.SH "OPTIONS" +.sp +Options: +.sp +\fB\-h\fP +.RS 4 +Print help +.RE +.sp +\fB\-v\fP +.RS 4 +Print version information +.RE +.sp +Options for operating mode: +.sp +\fB\-c \fP +.RS 4 +Path to configuration file +.RE +.sp +\fB\-A\fP +.RS 4 +Command server will be accessible from your network/internet (default: localhost only) +.RE +.sp +\fB\-U\fP +.RS 4 +Command server will use UDP instead of TCP +.RE +.sp +\fB\-x\fP +.RS 4 +Do not start a command server for receiving commands +.RE +.sp +\fB\-p \fP +.RS 4 +Port where the command server shall listen to (default: 1256) +.RE +.sp +Options for control mode: +.sp +\fB\-s [name]\fP +.RS 4 +Connect to streaming server +.RE +.sp +\fB\-d\fP +.RS 4 +Disconnect from streaming server +.RE +.sp +\fB\-r\fP +.RS 4 +Start recording +.RE +.sp +\fB\-t\fP +.RS 4 +Stop recording +.RE +.sp +\fB\-n\fP +.RS 4 +Split recording +.RE +.sp +\fB\-q\fP +.RS 4 +Quit butt +.RE +.sp +\fB\-u \fP +.RS 4 +update song name +.RE +.sp +\fB\-S\fP +.RS 4 +Request status +.RE +.sp +\fB\-M \fP +.RS 4 +Set streaming signal threshold +.RE +.sp +\fB\-m \fP +.RS 4 +Set streaming silence threshold +.RE +.sp +\fB\-O \fP +.RS 4 +Set recording signal threshold +.RE +.sp +\fB\-o \fP +.RS 4 +Set recording silence threshold +.RE +.sp +\fB\-U\fP +.RS 4 +Connect via UDP instead of TCP +.RE +.sp +\fB\-a
\fP +.RS 4 +Address of the \fBbutt\fP instance to be controlled (default: 127.0.0.1) +.RE +.sp +\fB\-p \fP +.RS 4 +Port of the \fBbutt\fP instance to be controlled (default: 1256) +.RE +.SH "RESSOURCES" +.sp +Project web site: \c +.URL "https://danielnoethen.de/butt" "" "" +.SH "SEE ALSO" +.sp +A more detailed description can be found in the manual at +.URL "http://danielnoethen.de/butt/manual.html" "" "" +.SH "FILES" +.sp +~/.buttrc +.RS 4 +\fBbutt\fP configuration file. +.RE +.SH "BUGS" +.sp +Please contact me at \c +.MTO "butt\(atdanielnoethen.de" "" " " +if you find any bugs. +.SH "AUTHORS" +.sp +\fBbutt\fP was written by Daniel Nöthen and other contributors. \ No newline at end of file diff --git a/compile b/compile new file mode 100755 index 0000000..df363c8 --- /dev/null +++ b/compile @@ -0,0 +1,348 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 1999-2021 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN* | MSYS*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/* | msys/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/config.guess b/config.guess new file mode 100755 index 0000000..f50dcdb --- /dev/null +++ b/config.guess @@ -0,0 +1,1480 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2018 Free Software Foundation, Inc. + +timestamp='2018-02-24' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2018 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > "$dummy.c" ; + for c in cc gcc c89 c99 ; do + if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "$UNAME_SYSTEM" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval "$set_cc_for_build" + cat <<-EOF > "$dummy.c" + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ + echo unknown)` + case "$UNAME_MACHINE_ARCH" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown + ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval "$set_cc_for_build" + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "$UNAME_VERSION" in + Debian*) + release='-gnu' + ;; + *) + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "$machine-${os}${release}${abi}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" + exit ;; + *:ekkoBSD:*:*) + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" + exit ;; + *:SolidBSD:*:*) + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:MirBSD:*:*) + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE=alpha ;; + "EV4.5 (21064)") + UNAME_MACHINE=alpha ;; + "LCA4 (21066/21068)") + UNAME_MACHINE=alpha ;; + "EV5 (21164)") + UNAME_MACHINE=alphaev5 ;; + "EV5.6 (21164A)") + UNAME_MACHINE=alphaev56 ;; + "EV5.6 (21164PC)") + UNAME_MACHINE=alphapca56 ;; + "EV5.7 (21164PC)") + UNAME_MACHINE=alphapca57 ;; + "EV6 (21264)") + UNAME_MACHINE=alphaev6 ;; + "EV6.7 (21264A)") + UNAME_MACHINE=alphaev67 ;; + "EV6.8CB (21264C)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8AL (21264B)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8CX (21264D)") + UNAME_MACHINE=alphaev68 ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE=alphaev69 ;; + "EV7 (21364)") + UNAME_MACHINE=alphaev7 ;; + "EV7.9 (21364A)") + UNAME_MACHINE=alphaev79 ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix"$UNAME_RELEASE" + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux"$UNAME_RELEASE" + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval "$set_cc_for_build" + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos"$UNAME_RELEASE" + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos"$UNAME_RELEASE" + ;; + sun4) + echo sparc-sun-sunos"$UNAME_RELEASE" + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos"$UNAME_RELEASE" + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint"$UNAME_RELEASE" + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint"$UNAME_RELEASE" + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint"$UNAME_RELEASE" + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten"$UNAME_RELEASE" + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten"$UNAME_RELEASE" + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix"$UNAME_RELEASE" + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix"$UNAME_RELEASE" + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix"$UNAME_RELEASE" + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos"$UNAME_RELEASE" + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] + then + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] + then + echo m88k-dg-dgux"$UNAME_RELEASE" + else + echo m88k-dg-dguxbcs"$UNAME_RELEASE" + fi + else + echo i586-dg-dgux"$UNAME_RELEASE" + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "$sc_cpu_version" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "$sc_kernel_bits" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "$HP_ARCH" = "" ]; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ "$HP_ARCH" = hppa2.0w ] + then + eval "$set_cc_for_build" + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH=hppa2.0w + else + HP_ARCH=hppa64 + fi + fi + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" + exit ;; + 3050*:HI-UX:*:*) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo "$UNAME_MACHINE"-unknown-osf1mk + else + echo "$UNAME_MACHINE"-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi"$UNAME_RELEASE" + exit ;; + *:BSD/OS:*:*) + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case "$UNAME_PROCESSOR" in + amd64) + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; + esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" + exit ;; + i*:CYGWIN*:*) + echo "$UNAME_MACHINE"-pc-cygwin + exit ;; + *:MINGW64*:*) + echo "$UNAME_MACHINE"-pc-mingw64 + exit ;; + *:MINGW*:*) + echo "$UNAME_MACHINE"-pc-mingw32 + exit ;; + *:MSYS*:*) + echo "$UNAME_MACHINE"-pc-msys + exit ;; + i*:PW*:*) + echo "$UNAME_MACHINE"-pc-pw32 + exit ;; + *:Interix*:*) + case "$UNAME_MACHINE" in + x86) + echo i586-pc-interix"$UNAME_RELEASE" + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix"$UNAME_RELEASE" + exit ;; + IA64) + echo ia64-unknown-interix"$UNAME_RELEASE" + exit ;; + esac ;; + i*:UWIN*:*) + echo "$UNAME_MACHINE"-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + *:GNU:*:*) + # the GNU system + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" + exit ;; + i*86:Minix:*:*) + echo "$UNAME_MACHINE"-pc-minix + exit ;; + aarch64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arm*:Linux:*:*) + eval "$set_cc_for_build" + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi + else + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + cris:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + crisv32:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + frv:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + hexagon:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:Linux:*:*) + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + exit ;; + ia64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m32r*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m68*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" + test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } + ;; + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-"$LIBC" + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-"$LIBC" + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-"$LIBC" + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-"$LIBC" + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-"$LIBC" + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-"$LIBC" + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" + exit ;; + sh64*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sh*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + tile*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + vax:Linux:*:*) + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" + exit ;; + x86_64:Linux:*:*) + if objdump -f /bin/sh | grep -q elf32-x86-64; then + echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 + else + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + fi + exit ;; + xtensa*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo "$UNAME_MACHINE"-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo "$UNAME_MACHINE"-unknown-stop + exit ;; + i*86:atheos:*:*) + echo "$UNAME_MACHINE"-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo "$UNAME_MACHINE"-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos"$UNAME_RELEASE" + exit ;; + i*86:*DOS:*:*) + echo "$UNAME_MACHINE"-pc-msdosdjgpp + exit ;; + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos"$UNAME_RELEASE" + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos"$UNAME_RELEASE" + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos"$UNAME_RELEASE" + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos"$UNAME_RELEASE" + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv"$UNAME_RELEASE" + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo "$UNAME_MACHINE"-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo "$UNAME_MACHINE"-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux"$UNAME_RELEASE" + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv"$UNAME_RELEASE" + else + echo mips-unknown-sysv"$UNAME_RELEASE" + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux"$UNAME_RELEASE" + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux"$UNAME_RELEASE" + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux"$UNAME_RELEASE" + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux"$UNAME_RELEASE" + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody"$UNAME_RELEASE" + exit ;; + *:Rhapsody:*:*) + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval "$set_cc_for_build" + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = x86; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = 386; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo "$UNAME_MACHINE"-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux"$UNAME_RELEASE" + exit ;; + *:DragonFly:*:*) + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "$UNAME_MACHINE" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" + exit ;; + i*86:rdos:*:*) + echo "$UNAME_MACHINE"-pc-rdos + exit ;; + i*86:AROS:*:*) + echo "$UNAME_MACHINE"-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo "$UNAME_MACHINE"-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; +esac + +echo "$0: unable to guess system type" >&2 + +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 </dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-functions 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.h b/config.h new file mode 100644 index 0000000..40ee13b --- /dev/null +++ b/config.h @@ -0,0 +1,197 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* build only butt-client */ +/* #undef CLIENT_ONLY */ + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +#define ENABLE_NLS 1 + +/* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the + CoreFoundation framework. */ +/* #undef HAVE_CFLOCALECOPYCURRENT */ + +/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in + the CoreFoundation framework. */ +/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */ + +/* Use dbus to get current tracks */ +#define HAVE_DBUS 1 + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +#define HAVE_DCGETTEXT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `gethostbyaddr' function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the `gethostbyname' function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#define HAVE_GETTEXT 1 + +/* Define if you have the iconv() function and it works. */ +/* #undef HAVE_ICONV */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +#define HAVE_LIBCRYPTO 1 + +/* Define to 1 if you have the `curl' library (-lcurl). */ +#define HAVE_LIBCURL 1 + +/* Define to 1 if you have the `datachannel' library (-ldatachannel). */ +/* #undef HAVE_LIBDATACHANNEL */ + +/* Define to 1 if you have the `FLAC' library (-lFLAC). */ +#define HAVE_LIBFLAC 1 + +/* Define to 1 if you have the `mp3lame' library (-lmp3lame). */ +#define HAVE_LIBMP3LAME 1 + +/* Define to 1 if you have the `ogg' library (-logg). */ +#define HAVE_LIBOGG 1 + +/* Define to 1 if you have the `opus' library (-lopus). */ +#define HAVE_LIBOPUS 1 + +/* Define to 1 if you have the `portaudio' library (-lportaudio). */ +#define HAVE_LIBPORTAUDIO 1 + +/* Define to 1 if you have the `portmidi' library (-lportmidi). */ +#define HAVE_LIBPORTMIDI 1 + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#define HAVE_LIBPTHREAD 1 + +/* Define to 1 if you have the `samplerate' library (-lsamplerate). */ +#define HAVE_LIBSAMPLERATE 1 + +/* Define to 1 if you have the `ssl' library (-lssl). */ +#define HAVE_LIBSSL 1 + +/* Define to 1 if you have the `vorbis' library (-lvorbis). */ +#define HAVE_LIBVORBIS 1 + +/* Define to 1 if you have the `vorbisenc' library (-lvorbisenc). */ +#define HAVE_LIBVORBISENC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the `pow' function. */ +/* #undef HAVE_POW */ + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if stdbool.h conforms to C99. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strpbrk' function. */ +#define HAVE_STRPBRK 1 + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `X509_check_host' function. */ +#define HAVE_X509_CHECK_HOST 1 + +/* Define to 1 if the system has the type `_Bool'. */ +#define HAVE__BOOL 1 + +/* Name of package */ +#define PACKAGE "butt" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "BUG-REPORT-ADDRESS" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "butt" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "butt 1.45.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "butt" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.45.0" + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.45.0" + +/* build butt and butt-client */ +/* #undef WITH_CLIENT */ + +/* Enable support for Radio.co authentification */ +/* #undef WITH_RADIOCO */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..e80af53 --- /dev/null +++ b/config.h.in @@ -0,0 +1,196 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* build only butt-client */ +#undef CLIENT_ONLY + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +#undef ENABLE_NLS + +/* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the + CoreFoundation framework. */ +#undef HAVE_CFLOCALECOPYCURRENT + +/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in + the CoreFoundation framework. */ +#undef HAVE_CFPREFERENCESCOPYAPPVALUE + +/* Use dbus to get current tracks */ +#undef HAVE_DBUS + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +#undef HAVE_DCGETTEXT + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `gethostbyaddr' function. */ +#undef HAVE_GETHOSTBYADDR + +/* Define to 1 if you have the `gethostbyname' function. */ +#undef HAVE_GETHOSTBYNAME + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#undef HAVE_GETTEXT + +/* Define if you have the iconv() function and it works. */ +#undef HAVE_ICONV + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +#undef HAVE_LIBCRYPTO + +/* Define to 1 if you have the `curl' library (-lcurl). */ +#undef HAVE_LIBCURL + +/* Define to 1 if you have the `datachannel' library (-ldatachannel). */ +#undef HAVE_LIBDATACHANNEL + +/* Define to 1 if you have the `FLAC' library (-lFLAC). */ +#undef HAVE_LIBFLAC + +/* Define to 1 if you have the `mp3lame' library (-lmp3lame). */ +#undef HAVE_LIBMP3LAME + +/* Define to 1 if you have the `ogg' library (-logg). */ +#undef HAVE_LIBOGG + +/* Define to 1 if you have the `opus' library (-lopus). */ +#undef HAVE_LIBOPUS + +/* Define to 1 if you have the `portaudio' library (-lportaudio). */ +#undef HAVE_LIBPORTAUDIO + +/* Define to 1 if you have the `portmidi' library (-lportmidi). */ +#undef HAVE_LIBPORTMIDI + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#undef HAVE_LIBPTHREAD + +/* Define to 1 if you have the `samplerate' library (-lsamplerate). */ +#undef HAVE_LIBSAMPLERATE + +/* Define to 1 if you have the `ssl' library (-lssl). */ +#undef HAVE_LIBSSL + +/* Define to 1 if you have the `vorbis' library (-lvorbis). */ +#undef HAVE_LIBVORBIS + +/* Define to 1 if you have the `vorbisenc' library (-lvorbisenc). */ +#undef HAVE_LIBVORBISENC + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the `pow' function. */ +#undef HAVE_POW + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the `socket' function. */ +#undef HAVE_SOCKET + +/* Define to 1 if stdbool.h conforms to C99. */ +#undef HAVE_STDBOOL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strpbrk' function. */ +#undef HAVE_STRPBRK + +/* Define to 1 if you have the `strrchr' function. */ +#undef HAVE_STRRCHR + +/* Define to 1 if you have the `strstr' function. */ +#undef HAVE_STRSTR + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `X509_check_host' function. */ +#undef HAVE_X509_CHECK_HOST + +/* Define to 1 if the system has the type `_Bool'. */ +#undef HAVE__BOOL + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* build butt and butt-client */ +#undef WITH_CLIENT + +/* Enable support for Radio.co authentification */ +#undef WITH_RADIOCO + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif diff --git a/config.rpath b/config.rpath new file mode 100755 index 0000000..ab6fd99 --- /dev/null +++ b/config.rpath @@ -0,0 +1,690 @@ +#! /bin/sh +# Output a system dependent set of variables, describing how to set the +# run time search path of shared libraries in an executable. +# +# Copyright 1996-2014 Free Software Foundation, Inc. +# Taken from GNU libtool, 2001 +# Originally by Gordon Matzigkeit , 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# The first argument passed to this file is the canonical host specification, +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld +# should be set by the caller. +# +# The set of defined variables is at the end of this script. + +# Known limitations: +# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer +# than 256 bytes, otherwise the compiler driver will dump core. The only +# known workaround is to choose shorter directory names for the build +# directory and/or the installation directory. + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +shrext=.so + +host="$1" +host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +# Code taken from libtool.m4's _LT_CC_BASENAME. + +for cc_temp in $CC""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` + +# Code taken from libtool.m4's _LT_COMPILER_PIC. + +wl= +if test "$GCC" = yes; then + wl='-Wl,' +else + case "$host_os" in + aix*) + wl='-Wl,' + ;; + mingw* | cygwin* | pw32* | os2* | cegcc*) + ;; + hpux9* | hpux10* | hpux11*) + wl='-Wl,' + ;; + irix5* | irix6* | nonstopux*) + wl='-Wl,' + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + ecc*) + wl='-Wl,' + ;; + icc* | ifort*) + wl='-Wl,' + ;; + lf95*) + wl='-Wl,' + ;; + nagfor*) + wl='-Wl,-Wl,,' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + wl='-Wl,' + ;; + ccc*) + wl='-Wl,' + ;; + xl* | bgxl* | bgf* | mpixl*) + wl='-Wl,' + ;; + como) + wl='-lopt=' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + wl= + ;; + *Sun\ C*) + wl='-Wl,' + ;; + esac + ;; + esac + ;; + newsos6) + ;; + *nto* | *qnx*) + ;; + osf3* | osf4* | osf5*) + wl='-Wl,' + ;; + rdos*) + ;; + solaris*) + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + wl='-Qoption ld ' + ;; + *) + wl='-Wl,' + ;; + esac + ;; + sunos4*) + wl='-Qoption ld ' + ;; + sysv4 | sysv4.2uw2* | sysv4.3*) + wl='-Wl,' + ;; + sysv4*MP*) + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + wl='-Wl,' + ;; + unicos*) + wl='-Wl,' + ;; + uts4*) + ;; + esac +fi + +# Code taken from libtool.m4's _LT_LINKER_SHLIBS. + +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no + +case "$host_os" in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + # Unlike libtool, we use -rpath here, not --rpath, since the documented + # option of GNU ld is called -rpath, not --rpath. + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + case "$host_os" in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + fi + ;; + amigaos*) + case "$host_cpu" in + powerpc) + ;; + m68k) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + cygwin* | mingw* | pw32* | cegcc*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + haiku*) + ;; + interix[3-9]*) + hardcode_direct=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + netbsd*) + ;; + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + else + ld_shlibs=no + fi + ;; + esac + ;; + sunos4*) + hardcode_direct=yes + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + esac + if test "$ld_shlibs" = no; then + hardcode_libdir_flag_spec= + fi +else + case "$host_os" in + aix3*) + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + else + aix_use_runtimelinking=no + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + fi + hardcode_direct=yes + hardcode_libdir_separator=':' + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + fi + # Begin _LT_AC_SYS_LIBPATH_AIX. + echo 'int main () { return 0; }' > conftest.c + ${CC} ${LDFLAGS} conftest.c -o conftest + aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + fi + if test -z "$aix_libpath"; then + aix_libpath="/usr/lib:/lib" + fi + rm -f conftest.c conftest + # End _LT_AC_SYS_LIBPATH_AIX. + if test "$aix_use_runtimelinking" = yes; then + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + else + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + fi + fi + ;; + amigaos*) + case "$host_cpu" in + powerpc) + ;; + m68k) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + bsdi[45]*) + ;; + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + libext=lib + ;; + darwin* | rhapsody*) + hardcode_direct=no + if { case $cc_basename in ifort*) true;; *) test "$GCC" = yes;; esac; }; then + : + else + ld_shlibs=no + fi + ;; + dgux*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + freebsd2.2*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + freebsd2*) + hardcode_direct=yes + hardcode_minus_L=yes + ;; + freebsd* | dragonfly*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + hpux9*) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + hpux10*) + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + hpux11*) + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + ;; + *) + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + irix5* | irix6* | nonstopux*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + netbsd*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + newsos6) + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + *nto* | *qnx*) + ;; + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + else + case "$host_os" in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + osf3*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + osf4* | osf5*) + if test "$GCC" = yes; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + # Both cc and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + solaris*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + sunos4*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + ;; + sysv4) + case $host_vendor in + sni) + hardcode_direct=yes # is this really true??? + ;; + siemens) + hardcode_direct=no + ;; + motorola) + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + ;; + sysv4.3*) + ;; + sysv4*MP*) + if test -d /usr/nec; then + ld_shlibs=yes + fi + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + ;; + sysv5* | sco3.2v5* | sco5v6*) + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator=':' + ;; + uts4*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + *) + ld_shlibs=no + ;; + esac +fi + +# Check dynamic linker characteristics +# Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER. +# Unlike libtool.m4, here we don't care about _all_ names of the library, but +# only about the one the linker finds when passed -lNAME. This is the last +# element of library_names_spec in libtool.m4, or possibly two of them if the +# linker has special search rules. +library_names_spec= # the last element of library_names_spec in libtool.m4 +libname_spec='lib$name' +case "$host_os" in + aix3*) + library_names_spec='$libname.a' + ;; + aix[4-9]*) + library_names_spec='$libname$shrext' + ;; + amigaos*) + case "$host_cpu" in + powerpc*) + library_names_spec='$libname$shrext' ;; + m68k) + library_names_spec='$libname.a' ;; + esac + ;; + beos*) + library_names_spec='$libname$shrext' + ;; + bsdi[45]*) + library_names_spec='$libname$shrext' + ;; + cygwin* | mingw* | pw32* | cegcc*) + shrext=.dll + library_names_spec='$libname.dll.a $libname.lib' + ;; + darwin* | rhapsody*) + shrext=.dylib + library_names_spec='$libname$shrext' + ;; + dgux*) + library_names_spec='$libname$shrext' + ;; + freebsd* | dragonfly*) + case "$host_os" in + freebsd[123]*) + library_names_spec='$libname$shrext$versuffix' ;; + *) + library_names_spec='$libname$shrext' ;; + esac + ;; + gnu*) + library_names_spec='$libname$shrext' + ;; + haiku*) + library_names_spec='$libname$shrext' + ;; + hpux9* | hpux10* | hpux11*) + case $host_cpu in + ia64*) + shrext=.so + ;; + hppa*64*) + shrext=.sl + ;; + *) + shrext=.sl + ;; + esac + library_names_spec='$libname$shrext' + ;; + interix[3-9]*) + library_names_spec='$libname$shrext' + ;; + irix5* | irix6* | nonstopux*) + library_names_spec='$libname$shrext' + case "$host_os" in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; + *) libsuff= shlibsuff= ;; + esac + ;; + esac + ;; + linux*oldld* | linux*aout* | linux*coff*) + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + library_names_spec='$libname$shrext' + ;; + knetbsd*-gnu) + library_names_spec='$libname$shrext' + ;; + netbsd*) + library_names_spec='$libname$shrext' + ;; + newsos6) + library_names_spec='$libname$shrext' + ;; + *nto* | *qnx*) + library_names_spec='$libname$shrext' + ;; + openbsd*) + library_names_spec='$libname$shrext$versuffix' + ;; + os2*) + libname_spec='$name' + shrext=.dll + library_names_spec='$libname.a' + ;; + osf3* | osf4* | osf5*) + library_names_spec='$libname$shrext' + ;; + rdos*) + ;; + solaris*) + library_names_spec='$libname$shrext' + ;; + sunos4*) + library_names_spec='$libname$shrext$versuffix' + ;; + sysv4 | sysv4.3*) + library_names_spec='$libname$shrext' + ;; + sysv4*MP*) + library_names_spec='$libname$shrext' + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + library_names_spec='$libname$shrext' + ;; + tpf*) + library_names_spec='$libname$shrext' + ;; + uts4*) + library_names_spec='$libname$shrext' + ;; +esac + +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' +escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` +shlibext=`echo "$shrext" | sed -e 's,^\.,,'` +escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` +escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` +escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` + +LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS + +Canonicalize a configuration name. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2018 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo "$1" + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo "$1" | sed 's/-[^-]*$//'` + if [ "$basic_machine" != "$1" ] + then os=`echo "$1" | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | wasm32 \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ + | pyramid-* \ + | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | wasm32-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-pc + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + asmjs) + basic_machine=asmjs-unknown + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2*) + basic_machine=m68k-bull + os=-sysv3 + ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=$os"spe" + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + x64) + basic_machine=x86_64-pc + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases that might get confused + # with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # es1800 is here to avoid being matched by es* (a different OS) + -es1800*) + os=-ose + ;; + # Now accept the basic system types. + # The portable systems comes first. + # Each alternative MUST end in a * to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ + | -midnightbsd*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -xray | -os68k* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo "$os" | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4*) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; + -nacl*) + ;; + -ios) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + pru-*) + os=-elf + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` + ;; +esac + +echo "$basic_machine$os" +exit + +# Local variables: +# eval: (add-hook 'write-file-functions 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 0000000..b9af219 --- /dev/null +++ b/configure @@ -0,0 +1,12011 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.71 for butt 1.45.0. +# +# Report bugs to . +# +# +# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, +# Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +as_nop=: +if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 +then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else $as_nop + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + + +# Reset variables that may have inherited troublesome values from +# the environment. + +# IFS needs to be set, to space, tab, and newline, in precisely that order. +# (If _AS_PATH_WALK were called with IFS unset, it would have the +# side effect of setting IFS to empty, thus disabling word splitting.) +# Quoting is to prevent editors from complaining about space-tab. +as_nl=' +' +export as_nl +IFS=" "" $as_nl" + +PS1='$ ' +PS2='> ' +PS4='+ ' + +# Ensure predictable behavior from utilities with locale-dependent output. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# We cannot yet rely on "unset" to work, but we need these variables +# to be unset--not just set to an empty or harmless value--now, to +# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct +# also avoids known problems related to "unset" and subshell syntax +# in other old shells (e.g. bash 2.01 and pdksh 5.2.14). +for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH +do eval test \${$as_var+y} \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done + +# Ensure that fds 0, 1, and 2 are open. +if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi +if (exec 3>&2) ; then :; else exec 2>/dev/null; fi + +# The user is always right. +if ${PATH_SEPARATOR+false} :; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + test -r "$as_dir$0" && as_myself=$as_dir$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="as_nop=: +if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 +then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else \$as_nop + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ) +then : + +else \$as_nop + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +blah=\$(echo \$(echo blah)) +test x\"\$blah\" = xblah || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null +then : + as_have_required=yes +else $as_nop + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null +then : + +else $as_nop + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null +then : + CONFIG_SHELL=$as_shell as_have_required=yes + if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null +then : + break 2 +fi +fi + done;; + esac + as_found=false +done +IFS=$as_save_IFS +if $as_found +then : + +else $as_nop + if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null +then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi +fi + + + if test "x$CONFIG_SHELL" != x +then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno +then : + printf "%s\n" "$0: This script requires a shell more modern than all" + printf "%s\n" "$0: the shells that I found on your system." + if test ${ZSH_VERSION+y} ; then + printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" + printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." + else + printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and BUG-REPORT-ADDRESS +$0: about your system, including any error possibly output +$0: before this message. Then install a modern shell, or +$0: manually run the script under such a shell if you do +$0: have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit +# as_fn_nop +# --------- +# Do nothing but, unlike ":", preserve the value of $?. +as_fn_nop () +{ + return $? +} +as_nop=as_fn_nop + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null +then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else $as_nop + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null +then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else $as_nop + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + +# as_fn_nop +# --------- +# Do nothing but, unlike ":", preserve the value of $?. +as_fn_nop () +{ + return $? +} +as_nop=as_fn_nop + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + printf "%s\n" "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +# Determine whether it's possible to make 'echo' print without a newline. +# These variables are no longer used directly by Autoconf, but are AC_SUBSTed +# for compatibility with existing Makefiles. +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +# For backward compatibility with old third-party macros, we provide +# the shell variables $as_echo and $as_echo_n. New code should use +# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. +as_echo='printf %s\n' +as_echo_n='printf %s' + + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='butt' +PACKAGE_TARNAME='butt' +PACKAGE_VERSION='1.45.0' +PACKAGE_STRING='butt 1.45.0' +PACKAGE_BUGREPORT='BUG-REPORT-ADDRESS' +PACKAGE_URL='' + +ac_unique_file="config.h.in" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_STDIO_H +# include +#endif +#ifdef HAVE_STDLIB_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_header_c_list= +gt_needs= +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +XMKMF +DBUS_LIBS +DBUS_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +FLTKCONFIG +CLIENT_ONLY_FALSE +CLIENT_ONLY_TRUE +WITH_CLIENT_FALSE +WITH_CLIENT_TRUE +WITH_RADIOCO_FALSE +WITH_RADIOCO_TRUE +FREEBSD_FALSE +FREEBSD_TRUE +OSX_FALSE +OSX_TRUE +LINUX_FALSE +LINUX_TRUE +WINDOWS_FALSE +WINDOWS_TRUE +POSUB +LTLIBINTL +LIBINTL +INTLLIBS +LTLIBICONV +LIBICONV +INTL_MACOSX_LIBS +EGREP +GREP +CPP +XGETTEXT_EXTRA_OPTIONS +MSGMERGE +XGETTEXT_015 +XGETTEXT +GMSGFMT_015 +MSGFMT_015 +GMSGFMT +MSGFMT +GETTEXT_MACRO_VERSION +USE_NLS +SED +am__fastdepOBJC_FALSE +am__fastdepOBJC_TRUE +OBJCDEPMODE +ac_ct_OBJC +OBJCFLAGS +OBJC +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +ac_ct_CC +CFLAGS +CC +am__fastdepCXX_FALSE +am__fastdepCXX_TRUE +CXXDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CXX +CPPFLAGS +LDFLAGS +CXXFLAGS +CXX +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +CSCOPE +ETAGS +CTAGS +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +runstatedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL +am__quote' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_dependency_tracking +with_radioco +with_client +with_butt +enable_aac +enable_nls +with_gnu_ld +enable_rpath +with_libiconv_prefix +with_libintl_prefix +enable_webrtc +with_x +' + ac_precious_vars='build_alias +host_alias +target_alias +CXX +CXXFLAGS +LDFLAGS +LIBS +CPPFLAGS +CCC +CC +CFLAGS +OBJC +OBJCFLAGS +CPP +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +DBUS_CFLAGS +DBUS_LIBS +XMKMF' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: \`$ac_useropt'" + ac_useropt_orig=$ac_useropt + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: \`$ac_useropt'" + ac_useropt_orig=$ac_useropt + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: \`$ac_useropt'" + ac_useropt_orig=$ac_useropt + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: \`$ac_useropt'" + ac_useropt_orig=$ac_useropt + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir runstatedir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures butt 1.45.0 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/butt] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of butt 1.45.0:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --disable-aac Disable aac support + --disable-nls do not use Native Language Support + --disable-rpath do not hardcode runtime library paths + --enable-webrtc Enable WebRTC support + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-radioco Include support for Radio.co + --with-client Build butt and butt-client + --without-butt Build only butt-client + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib + --without-libiconv-prefix don't search for libiconv in includedir and libdir + --with-libintl-prefix[=DIR] search for libintl in DIR/include and DIR/lib + --without-libintl-prefix don't search for libintl in includedir and libdir + --with-x use the X Window System + +Some influential environment variables: + CXX C++ compiler command + CXXFLAGS C++ compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CC C compiler command + CFLAGS C compiler flags + OBJC Objective C compiler command + OBJCFLAGS Objective C compiler flags + CPP C preprocessor + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + DBUS_CFLAGS C compiler flags for DBUS, overriding pkg-config + DBUS_LIBS linker flags for DBUS, overriding pkg-config + XMKMF Path to xmkmf, Makefile generator for X Window System + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for configure.gnu first; this name is used for a wrapper for + # Metaconfig's "Configure" on case-insensitive file systems. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +butt configure 1.45.0 +generated by GNU Autoconf 2.71 + +Copyright (C) 2021 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest.beam + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext +then : + ac_retval=0 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest.beam + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext +then : + ac_retval=0 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_objc_try_compile LINENO +# ----------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_objc_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest.beam + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_objc_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext +then : + ac_retval=0 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_objc_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + } +then : + ac_retval=0 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +printf %s "checking for $2... " >&6; } +if eval test \${$3+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval "$3=yes" +else $as_nop + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +eval ac_res=\$$3 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + } +then : + ac_retval=0 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that +# executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then : + ac_retval=0 +else $as_nop + printf "%s\n" "$as_me: program exited with status $ac_status" >&5 + printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +printf %s "checking for $2... " >&6; } +if eval test \${$3+y} +then : + printf %s "(cached) " >&6 +else $as_nop + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main (void) +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main (void) +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + +else $as_nop + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +eval ac_res=\$$3 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +printf %s "checking for $2... " >&6; } +if eval test \${$3+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. */ + +#include +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main (void) +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + eval "$3=yes" +else $as_nop + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func +ac_configure_args_raw= +for ac_arg +do + case $ac_arg in + *\'*) + ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append ac_configure_args_raw " '$ac_arg'" +done + +case $ac_configure_args_raw in + *$as_nl*) + ac_safe_unquote= ;; + *) + ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. + ac_unsafe_a="$ac_unsafe_z#~" + ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" + ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; +esac + +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by butt $as_me 1.45.0, which was +generated by GNU Autoconf 2.71. Invocation command line was + + $ $0$ac_configure_args_raw + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + printf "%s\n" "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Sanitize IFS. + IFS=" "" $as_nl" + # Save into config.log some information that might help in debugging. + { + echo + + printf "%s\n" "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + printf "%s\n" "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + printf "%s\n" "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + printf "%s\n" "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + printf "%s\n" "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + printf "%s\n" "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + printf "%s\n" "$as_me: caught signal $ac_signal" + printf "%s\n" "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +printf "%s\n" "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h + +printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h + +printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h + +printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h + +printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h + +printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +if test -n "$CONFIG_SITE"; then + ac_site_files="$CONFIG_SITE" +elif test "x$prefix" != xNONE; then + ac_site_files="$prefix/share/config.site $prefix/etc/config.site" +else + ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" +fi + +for ac_site_file in $ac_site_files +do + case $ac_site_file in #( + */*) : + ;; #( + *) : + ac_site_file=./$ac_site_file ;; +esac + if test -f "$ac_site_file" && test -r "$ac_site_file"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +printf "%s\n" "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +printf "%s\n" "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Test code for whether the C++ compiler supports C++98 (global declarations) +ac_cxx_conftest_cxx98_globals=' +// Does the compiler advertise C++98 conformance? +#if !defined __cplusplus || __cplusplus < 199711L +# error "Compiler does not advertise C++98 conformance" +#endif + +// These inclusions are to reject old compilers that +// lack the unsuffixed header files. +#include +#include + +// and are *not* freestanding headers in C++98. +extern void assert (int); +namespace std { + extern int strcmp (const char *, const char *); +} + +// Namespaces, exceptions, and templates were all added after "C++ 2.0". +using std::exception; +using std::strcmp; + +namespace { + +void test_exception_syntax() +{ + try { + throw "test"; + } catch (const char *s) { + // Extra parentheses suppress a warning when building autoconf itself, + // due to lint rules shared with more typical C programs. + assert (!(strcmp) (s, "test")); + } +} + +template struct test_template +{ + T const val; + explicit test_template(T t) : val(t) {} + template T add(U u) { return static_cast(u) + val; } +}; + +} // anonymous namespace +' + +# Test code for whether the C++ compiler supports C++98 (body of main) +ac_cxx_conftest_cxx98_main=' + assert (argc); + assert (! argv[0]); +{ + test_exception_syntax (); + test_template tt (2.0); + assert (tt.add (4) == 6.0); + assert (true && !false); +} +' + +# Test code for whether the C++ compiler supports C++11 (global declarations) +ac_cxx_conftest_cxx11_globals=' +// Does the compiler advertise C++ 2011 conformance? +#if !defined __cplusplus || __cplusplus < 201103L +# error "Compiler does not advertise C++11 conformance" +#endif + +namespace cxx11test +{ + constexpr int get_val() { return 20; } + + struct testinit + { + int i; + double d; + }; + + class delegate + { + public: + delegate(int n) : n(n) {} + delegate(): delegate(2354) {} + + virtual int getval() { return this->n; }; + protected: + int n; + }; + + class overridden : public delegate + { + public: + overridden(int n): delegate(n) {} + virtual int getval() override final { return this->n * 2; } + }; + + class nocopy + { + public: + nocopy(int i): i(i) {} + nocopy() = default; + nocopy(const nocopy&) = delete; + nocopy & operator=(const nocopy&) = delete; + private: + int i; + }; + + // for testing lambda expressions + template Ret eval(Fn f, Ret v) + { + return f(v); + } + + // for testing variadic templates and trailing return types + template auto sum(V first) -> V + { + return first; + } + template auto sum(V first, Args... rest) -> V + { + return first + sum(rest...); + } +} +' + +# Test code for whether the C++ compiler supports C++11 (body of main) +ac_cxx_conftest_cxx11_main=' +{ + // Test auto and decltype + auto a1 = 6538; + auto a2 = 48573953.4; + auto a3 = "String literal"; + + int total = 0; + for (auto i = a3; *i; ++i) { total += *i; } + + decltype(a2) a4 = 34895.034; +} +{ + // Test constexpr + short sa[cxx11test::get_val()] = { 0 }; +} +{ + // Test initializer lists + cxx11test::testinit il = { 4323, 435234.23544 }; +} +{ + // Test range-based for + int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3, + 14, 19, 17, 8, 6, 20, 16, 2, 11, 1}; + for (auto &x : array) { x += 23; } +} +{ + // Test lambda expressions + using cxx11test::eval; + assert (eval ([](int x) { return x*2; }, 21) == 42); + double d = 2.0; + assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0); + assert (d == 5.0); + assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0); + assert (d == 5.0); +} +{ + // Test use of variadic templates + using cxx11test::sum; + auto a = sum(1); + auto b = sum(1, 2); + auto c = sum(1.0, 2.0, 3.0); +} +{ + // Test constructor delegation + cxx11test::delegate d1; + cxx11test::delegate d2(); + cxx11test::delegate d3(45); +} +{ + // Test override and final + cxx11test::overridden o1(55464); +} +{ + // Test nullptr + char *c = nullptr; +} +{ + // Test template brackets + test_template<::test_template> v(test_template(12)); +} +{ + // Unicode literals + char const *utf8 = u8"UTF-8 string \u2500"; + char16_t const *utf16 = u"UTF-8 string \u2500"; + char32_t const *utf32 = U"UTF-32 string \u2500"; +} +' + +# Test code for whether the C compiler supports C++11 (complete). +ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals} +${ac_cxx_conftest_cxx11_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_cxx_conftest_cxx98_main} + ${ac_cxx_conftest_cxx11_main} + return ok; +} +" + +# Test code for whether the C compiler supports C++98 (complete). +ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals} +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_cxx_conftest_cxx98_main} + return ok; +} +" + +# Test code for whether the C compiler supports C89 (global declarations) +ac_c_conftest_c89_globals=' +/* Does the compiler advertise C89 conformance? + Do not test the value of __STDC__, because some compilers set it to 0 + while being otherwise adequately conformant. */ +#if !defined __STDC__ +# error "Compiler does not advertise C89 conformance" +#endif + +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ +struct buf { int x; }; +struct buf * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not \xHH hex character constants. + These do not provoke an error unfortunately, instead are silently treated + as an "x". The following induces an error, until -std is added to get + proper ANSI mode. Curiously \x00 != x always comes out true, for an + array size at least. It is necessary to write \x00 == 0 to get something + that is true only with -std. */ +int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) '\''x'\'' +int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), + int, int);' + +# Test code for whether the C compiler supports C89 (body of main). +ac_c_conftest_c89_main=' +ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); +' + +# Test code for whether the C compiler supports C99 (global declarations) +ac_c_conftest_c99_globals=' +// Does the compiler advertise C99 conformance? +#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L +# error "Compiler does not advertise C99 conformance" +#endif + +#include +extern int puts (const char *); +extern int printf (const char *, ...); +extern int dprintf (int, const char *, ...); +extern void *malloc (size_t); + +// Check varargs macros. These examples are taken from C99 6.10.3.5. +// dprintf is used instead of fprintf to avoid needing to declare +// FILE and stderr. +#define debug(...) dprintf (2, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} + +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + #error "your preprocessor is broken" +#endif +#if BIG_OK +#else + #error "your preprocessor is broken" +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; + +typedef const char *ccp; + +static inline int +test_restrict (ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) + continue; + return 0; +} + +// Check varargs and va_copy. +static bool +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); + + const char *str = ""; + int number = 0; + float fnumber = 0; + + while (*format) + { + switch (*format++) + { + case '\''s'\'': // string + str = va_arg (args_copy, const char *); + break; + case '\''d'\'': // int + number = va_arg (args_copy, int); + break; + case '\''f'\'': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); + + return *str && number && fnumber; +} +' + +# Test code for whether the C compiler supports C99 (body of main). +ac_c_conftest_c99_main=' + // Check bool. + _Bool success = false; + success |= (argc != 0); + + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); + test_varargs_macros (); + + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; + + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[0] = argv[0][0]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' + || dynamic_array[ni.number - 1] != 543); +' + +# Test code for whether the C compiler supports C11 (global declarations) +ac_c_conftest_c11_globals=' +// Does the compiler advertise C11 conformance? +#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L +# error "Compiler does not advertise C11 conformance" +#endif + +// Check _Alignas. +char _Alignas (double) aligned_as_double; +char _Alignas (0) no_special_alignment; +extern char aligned_as_int; +char _Alignas (0) _Alignas (int) aligned_as_int; + +// Check _Alignof. +enum +{ + int_alignment = _Alignof (int), + int_array_alignment = _Alignof (int[100]), + char_alignment = _Alignof (char) +}; +_Static_assert (0 < -_Alignof (int), "_Alignof is signed"); + +// Check _Noreturn. +int _Noreturn does_not_return (void) { for (;;) continue; } + +// Check _Static_assert. +struct test_static_assert +{ + int x; + _Static_assert (sizeof (int) <= sizeof (long int), + "_Static_assert does not work in struct"); + long int y; +}; + +// Check UTF-8 literals. +#define u8 syntax error! +char const utf8_literal[] = u8"happens to be ASCII" "another string"; + +// Check duplicate typedefs. +typedef long *long_ptr; +typedef long int *long_ptr; +typedef long_ptr long_ptr; + +// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. +struct anonymous +{ + union { + struct { int i; int j; }; + struct { int k; long int l; } w; + }; + int m; +} v1; +' + +# Test code for whether the C compiler supports C11 (body of main). +ac_c_conftest_c11_main=' + _Static_assert ((offsetof (struct anonymous, i) + == offsetof (struct anonymous, w.k)), + "Anonymous union alignment botch"); + v1.i = 2; + v1.w.k = 5; + ok |= v1.i != 5; +' + +# Test code for whether the C compiler supports C11 (complete). +ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} +${ac_c_conftest_c99_globals} +${ac_c_conftest_c11_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_c_conftest_c89_main} + ${ac_c_conftest_c99_main} + ${ac_c_conftest_c11_main} + return ok; +} +" + +# Test code for whether the C compiler supports C99 (complete). +ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} +${ac_c_conftest_c99_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_c_conftest_c89_main} + ${ac_c_conftest_c99_main} + return ok; +} +" + +# Test code for whether the C compiler supports C89 (complete). +ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_c_conftest_c89_main} + return ok; +} +" + +as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" +as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" +as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" +as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" +as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" +as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" +as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" +as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" +as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" +gt_needs="$gt_needs " + +# Auxiliary files required by this configure script. +ac_aux_files="config.rpath compile config.guess config.sub missing install-sh" + +# Locations in which to look for auxiliary files. +ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.." + +# Search for a directory containing all of the required auxiliary files, +# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. +# If we don't find one directory that contains all the files we need, +# we report the set of missing files from the *first* directory in +# $ac_aux_dir_candidates and give up. +ac_missing_aux_files="" +ac_first_candidate=: +printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5 +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in $ac_aux_dir_candidates +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + as_found=: + + printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5 + ac_aux_dir_found=yes + ac_install_sh= + for ac_aux in $ac_aux_files + do + # As a special case, if "install-sh" is required, that requirement + # can be satisfied by any of "install-sh", "install.sh", or "shtool", + # and $ac_install_sh is set appropriately for whichever one is found. + if test x"$ac_aux" = x"install-sh" + then + if test -f "${as_dir}install-sh"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5 + ac_install_sh="${as_dir}install-sh -c" + elif test -f "${as_dir}install.sh"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5 + ac_install_sh="${as_dir}install.sh -c" + elif test -f "${as_dir}shtool"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5 + ac_install_sh="${as_dir}shtool install -c" + else + ac_aux_dir_found=no + if $ac_first_candidate; then + ac_missing_aux_files="${ac_missing_aux_files} install-sh" + else + break + fi + fi + else + if test -f "${as_dir}${ac_aux}"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5 + else + ac_aux_dir_found=no + if $ac_first_candidate; then + ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}" + else + break + fi + fi + fi + done + if test "$ac_aux_dir_found" = yes; then + ac_aux_dir="$as_dir" + break + fi + ac_first_candidate=false + + as_found=false +done +IFS=$as_save_IFS +if $as_found +then : + +else $as_nop + as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 +fi + + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +if test -f "${ac_aux_dir}config.guess"; then + ac_config_guess="$SHELL ${ac_aux_dir}config.guess" +fi +if test -f "${ac_aux_dir}config.sub"; then + ac_config_sub="$SHELL ${ac_aux_dir}config.sub" +fi +if test -f "$ac_aux_dir/configure"; then + ac_configure="$SHELL ${ac_aux_dir}configure" +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file' + and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +am__api_version='1.16' + + + + # Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +printf %s "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if test ${ac_cv_path_install+y} +then : + printf %s "(cached) " >&6 +else $as_nop + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + # Account for fact that we put trailing slashes in our PATH walk. +case $as_dir in #(( + ./ | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test ${ac_cv_path_install+y}; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +printf "%s\n" "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +printf %s "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"` + + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + + + if test x"${MISSING+set}" != xset; then + MISSING="\${SHELL} '$am_aux_dir/missing'" +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +printf "%s\n" "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_STRIP+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +printf "%s\n" "$STRIP" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_STRIP+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +printf "%s\n" "$ac_ct_STRIP" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5 +printf %s "checking for a race-free mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if test ${ac_cv_path_mkdir+y} +then : + printf %s "(cached) " >&6 +else $as_nop + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue + case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir ('*'coreutils) '* | \ + 'BusyBox '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test ${ac_cv_path_mkdir+y}; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +printf "%s\n" "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_AWK+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +printf "%s\n" "$AWK" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval test \${ac_cv_prog_make_${ac_make}_set+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + SET_MAKE= +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test ${enable_silent_rules+y} +then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +printf %s "checking whether $am_make supports nested variables... " >&6; } +if test ${am_cv_make_support_nested_variables+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if printf "%s\n" 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +printf "%s\n" "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='butt' + VERSION='1.45.0' + + +printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h + + +printf "%s\n" "#define VERSION \"$VERSION\"" >>confdefs.h + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar pax cpio none' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + +# Variables for tags utilities; see am/tags.am +if test -z "$CTAGS"; then + CTAGS=ctags +fi + +if test -z "$ETAGS"; then + ETAGS=etags +fi + +if test -z "$CSCOPE"; then + CSCOPE=cscope +fi + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + + + + # Make sure we can run config.sub. +$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5 + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +printf %s "checking build system type... " >&6; } +if test ${ac_cv_build+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +printf "%s\n" "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +printf %s "checking host system type... " >&6; } +if test ${ac_cv_host+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` || + as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +printf "%s\n" "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + + + +ac_config_headers="$ac_config_headers config.h" + + +#predefined CXXFLAGS so AC_PROG_CXX does not add the -g flag +CXXFLAGS="$CXXFLAGS -O2" + +# Compile with address sanitizer +# CXXFLAGS="$CXXFLAGS -O2 -g -fsanitize=address" + +# Checks for programs. + + + + + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CXX+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +printf "%s\n" "$CXX" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CXX+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +printf "%s\n" "$ac_ct_CXX" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5 +printf %s "checking whether the C++ compiler works... " >&6; } +ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else $as_nop + ac_file='' +fi +if test -z "$ac_file" +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C++ compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5 +printf %s "checking for C++ compiler default output file name... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +printf "%s\n" "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +printf %s "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else $as_nop + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +printf "%s\n" "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +printf %s "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot run C++ compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +printf "%s\n" "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +printf %s "checking for suffix of object files... " >&6; } +if test ${ac_cv_objext+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +printf "%s\n" "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5 +printf %s "checking whether the compiler supports GNU C++... " >&6; } +if test ${ac_cv_cxx_compiler_gnu+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + ac_compiler_gnu=yes +else $as_nop + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; } +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+y} +ac_save_CXXFLAGS=$CXXFLAGS +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +printf %s "checking whether $CXX accepts -g... " >&6; } +if test ${ac_cv_prog_cxx_g+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + ac_cv_prog_cxx_g=yes +else $as_nop + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + +else $as_nop + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +printf "%s\n" "$ac_cv_prog_cxx_g" >&6; } +if test $ac_test_CXXFLAGS; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_prog_cxx_stdcxx=no +if test x$ac_prog_cxx_stdcxx = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5 +printf %s "checking for $CXX option to enable C++11 features... " >&6; } +if test ${ac_cv_prog_cxx_11+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cxx_11=no +ac_save_CXX=$CXX +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_cxx_conftest_cxx11_program +_ACEOF +for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA +do + CXX="$ac_save_CXX $ac_arg" + if ac_fn_cxx_try_compile "$LINENO" +then : + ac_cv_prog_cxx_cxx11=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cxx_cxx11" != "xno" && break +done +rm -f conftest.$ac_ext +CXX=$ac_save_CXX +fi + +if test "x$ac_cv_prog_cxx_cxx11" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cxx_cxx11" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5 +printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; } + CXX="$CXX $ac_cv_prog_cxx_cxx11" +fi + ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11 + ac_prog_cxx_stdcxx=cxx11 +fi +fi +if test x$ac_prog_cxx_stdcxx = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5 +printf %s "checking for $CXX option to enable C++98 features... " >&6; } +if test ${ac_cv_prog_cxx_98+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cxx_98=no +ac_save_CXX=$CXX +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_cxx_conftest_cxx98_program +_ACEOF +for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA +do + CXX="$ac_save_CXX $ac_arg" + if ac_fn_cxx_try_compile "$LINENO" +then : + ac_cv_prog_cxx_cxx98=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cxx_cxx98" != "xno" && break +done +rm -f conftest.$ac_ext +CXX=$ac_save_CXX +fi + +if test "x$ac_cv_prog_cxx_cxx98" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cxx_cxx98" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5 +printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; } + CXX="$CXX $ac_cv_prog_cxx_cxx98" +fi + ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98 + ac_prog_cxx_stdcxx=cxx98 +fi +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 +printf %s "checking whether ${MAKE-make} supports the include directive... " >&6; } +cat > confinc.mk << 'END' +am__doit: + @echo this is the am__doit target >confinc.out +.PHONY: am__doit +END +am__include="#" +am__quote= +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 + (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + case $?:`cat confinc.out 2>/dev/null` in #( + '0:this is the am__doit target') : + case $s in #( + BSD) : + am__include='.include' am__quote='"' ;; #( + *) : + am__include='include' am__quote='' ;; +esac ;; #( + *) : + ;; +esac + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 +printf "%s\n" "${_am_result}" >&6; } + +# Check whether --enable-dependency-tracking was given. +if test ${enable_dependency_tracking+y} +then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CXX" am_compiler_list= + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +printf %s "checking dependency style of $depcc... " >&6; } +if test ${am_cv_CXX_dependencies_compiler_type+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 +printf "%s\n" "$am_cv_CXX_dependencies_compiler_type" >&6; } +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +printf "%s\n" "$ac_ct_CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +printf "%s\n" "$ac_ct_CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. +set dummy ${ac_tool_prefix}clang; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}clang" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "clang", so it can be a program name with args. +set dummy clang; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="clang" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +printf "%s\n" "$ac_ct_CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +fi + + +test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion -version; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 +printf %s "checking whether the compiler supports GNU C... " >&6; } +if test ${ac_cv_c_compiler_gnu+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_compiler_gnu=yes +else $as_nop + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+y} +ac_save_CFLAGS=$CFLAGS +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +printf %s "checking whether $CC accepts -g... " >&6; } +if test ${ac_cv_prog_cc_g+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_g=yes +else $as_nop + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + +else $as_nop + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +printf "%s\n" "$ac_cv_prog_cc_g" >&6; } +if test $ac_test_CFLAGS; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +ac_prog_cc_stdc=no +if test x$ac_prog_cc_stdc = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 +printf %s "checking for $CC option to enable C11 features... " >&6; } +if test ${ac_cv_prog_cc_c11+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cc_c11=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_c_conftest_c11_program +_ACEOF +for ac_arg in '' -std=gnu11 +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_c11=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cc_c11" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC +fi + +if test "x$ac_cv_prog_cc_c11" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cc_c11" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 +printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } + CC="$CC $ac_cv_prog_cc_c11" +fi + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 + ac_prog_cc_stdc=c11 +fi +fi +if test x$ac_prog_cc_stdc = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 +printf %s "checking for $CC option to enable C99 features... " >&6; } +if test ${ac_cv_prog_cc_c99+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_c_conftest_c99_program +_ACEOF +for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_c99=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cc_c99" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC +fi + +if test "x$ac_cv_prog_cc_c99" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cc_c99" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } + CC="$CC $ac_cv_prog_cc_c99" +fi + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 + ac_prog_cc_stdc=c99 +fi +fi +if test x$ac_prog_cc_stdc = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 +printf %s "checking for $CC option to enable C89 features... " >&6; } +if test ${ac_cv_prog_cc_c89+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_c_conftest_c89_program +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC +fi + +if test "x$ac_cv_prog_cc_c89" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cc_c89" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } + CC="$CC $ac_cv_prog_cc_c89" +fi + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 + ac_prog_cc_stdc=c89 +fi +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +printf %s "checking whether $CC understands -c and -o together... " >&6; } +if test ${am_cv_prog_cc_c_o+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +printf "%s\n" "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +depcc="$CC" am_compiler_list= + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +printf %s "checking dependency style of $depcc... " >&6; } +if test ${am_cv_CC_dependencies_compiler_type+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +ac_ext=m +ac_cpp='$OBJCPP $CPPFLAGS' +ac_compile='$OBJC -c $OBJCFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$OBJC -o conftest$ac_exeext $OBJCFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_objc_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in gcc objcc objc cc CC clang + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_OBJC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$OBJC"; then + ac_cv_prog_OBJC="$OBJC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJC="$ac_tool_prefix$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJC=$ac_cv_prog_OBJC +if test -n "$OBJC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OBJC" >&5 +printf "%s\n" "$OBJC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$OBJC" && break + done +fi +if test -z "$OBJC"; then + ac_ct_OBJC=$OBJC + for ac_prog in gcc objcc objc cc CC clang +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_OBJC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_OBJC"; then + ac_cv_prog_ac_ct_OBJC="$ac_ct_OBJC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJC="$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJC=$ac_cv_prog_ac_ct_OBJC +if test -n "$ac_ct_OBJC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJC" >&5 +printf "%s\n" "$ac_ct_OBJC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$ac_ct_OBJC" && break +done + + if test "x$ac_ct_OBJC" = x; then + OBJC="gcc" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJC=$ac_ct_OBJC + fi +fi + +# Provide some information about the compiler. +printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Objective C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU Objective C" >&5 +printf %s "checking whether the compiler supports GNU Objective C... " >&6; } +if test ${ac_cv_objc_compiler_gnu+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_objc_try_compile "$LINENO" +then : + ac_compiler_gnu=yes +else $as_nop + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +ac_cv_objc_compiler_gnu=$ac_compiler_gnu + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objc_compiler_gnu" >&5 +printf "%s\n" "$ac_cv_objc_compiler_gnu" >&6; } +ac_compiler_gnu=$ac_cv_objc_compiler_gnu + +if test $ac_compiler_gnu = yes; then + GOBJC=yes +else + GOBJC= +fi +ac_test_OBJCFLAGS=${OBJCFLAGS+y} +ac_save_OBJCFLAGS=$OBJCFLAGS +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $OBJC accepts -g" >&5 +printf %s "checking whether $OBJC accepts -g... " >&6; } +if test ${ac_cv_prog_objc_g+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_save_objc_werror_flag=$ac_objc_werror_flag + ac_objc_werror_flag=yes + ac_cv_prog_objc_g=no + OBJCFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_objc_try_compile "$LINENO" +then : + ac_cv_prog_objc_g=yes +else $as_nop + OBJCFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_objc_try_compile "$LINENO" +then : + +else $as_nop + ac_objc_werror_flag=$ac_save_objc_werror_flag + OBJCFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_objc_try_compile "$LINENO" +then : + ac_cv_prog_objc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + ac_objc_werror_flag=$ac_save_objc_werror_flag +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_objc_g" >&5 +printf "%s\n" "$ac_cv_prog_objc_g" >&6; } +if test $ac_test_OBJCFLAGS; then + OBJCFLAGS=$ac_save_OBJCFLAGS +elif test $ac_cv_prog_objc_g = yes; then + if test "$GOBJC" = yes; then + OBJCFLAGS="-g -O2" + else + OBJCFLAGS="-g" + fi +else + if test "$GOBJC" = yes; then + OBJCFLAGS="-O2" + else + OBJCFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$OBJC" am_compiler_list='gcc3 gcc' + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +printf %s "checking dependency style of $depcc... " >&6; } +if test ${am_cv_OBJC_dependencies_compiler_type+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_OBJC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_OBJC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_OBJC_dependencies_compiler_type=none +fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_OBJC_dependencies_compiler_type" >&5 +printf "%s\n" "$am_cv_OBJC_dependencies_compiler_type" >&6; } +OBJCDEPMODE=depmode=$am_cv_OBJC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_OBJC_dependencies_compiler_type" = gcc3; then + am__fastdepOBJC_TRUE= + am__fastdepOBJC_FALSE='#' +else + am__fastdepOBJC_TRUE='#' + am__fastdepOBJC_FALSE= +fi + + + +LDFLAGS="$LDFLAGS -L/usr/local/lib" + +# Compile with address sanitizer +#LDFLAGS="$LDFLAGS -L/usr/local/lib -fsanitize=address" + + + +# Check whether --with-radioco was given. +if test ${with_radioco+y} +then : + withval=$with_radioco; +fi + + + +# Check whether --with-client was given. +if test ${with_client+y} +then : + withval=$with_client; with_client=yes +fi + + + +# Check whether --with-butt was given. +if test ${with_butt+y} +then : + withval=$with_butt; client_only=yes +fi + + +# Check whether --enable-aac was given. +if test ${enable_aac+y} +then : + enableval=$enable_aac; +fi + + + +if test "x$with_radioco" = "xyes" +then : + + +printf "%s\n" "#define WITH_RADIOCO 1" >>confdefs.h + + +fi + +if test "x$client_only" = "xyes" +then : + + +printf "%s\n" "#define CLIENT_ONLY 1" >>confdefs.h + + +fi + +if test "x$with_client" = "xyes" +then : + + +printf "%s\n" "#define WITH_CLIENT 1" >>confdefs.h + + +fi + + +if test "x$client_only" != "xyes" +then : + +# Checks for libraries. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ogg_stream_init in -logg" >&5 +printf %s "checking for ogg_stream_init in -logg... " >&6; } +if test ${ac_cv_lib_ogg_ogg_stream_init+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-logg $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char ogg_stream_init (); +int +main (void) +{ +return ogg_stream_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_ogg_ogg_stream_init=yes +else $as_nop + ac_cv_lib_ogg_ogg_stream_init=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ogg_ogg_stream_init" >&5 +printf "%s\n" "$ac_cv_lib_ogg_ogg_stream_init" >&6; } +if test "x$ac_cv_lib_ogg_ogg_stream_init" = xyes +then : + printf "%s\n" "#define HAVE_LIBOGG 1" >>confdefs.h + + LIBS="-logg $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find libogg ****" "$LINENO" 5 + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for vorbis_info_init in -lvorbis" >&5 +printf %s "checking for vorbis_info_init in -lvorbis... " >&6; } +if test ${ac_cv_lib_vorbis_vorbis_info_init+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lvorbis $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char vorbis_info_init (); +int +main (void) +{ +return vorbis_info_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_vorbis_vorbis_info_init=yes +else $as_nop + ac_cv_lib_vorbis_vorbis_info_init=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vorbis_vorbis_info_init" >&5 +printf "%s\n" "$ac_cv_lib_vorbis_vorbis_info_init" >&6; } +if test "x$ac_cv_lib_vorbis_vorbis_info_init" = xyes +then : + printf "%s\n" "#define HAVE_LIBVORBIS 1" >>confdefs.h + + LIBS="-lvorbis $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find libvorbis ****" "$LINENO" 5 + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for vorbis_encode_init in -lvorbisenc" >&5 +printf %s "checking for vorbis_encode_init in -lvorbisenc... " >&6; } +if test ${ac_cv_lib_vorbisenc_vorbis_encode_init+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lvorbisenc $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char vorbis_encode_init (); +int +main (void) +{ +return vorbis_encode_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_vorbisenc_vorbis_encode_init=yes +else $as_nop + ac_cv_lib_vorbisenc_vorbis_encode_init=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vorbisenc_vorbis_encode_init" >&5 +printf "%s\n" "$ac_cv_lib_vorbisenc_vorbis_encode_init" >&6; } +if test "x$ac_cv_lib_vorbisenc_vorbis_encode_init" = xyes +then : + printf "%s\n" "#define HAVE_LIBVORBISENC 1" >>confdefs.h + + LIBS="-lvorbisenc $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find libvorbisenc ****" "$LINENO" 5 + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for opus_encoder_create in -lopus" >&5 +printf %s "checking for opus_encoder_create in -lopus... " >&6; } +if test ${ac_cv_lib_opus_opus_encoder_create+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lopus $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char opus_encoder_create (); +int +main (void) +{ +return opus_encoder_create (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_opus_opus_encoder_create=yes +else $as_nop + ac_cv_lib_opus_opus_encoder_create=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_opus_opus_encoder_create" >&5 +printf "%s\n" "$ac_cv_lib_opus_opus_encoder_create" >&6; } +if test "x$ac_cv_lib_opus_opus_encoder_create" = xyes +then : + printf "%s\n" "#define HAVE_LIBOPUS 1" >>confdefs.h + + LIBS="-lopus $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find libopus ****" "$LINENO" 5 + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for lame_init in -lmp3lame" >&5 +printf %s "checking for lame_init in -lmp3lame... " >&6; } +if test ${ac_cv_lib_mp3lame_lame_init+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lmp3lame $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char lame_init (); +int +main (void) +{ +return lame_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_mp3lame_lame_init=yes +else $as_nop + ac_cv_lib_mp3lame_lame_init=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mp3lame_lame_init" >&5 +printf "%s\n" "$ac_cv_lib_mp3lame_lame_init" >&6; } +if test "x$ac_cv_lib_mp3lame_lame_init" = xyes +then : + printf "%s\n" "#define HAVE_LIBMP3LAME 1" >>confdefs.h + + LIBS="-lmp3lame $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find libmp3lame ****" "$LINENO" 5 + + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for FLAC__stream_encoder_new in -lFLAC" >&5 +printf %s "checking for FLAC__stream_encoder_new in -lFLAC... " >&6; } +if test ${ac_cv_lib_FLAC_FLAC__stream_encoder_new+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lFLAC $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char FLAC__stream_encoder_new (); +int +main (void) +{ +return FLAC__stream_encoder_new (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_FLAC_FLAC__stream_encoder_new=yes +else $as_nop + ac_cv_lib_FLAC_FLAC__stream_encoder_new=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_FLAC_FLAC__stream_encoder_new" >&5 +printf "%s\n" "$ac_cv_lib_FLAC_FLAC__stream_encoder_new" >&6; } +if test "x$ac_cv_lib_FLAC_FLAC__stream_encoder_new" = xyes +then : + printf "%s\n" "#define HAVE_LIBFLAC 1" >>confdefs.h + + LIBS="-lFLAC $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find libFLAC ****" "$LINENO" 5 + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Pa_Initialize in -lportaudio" >&5 +printf %s "checking for Pa_Initialize in -lportaudio... " >&6; } +if test ${ac_cv_lib_portaudio_Pa_Initialize+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lportaudio $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char Pa_Initialize (); +int +main (void) +{ +return Pa_Initialize (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_portaudio_Pa_Initialize=yes +else $as_nop + ac_cv_lib_portaudio_Pa_Initialize=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_portaudio_Pa_Initialize" >&5 +printf "%s\n" "$ac_cv_lib_portaudio_Pa_Initialize" >&6; } +if test "x$ac_cv_lib_portaudio_Pa_Initialize" = xyes +then : + printf "%s\n" "#define HAVE_LIBPORTAUDIO 1" >>confdefs.h + + LIBS="-lportaudio $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find libportaudio ****" "$LINENO" 5 + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Pm_Initialize in -lportmidi" >&5 +printf %s "checking for Pm_Initialize in -lportmidi... " >&6; } +if test ${ac_cv_lib_portmidi_Pm_Initialize+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lportmidi $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char Pm_Initialize (); +int +main (void) +{ +return Pm_Initialize (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_portmidi_Pm_Initialize=yes +else $as_nop + ac_cv_lib_portmidi_Pm_Initialize=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_portmidi_Pm_Initialize" >&5 +printf "%s\n" "$ac_cv_lib_portmidi_Pm_Initialize" >&6; } +if test "x$ac_cv_lib_portmidi_Pm_Initialize" = xyes +then : + printf "%s\n" "#define HAVE_LIBPORTMIDI 1" >>confdefs.h + + LIBS="-lportmidi $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find libportmidi ****" "$LINENO" 5 + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for src_new in -lsamplerate" >&5 +printf %s "checking for src_new in -lsamplerate... " >&6; } +if test ${ac_cv_lib_samplerate_src_new+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsamplerate $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char src_new (); +int +main (void) +{ +return src_new (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_samplerate_src_new=yes +else $as_nop + ac_cv_lib_samplerate_src_new=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_samplerate_src_new" >&5 +printf "%s\n" "$ac_cv_lib_samplerate_src_new" >&6; } +if test "x$ac_cv_lib_samplerate_src_new" = xyes +then : + printf "%s\n" "#define HAVE_LIBSAMPLERATE 1" >>confdefs.h + + LIBS="-lsamplerate $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find samplerate ****" "$LINENO" 5 + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5 +printf %s "checking for pthread_create in -lpthread... " >&6; } +if test ${ac_cv_lib_pthread_pthread_create+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char pthread_create (); +int +main (void) +{ +return pthread_create (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_pthread_pthread_create=yes +else $as_nop + ac_cv_lib_pthread_pthread_create=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5 +printf "%s\n" "$ac_cv_lib_pthread_pthread_create" >&6; } +if test "x$ac_cv_lib_pthread_pthread_create" = xyes +then : + printf "%s\n" "#define HAVE_LIBPTHREAD 1" >>confdefs.h + + LIBS="-lpthread $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find libpthread ****" "$LINENO" 5 + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for curl_global_init in -lcurl" >&5 +printf %s "checking for curl_global_init in -lcurl... " >&6; } +if test ${ac_cv_lib_curl_curl_global_init+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcurl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char curl_global_init (); +int +main (void) +{ +return curl_global_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_curl_curl_global_init=yes +else $as_nop + ac_cv_lib_curl_curl_global_init=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curl_curl_global_init" >&5 +printf "%s\n" "$ac_cv_lib_curl_curl_global_init" >&6; } +if test "x$ac_cv_lib_curl_curl_global_init" = xyes +then : + printf "%s\n" "#define HAVE_LIBCURL 1" >>confdefs.h + + LIBS="-lcurl $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find libcurl ****" "$LINENO" 5 + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SSL_CTX_new in -lssl" >&5 +printf %s "checking for SSL_CTX_new in -lssl... " >&6; } +if test ${ac_cv_lib_ssl_SSL_CTX_new+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lssl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char SSL_CTX_new (); +int +main (void) +{ +return SSL_CTX_new (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_ssl_SSL_CTX_new=yes +else $as_nop + ac_cv_lib_ssl_SSL_CTX_new=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_CTX_new" >&5 +printf "%s\n" "$ac_cv_lib_ssl_SSL_CTX_new" >&6; } +if test "x$ac_cv_lib_ssl_SSL_CTX_new" = xyes +then : + printf "%s\n" "#define HAVE_LIBSSL 1" >>confdefs.h + + LIBS="-lssl $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find libssl ****" "$LINENO" 5 + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for EVP_EncryptInit in -lcrypto" >&5 +printf %s "checking for EVP_EncryptInit in -lcrypto... " >&6; } +if test ${ac_cv_lib_crypto_EVP_EncryptInit+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char EVP_EncryptInit (); +int +main (void) +{ +return EVP_EncryptInit (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_crypto_EVP_EncryptInit=yes +else $as_nop + ac_cv_lib_crypto_EVP_EncryptInit=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_EVP_EncryptInit" >&5 +printf "%s\n" "$ac_cv_lib_crypto_EVP_EncryptInit" >&6; } +if test "x$ac_cv_lib_crypto_EVP_EncryptInit" = xyes +then : + printf "%s\n" "#define HAVE_LIBCRYPTO 1" >>confdefs.h + + LIBS="-lcrypto $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find libcrypto ****" "$LINENO" 5 + +fi + + + +fi + +ac_header= ac_cache= +for ac_item in $ac_header_c_list +do + if test $ac_cache; then + ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" + if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then + printf "%s\n" "#define $ac_item 1" >> confdefs.h + fi + ac_header= ac_cache= + elif test $ac_header; then + ac_cache=$ac_item + else + ac_header=$ac_item + fi +done + + + + + + + + +if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes +then : + +printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "winsock2.h" "ac_cv_header_winsock2_h" "$ac_includes_default" +if test "x$ac_cv_header_winsock2_h" = xyes +then : + + LIBS="$LIBS -lws2_32" + host_os="windows" + +fi + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +printf %s "checking for a sed that does not truncate output... " >&6; } +if test ${ac_cv_path_SED+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_prog in sed gsed + do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + printf %s 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + printf "%s\n" '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +printf "%s\n" "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 +printf %s "checking whether NLS is requested... " >&6; } + # Check whether --enable-nls was given. +if test ${enable_nls+y} +then : + enableval=$enable_nls; USE_NLS=$enableval +else $as_nop + USE_NLS=yes +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +printf "%s\n" "$USE_NLS" >&6; } + + + + + GETTEXT_MACRO_VERSION=0.19 + + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_MSGFMT+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case "$MSGFMT" in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --statistics /dev/null >&5 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + ac_cv_path_MSGFMT="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test "$MSGFMT" != ":"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 +printf "%s\n" "$MSGFMT" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_GMSGFMT+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $GMSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_GMSGFMT="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT=$ac_cv_path_GMSGFMT +if test -n "$GMSGFMT"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 +printf "%s\n" "$GMSGFMT" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac + + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_XGETTEXT+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case "$XGETTEXT" in + [\\/]* | ?:[\\/]*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&5 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test "$XGETTEXT" != ":"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 +printf "%s\n" "$XGETTEXT" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + rm -f messages.po + + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "msgmerge", so it can be a program name with args. +set dummy msgmerge; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_MSGMERGE+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case "$MSGMERGE" in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --update -q /dev/null /dev/null >&5 2>&1; then + ac_cv_path_MSGMERGE="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_MSGMERGE" && ac_cv_path_MSGMERGE=":" + ;; +esac +fi +MSGMERGE="$ac_cv_path_MSGMERGE" +if test "$MSGMERGE" != ":"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 +printf "%s\n" "$MSGMERGE" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$localedir" || localedir='${datadir}/locale' + + + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + + + ac_config_commands="$ac_config_commands po-directories" + + + + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" + + + +# Check whether --with-gnu-ld was given. +if test ${with_gnu_ld+y} +then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else $as_nop + with_gnu_ld=no +fi + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +printf %s "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo "$ac_prog"| sed 's%\\\\%/%g'` + while echo "$ac_prog" | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +printf %s "checking for GNU ld... " >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +printf %s "checking for non-GNU ld... " >&6; } +fi +if test ${acl_cv_path_LD+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -z "$LD"; then + acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$acl_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 &5 +printf "%s\n" "$LD" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +printf %s "checking if the linker ($LD) is GNU ld... " >&6; } +if test ${acl_cv_prog_gnu_ld+y} +then : + printf %s "(cached) " >&6 +else $as_nop + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +printf "%s\n" "$acl_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$acl_cv_prog_gnu_ld + + + + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shared library run path origin" >&5 +printf %s "checking for shared library run path origin... " >&6; } +if test ${acl_cv_rpath+y} +then : + printf %s "(cached) " >&6 +else $as_nop + + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $acl_cv_rpath" >&5 +printf "%s\n" "$acl_cv_rpath" >&6; } + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + # Check whether --enable-rpath was given. +if test ${enable_rpath+y} +then : + enableval=$enable_rpath; : +else $as_nop + enable_rpath=yes +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +printf %s "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test ${ac_cv_prog_CPP+y} +then : + printf %s "(cached) " >&6 +else $as_nop + # Double quotes because $CC needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO" +then : + +else $as_nop + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO" +then : + # Broken: success on invalid input. +continue +else $as_nop + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok +then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +printf "%s\n" "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO" +then : + +else $as_nop + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO" +then : + # Broken: success on invalid input. +continue +else $as_nop + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok +then : + +else $as_nop + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +printf %s "checking for grep that handles long lines and -e... " >&6; } +if test ${ac_cv_path_GREP+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_prog in grep ggrep + do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + printf %s 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + printf "%s\n" 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +printf "%s\n" "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +printf %s "checking for egrep... " >&6; } +if test ${ac_cv_path_EGREP+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_prog in egrep + do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + printf %s 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + printf "%s\n" 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +printf "%s\n" "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + + + + acl_libdirstem=lib + acl_libdirstem2= + case "$host_os" in + solaris*) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit host" >&5 +printf %s "checking for 64-bit host... " >&6; } +if test ${gl_cv_solaris_64bit+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef _LP64 +sixtyfour bits +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "sixtyfour bits" >/dev/null 2>&1 +then : + gl_cv_solaris_64bit=yes +else $as_nop + gl_cv_solaris_64bit=no +fi +rm -rf conftest* + + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $gl_cv_solaris_64bit" >&5 +printf "%s\n" "$gl_cv_solaris_64bit" >&6; } + if test $gl_cv_solaris_64bit = yes; then + acl_libdirstem=lib/64 + case "$host_cpu" in + sparc*) acl_libdirstem2=lib/sparcv9 ;; + i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; + esac + fi + ;; + *) + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + */../ | */.. ) + # Better ignore directories of this form. They are misleading. + ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + ;; + esac + test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" + + + + + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libiconv-prefix was given. +if test ${with_libiconv_prefix+y} +then : + withval=$with_libiconv_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi + +fi + + LIBICONV= + LTLIBICONV= + INCICONV= + LIBICONV_PREFIX= + HAVE_LIBICONV= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='iconv ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = 'iconv'; then + LIBICONV_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = 'iconv'; then + LIBICONV_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBICONV="${LIBICONV}${LIBICONV:+ }$dep" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep" + ;; + esac + done + fi + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir" + done + fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for CFPreferencesCopyAppValue" >&5 +printf %s "checking for CFPreferencesCopyAppValue... " >&6; } +if test ${gt_cv_func_CFPreferencesCopyAppValue+y} +then : + printf %s "(cached) " >&6 +else $as_nop + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +CFPreferencesCopyAppValue(NULL, NULL) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + gt_cv_func_CFPreferencesCopyAppValue=yes +else $as_nop + gt_cv_func_CFPreferencesCopyAppValue=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFPreferencesCopyAppValue" >&5 +printf "%s\n" "$gt_cv_func_CFPreferencesCopyAppValue" >&6; } + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + +printf "%s\n" "#define HAVE_CFPREFERENCESCOPYAPPVALUE 1" >>confdefs.h + + fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for CFLocaleCopyCurrent" >&5 +printf %s "checking for CFLocaleCopyCurrent... " >&6; } +if test ${gt_cv_func_CFLocaleCopyCurrent+y} +then : + printf %s "(cached) " >&6 +else $as_nop + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +CFLocaleCopyCurrent(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + gt_cv_func_CFLocaleCopyCurrent=yes +else $as_nop + gt_cv_func_CFLocaleCopyCurrent=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFLocaleCopyCurrent" >&5 +printf "%s\n" "$gt_cv_func_CFLocaleCopyCurrent" >&6; } + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + +printf "%s\n" "#define HAVE_CFLOCALECOPYCURRENT 1" >>confdefs.h + + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + + + + + + + LIBINTL= + LTLIBINTL= + POSUB= + + case " $gt_needs " in + *" need-formatstring-macros "*) gt_api_version=3 ;; + *" need-ngettext "*) gt_api_version=2 ;; + *) gt_api_version=1 ;; + esac + gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" + gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" + + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + + + if test $gt_api_version -ge 3; then + gt_revision_test_code=' +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +' + else + gt_revision_test_code= + fi + if test $gt_api_version -ge 2; then + gt_expression_test_code=' + * ngettext ("", "", 0)' + else + gt_expression_test_code= + fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libc" >&5 +printf %s "checking for GNU gettext in libc... " >&6; } +if eval test \${$gt_func_gnugettext_libc+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings; + +int +main (void) +{ + +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + eval "$gt_func_gnugettext_libc=yes" +else $as_nop + eval "$gt_func_gnugettext_libc=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$gt_func_gnugettext_libc + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + + + + + + am_save_CPPFLAGS="$CPPFLAGS" + + for element in $INCICONV; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 +printf %s "checking for iconv... " >&6; } +if test ${am_cv_func_iconv+y} +then : + printf %s "(cached) " >&6 +else $as_nop + + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +int +main (void) +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +int +main (void) +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + am_cv_lib_iconv=yes + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$am_save_LIBS" + fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5 +printf "%s\n" "$am_cv_func_iconv" >&6; } + if test "$am_cv_func_iconv" = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working iconv" >&5 +printf %s "checking for working iconv... " >&6; } +if test ${am_cv_func_iconv_works+y} +then : + printf %s "(cached) " >&6 +else $as_nop + + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + if test "$cross_compiling" = yes +then : + + case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac + +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int main () +{ + int result = 0; + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 1; + iconv_close (cd_utf8_to_88591); + } + } + /* Test against Solaris 10 bug: Failures are not distinguishable from + successful returns. */ + { + iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); + if (cd_ascii_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\263"; + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_ascii_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 2; + iconv_close (cd_ascii_to_88591); + } + } + /* Test against AIX 6.1..7.1 bug: Buffer overrun. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304"; + static char buf[2] = { (char)0xDE, (char)0xAD }; + const char *inptr = input; + size_t inbytesleft = 1; + char *outptr = buf; + size_t outbytesleft = 1; + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) + result |= 4; + iconv_close (cd_88591_to_utf8); + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + result |= 8; + iconv_close (cd_88591_to_utf8); + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + result |= 16; + return result; +} +_ACEOF +if ac_fn_c_try_run "$LINENO" +then : + am_cv_func_iconv_works=yes +else $as_nop + am_cv_func_iconv_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + LIBS="$am_save_LIBS" + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv_works" >&5 +printf "%s\n" "$am_cv_func_iconv_works" >&6; } + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + +printf "%s\n" "#define HAVE_ICONV 1" >>confdefs.h + + fi + if test "$am_cv_lib_iconv" = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 +printf %s "checking how to link with libiconv... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 +printf "%s\n" "$LIBICONV" >&6; } + else + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + + + + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libintl-prefix was given. +if test ${with_libintl_prefix+y} +then : + withval=$with_libintl_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi + +fi + + LIBINTL= + LTLIBINTL= + INCINTL= + LIBINTL_PREFIX= + HAVE_LIBINTL= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='intl ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBINTL="${LIBINTL}${LIBINTL:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_a" + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = 'intl'; then + LIBINTL_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = 'intl'; then + LIBINTL_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCINTL="${INCINTL}${INCINTL:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBINTL="${LIBINTL}${LIBINTL:+ }$dep" + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$dep" + ;; + esac + done + fi + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-R$found_dir" + done + fi + + + + + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libintl" >&5 +printf %s "checking for GNU gettext in libintl... " >&6; } +if eval test \${$gt_func_gnugettext_libintl+y} +then : + printf %s "(cached) " >&6 +else $as_nop + gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + +int +main (void) +{ + +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + eval "$gt_func_gnugettext_libintl=yes" +else $as_nop + eval "$gt_func_gnugettext_libintl=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + +int +main (void) +{ + +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + eval "$gt_func_gnugettext_libintl=yes" + +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS" +fi +eval ac_res=\$$gt_func_gnugettext_libintl + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + fi + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ + || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + + + if test -n "$INTL_MACOSX_LIBS"; then + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" + LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" + fi + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + +printf "%s\n" "#define ENABLE_NLS 1" >>confdefs.h + + else + USE_NLS=no + fi + fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to use NLS" >&5 +printf %s "checking whether to use NLS... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +printf "%s\n" "$USE_NLS" >&6; } + if test "$USE_NLS" = "yes"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking where the gettext function comes from" >&5 +printf %s "checking where the gettext function comes from... " >&6; } + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $gt_source" >&5 +printf "%s\n" "$gt_source" >&6; } + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to link with libintl" >&5 +printf %s "checking how to link with libintl... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LIBINTL" >&5 +printf "%s\n" "$LIBINTL" >&6; } + + for element in $INCINTL; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + fi + + +printf "%s\n" "#define HAVE_GETTEXT 1" >>confdefs.h + + +printf "%s\n" "#define HAVE_DCGETTEXT 1" >>confdefs.h + + fi + + POSUB=po + fi + + + + INTLLIBS="$LIBINTL" + + + + + + + + + if test "$host_os" = "windows"; then + WINDOWS_TRUE= + WINDOWS_FALSE='#' +else + WINDOWS_TRUE='#' + WINDOWS_FALSE= +fi + + + +build_linux=no +build_windows=no +build_mac=no +build_freebsd=no + +# Detect the target system +case "${host_os}" in + linux*) + build_linux=yes + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Linux detected" >&5 +printf "%s\n" "$as_me: Linux detected" >&6;} + + if test "x$enable_aac" != "xno" -a "x$client_only" != "xyes" +then : + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for aacEncOpen in -lfdk-aac" >&5 +printf %s "checking for aacEncOpen in -lfdk-aac... " >&6; } +if test ${ac_cv_lib_fdk_aac_aacEncOpen+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lfdk-aac $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char aacEncOpen (); +int +main (void) +{ +return aacEncOpen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_fdk_aac_aacEncOpen=yes +else $as_nop + ac_cv_lib_fdk_aac_aacEncOpen=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fdk_aac_aacEncOpen" >&5 +printf "%s\n" "$ac_cv_lib_fdk_aac_aacEncOpen" >&6; } +if test "x$ac_cv_lib_fdk_aac_aacEncOpen" = xyes +then : + + CPPFLAGS="$CPPFLAGS -DHAVE_LIBFDK_AAC" + LIBS="$LIBS -ldl" + +else $as_nop + as_fn_error $? "**** Could not find libfdk-aac - run ./configure --disable-aac to build without aac support ****" "$LINENO" 5 + +fi + + +fi + # Check whether --enable-webrtc was given. +if test ${enable_webrtc+y} +then : + enableval=$enable_webrtc; + if test "x$client_only" != "xyes" +then : + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for rtcCreatePeerConnection in -ldatachannel" >&5 +printf %s "checking for rtcCreatePeerConnection in -ldatachannel... " >&6; } +if test ${ac_cv_lib_datachannel_rtcCreatePeerConnection+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldatachannel $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char rtcCreatePeerConnection (); +int +main (void) +{ +return rtcCreatePeerConnection (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_datachannel_rtcCreatePeerConnection=yes +else $as_nop + ac_cv_lib_datachannel_rtcCreatePeerConnection=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_datachannel_rtcCreatePeerConnection" >&5 +printf "%s\n" "$ac_cv_lib_datachannel_rtcCreatePeerConnection" >&6; } +if test "x$ac_cv_lib_datachannel_rtcCreatePeerConnection" = xyes +then : + printf "%s\n" "#define HAVE_LIBDATACHANNEL 1" >>confdefs.h + + LIBS="-ldatachannel $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find datachannel ****" "$LINENO" 5 +fi + + +fi + +fi + + ;; + cygwin*|mingw*|windows) + build_windows=yes + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Windows detected" >&5 +printf "%s\n" "$as_me: Windows detected" >&6;} + + # Do NOT check for aac lib here because butt must not depend on libfdk-aac dll. + # Instead define HAVE_LIBFDK_AAC manually, so butt runs with and without the dll + CPPFLAGS="$CPPFLAGS -DHAVE_LIBFDK_AAC" + + if test "x$client_only" != "xyes" +then : + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for rtcCreatePeerConnection in -ldatachannel" >&5 +printf %s "checking for rtcCreatePeerConnection in -ldatachannel... " >&6; } +if test ${ac_cv_lib_datachannel_rtcCreatePeerConnection+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldatachannel $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char rtcCreatePeerConnection (); +int +main (void) +{ +return rtcCreatePeerConnection (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_datachannel_rtcCreatePeerConnection=yes +else $as_nop + ac_cv_lib_datachannel_rtcCreatePeerConnection=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_datachannel_rtcCreatePeerConnection" >&5 +printf "%s\n" "$ac_cv_lib_datachannel_rtcCreatePeerConnection" >&6; } +if test "x$ac_cv_lib_datachannel_rtcCreatePeerConnection" = xyes +then : + printf "%s\n" "#define HAVE_LIBDATACHANNEL 1" >>confdefs.h + + LIBS="-ldatachannel $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find datachannel ****" "$LINENO" 5 +fi + + +fi + ;; + darwin*) + build_mac=yes + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: MacOS detected" >&5 +printf "%s\n" "$as_me: MacOS detected" >&6;} + CPPFLAGS="$CPPFLAGS -x objective-c++" + LIBS="$LIBS -framework AVFoundation -lintl -framework ScriptingBridge" + LDFLAGS="$LDFLAGS -rpath /usr/local/lib" + + if test "x$client_only" != "xyes" +then : + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for rtcCreatePeerConnection in -ldatachannel" >&5 +printf %s "checking for rtcCreatePeerConnection in -ldatachannel... " >&6; } +if test ${ac_cv_lib_datachannel_rtcCreatePeerConnection+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldatachannel $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char rtcCreatePeerConnection (); +int +main (void) +{ +return rtcCreatePeerConnection (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_datachannel_rtcCreatePeerConnection=yes +else $as_nop + ac_cv_lib_datachannel_rtcCreatePeerConnection=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_datachannel_rtcCreatePeerConnection" >&5 +printf "%s\n" "$ac_cv_lib_datachannel_rtcCreatePeerConnection" >&6; } +if test "x$ac_cv_lib_datachannel_rtcCreatePeerConnection" = xyes +then : + printf "%s\n" "#define HAVE_LIBDATACHANNEL 1" >>confdefs.h + + LIBS="-ldatachannel $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find datachannel ****" "$LINENO" 5 +fi + + +fi + ;; + freebsd*) + build_freebsd=yes + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: FreeBSD detected" >&5 +printf "%s\n" "$as_me: FreeBSD detected" >&6;} + + if test "x$enable_aac" != "xno" -a "x$client_only" != "xyes" +then : + + # By default AC_CHECK_LIB adds -lfdk-aac to the linker flags if the check succeeds. But as the library is loaded with dlopen() during runtime + # the linker flag is not needed. So we only define HAVE_LIBFDK_AAC in case the library was found + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for aacEncOpen in -lfdk-aac" >&5 +printf %s "checking for aacEncOpen in -lfdk-aac... " >&6; } +if test ${ac_cv_lib_fdk_aac_aacEncOpen+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lfdk-aac $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char aacEncOpen (); +int +main (void) +{ +return aacEncOpen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_fdk_aac_aacEncOpen=yes +else $as_nop + ac_cv_lib_fdk_aac_aacEncOpen=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fdk_aac_aacEncOpen" >&5 +printf "%s\n" "$ac_cv_lib_fdk_aac_aacEncOpen" >&6; } +if test "x$ac_cv_lib_fdk_aac_aacEncOpen" = xyes +then : + CPPFLAGS="$CPPFLAGS -DHAVE_LIBFDK_AAC" +else $as_nop + as_fn_error $? "**** Could not find libfdk-aac - run ./configure --disable-aac to build without aac support ****" "$LINENO" 5 + +fi + + +fi + + # Check whether --enable-webrtc was given. +if test ${enable_webrtc+y} +then : + enableval=$enable_webrtc; + if test "x$client_only" != "xyes" +then : + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for rtcCreatePeerConnection in -ldatachannel" >&5 +printf %s "checking for rtcCreatePeerConnection in -ldatachannel... " >&6; } +if test ${ac_cv_lib_datachannel_rtcCreatePeerConnection+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldatachannel $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char rtcCreatePeerConnection (); +int +main (void) +{ +return rtcCreatePeerConnection (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_datachannel_rtcCreatePeerConnection=yes +else $as_nop + ac_cv_lib_datachannel_rtcCreatePeerConnection=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_datachannel_rtcCreatePeerConnection" >&5 +printf "%s\n" "$ac_cv_lib_datachannel_rtcCreatePeerConnection" >&6; } +if test "x$ac_cv_lib_datachannel_rtcCreatePeerConnection" = xyes +then : + printf "%s\n" "#define HAVE_LIBDATACHANNEL 1" >>confdefs.h + + LIBS="-ldatachannel $LIBS" + +else $as_nop + as_fn_error $? "**** Could not find datachannel ****" "$LINENO" 5 +fi + + +fi + +fi + + ;; + *) + as_fn_error $? "\"OS $host_os is not supported\"" "$LINENO" 5 + ;; +esac + +# Pass the conditionals to automake + if test "$build_linux" = "yes"; then + LINUX_TRUE= + LINUX_FALSE='#' +else + LINUX_TRUE='#' + LINUX_FALSE= +fi + + if test "$build_windows" = "yes"; then + WINDOWS_TRUE= + WINDOWS_FALSE='#' +else + WINDOWS_TRUE='#' + WINDOWS_FALSE= +fi + + if test "$build_mac" = "yes"; then + OSX_TRUE= + OSX_FALSE='#' +else + OSX_TRUE='#' + OSX_FALSE= +fi + + if test "$build_freebsd" = "yes"; then + FREEBSD_TRUE= + FREEBSD_FALSE='#' +else + FREEBSD_TRUE='#' + FREEBSD_FALSE= +fi + + if test "x$with_radioco" = "xyes"; then + WITH_RADIOCO_TRUE= + WITH_RADIOCO_FALSE='#' +else + WITH_RADIOCO_TRUE='#' + WITH_RADIOCO_FALSE= +fi + + if test "x$with_client" = "xyes" -o "x$client_only" = "xyes"; then + WITH_CLIENT_TRUE= + WITH_CLIENT_FALSE='#' +else + WITH_CLIENT_TRUE='#' + WITH_CLIENT_FALSE= +fi + + if test "x$client_only" = "xyes"; then + CLIENT_ONLY_TRUE= + CLIENT_ONLY_FALSE='#' +else + CLIENT_ONLY_TRUE='#' + CLIENT_ONLY_FALSE= +fi + + +# Extract the first word of "fltk-config", so it can be a program name with args. +set dummy fltk-config; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_FLTKCONFIG+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$FLTKCONFIG"; then + ac_cv_prog_FLTKCONFIG="$FLTKCONFIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_FLTKCONFIG="fltk-config" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +FLTKCONFIG=$ac_cv_prog_FLTKCONFIG +if test -n "$FLTKCONFIG"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FLTKCONFIG" >&5 +printf "%s\n" "$FLTKCONFIG" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + +if test "x$client_only" != "xyes"; then + if test "$FLTKCONFIG" = "fltk-config"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lfltk" >&5 +printf %s "checking for main in -lfltk... " >&6; } +if test ${ac_cv_lib_fltk_main+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lfltk $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main (void) +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_fltk_main=yes +else $as_nop + ac_cv_lib_fltk_main=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fltk_main" >&5 +printf "%s\n" "$ac_cv_lib_fltk_main" >&6; } +if test "x$ac_cv_lib_fltk_main" = xyes +then : + + LIBS="$LIBS `fltk-config --ldflags --use-images`" + CXXFLAGS="$CXXFLAGS `fltk-config --cxxflags`" + +else $as_nop + as_fn_error $? "**** Could not find libfltk ****" "$LINENO" 5 + +fi + + else + as_fn_error $? "**** Could not find fltk-config ****" "$LINENO" 5 + fi +fi + + +#Add dbus library for Linux +if test "$build_linux" = "yes" -a "x$client_only" != "xyes"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: " >&5 +printf "%s\n" "$as_me: " >&6;} + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_PKG_CONFIG+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +printf "%s\n" "$PKG_CONFIG" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_ac_pt_PKG_CONFIG+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +printf "%s\n" "$ac_pt_PKG_CONFIG" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +printf %s "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + PKG_CONFIG="" + fi +fi + +pkg_failed=no +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dbus-1" >&5 +printf %s "checking for dbus-1... " >&6; } + +if test -n "$DBUS_CFLAGS"; then + pkg_cv_DBUS_CFLAGS="$DBUS_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "dbus-1") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DBUS_CFLAGS=`$PKG_CONFIG --cflags "dbus-1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$DBUS_LIBS"; then + pkg_cv_DBUS_LIBS="$DBUS_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "dbus-1") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DBUS_LIBS=`$PKG_CONFIG --libs "dbus-1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + DBUS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "dbus-1" 2>&1` + else + DBUS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "dbus-1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$DBUS_PKG_ERRORS" >&5 + + + +printf "%s\n" "#define HAVE_DBUS 0" >>confdefs.h + + as_fn_error $? "**** Coud not find dbus dev files" "$LINENO" 5 + +elif test $pkg_failed = untried; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + + +printf "%s\n" "#define HAVE_DBUS 0" >>confdefs.h + + as_fn_error $? "**** Coud not find dbus dev files" "$LINENO" 5 + +else + DBUS_CFLAGS=$pkg_cv_DBUS_CFLAGS + DBUS_LIBS=$pkg_cv_DBUS_LIBS + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + + +printf "%s\n" "#define HAVE_DBUS 1" >>confdefs.h + + LIBS="$LIBS $DBUS_LIBS" + CFLAGS="$CFLAGS $LIBS $DBUS_CFLAGS" + CXXFLAGS="$CXXFLAGS $DBUS_CFLAGS" + +fi + # Explicitly add X11 library because it is not added by fltk-config on OpenSUSE + LIBS="$LIBS -lX11" + +fi + +#Add dbus library for FreeBSD +if test "$build_freebsd" = "yes" -a "x$client_only" != "xyes"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: " >&5 +printf "%s\n" "$as_me: " >&6;} + +pkg_failed=no +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dbus-1" >&5 +printf %s "checking for dbus-1... " >&6; } + +if test -n "$DBUS_CFLAGS"; then + pkg_cv_DBUS_CFLAGS="$DBUS_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "dbus-1") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DBUS_CFLAGS=`$PKG_CONFIG --cflags "dbus-1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$DBUS_LIBS"; then + pkg_cv_DBUS_LIBS="$DBUS_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "dbus-1") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DBUS_LIBS=`$PKG_CONFIG --libs "dbus-1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + DBUS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "dbus-1" 2>&1` + else + DBUS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "dbus-1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$DBUS_PKG_ERRORS" >&5 + + + +printf "%s\n" "#define HAVE_DBUS 0" >>confdefs.h + + as_fn_error $? "**** Coud not find dbus dev files" "$LINENO" 5 + +elif test $pkg_failed = untried; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + + +printf "%s\n" "#define HAVE_DBUS 0" >>confdefs.h + + as_fn_error $? "**** Coud not find dbus dev files" "$LINENO" 5 + +else + DBUS_CFLAGS=$pkg_cv_DBUS_CFLAGS + DBUS_LIBS=$pkg_cv_DBUS_LIBS + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + + +printf "%s\n" "#define HAVE_DBUS 1" >>confdefs.h + + LIBS="$LIBS $DBUS_LIBS" + CFLAGS="$CFLAGS $LIBS $DBUS_CFLAGS" + CXXFLAGS="$CXXFLAGS $DBUS_CFLAGS" + +fi +fi +# Checks for header files. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for X" >&5 +printf %s "checking for X... " >&6; } + + +# Check whether --with-x was given. +if test ${with_x+y} +then : + withval=$with_x; +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + case $x_includes,$x_libraries in #( + *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( + *,NONE | NONE,*) if test ${ac_cv_have_x+y} +then : + printf %s "(cached) " >&6 +else $as_nop + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no +ac_x_libraries=no +# Do we need to do anything special at all? +ac_save_LIBS=$LIBS +LIBS="-lX11 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +XrmInitialize () + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + # We can compile and link X programs with no special options. + ac_x_includes= + ac_x_libraries= +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS="$ac_save_LIBS" +# If that didn't work, only try xmkmf and file system searches +# for native compilation. +if test x"$ac_x_includes" = xno && test "$cross_compiling" = no +then : + rm -f -r conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + cat >Imakefile <<'_ACEOF' +incroot: + @echo incroot='${INCROOT}' +usrlibdir: + @echo usrlibdir='${USRLIBDIR}' +libdir: + @echo libdir='${LIBDIR}' +_ACEOF + if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. + for ac_var in incroot usrlibdir libdir; do + eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" + done + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl dylib la dll; do + if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && + test -f "$ac_im_libdir/libX11.$ac_extension"; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ac_x_includes= ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /usr/lib64 | /lib | /lib64) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -f -r conftest.dir +fi + + # Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R7/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R7 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R7/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R7 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/opt/X11/include + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Xlib.h. + # First, try using that file with no special directory specified. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO" +then : + # We can compile using X headers with no special include directory. +ac_x_includes= +else $as_nop + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Xlib.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lX11 $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +XrmInitialize () + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else $as_nop + LIBS=$ac_save_LIBS +for ac_dir in `printf "%s\n" "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl dylib la dll; do + if test -r "$ac_dir/libX11.$ac_extension"; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +fi +# Record the results. +case $ac_x_includes,$ac_x_libraries in #( + no,* | *,no | *\'*) : + # Didn't find X, or a directory has "'" in its name. + ac_cv_have_x="have_x=no" ;; #( + *) : + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$ac_x_includes'\ + ac_x_libraries='$ac_x_libraries'" ;; +esac +fi +;; #( + *) have_x=yes;; + esac + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5 +printf "%s\n" "$have_x" >&6; } + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$x_includes'\ + ac_x_libraries='$x_libraries'" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5 +printf "%s\n" "libraries $x_libraries, headers $x_includes" >&6; } +fi + +ac_fn_c_check_header_compile "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default" +if test "x$ac_cv_header_fcntl_h" = xyes +then : + printf "%s\n" "#define HAVE_FCNTL_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default" +if test "x$ac_cv_header_limits_h" = xyes +then : + printf "%s\n" "#define HAVE_LIMITS_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "netdb.h" "ac_cv_header_netdb_h" "$ac_includes_default" +if test "x$ac_cv_header_netdb_h" = xyes +then : + printf "%s\n" "#define HAVE_NETDB_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "netinet/in.h" "ac_cv_header_netinet_in_h" "$ac_includes_default" +if test "x$ac_cv_header_netinet_in_h" = xyes +then : + printf "%s\n" "#define HAVE_NETINET_IN_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes +then : + printf "%s\n" "#define HAVE_STDLIB_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default" +if test "x$ac_cv_header_string_h" = xyes +then : + printf "%s\n" "#define HAVE_STRING_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_socket_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_SOCKET_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" +if test "x$ac_cv_header_unistd_h" = xyes +then : + printf "%s\n" "#define HAVE_UNISTD_H 1" >>confdefs.h + +fi + + +# Checks for typedefs, structures, and compiler characteristics. +ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default" +if test "x$ac_cv_type__Bool" = xyes +then : + +printf "%s\n" "#define HAVE__BOOL 1" >>confdefs.h + + +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5 +printf %s "checking for stdbool.h that conforms to C99... " >&6; } +if test ${ac_cv_header_stdbool_h+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + + #ifndef __bool_true_false_are_defined + #error "__bool_true_false_are_defined is not defined" + #endif + char a[__bool_true_false_are_defined == 1 ? 1 : -1]; + + /* Regardless of whether this is C++ or "_Bool" is a + valid type name, "true" and "false" should be usable + in #if expressions and integer constant expressions, + and "bool" should be a valid type name. */ + + #if !true + #error "'true' is not true" + #endif + #if true != 1 + #error "'true' is not equal to 1" + #endif + char b[true == 1 ? 1 : -1]; + char c[true]; + + #if false + #error "'false' is not false" + #endif + #if false != 0 + #error "'false' is not equal to 0" + #endif + char d[false == 0 ? 1 : -1]; + + enum { e = false, f = true, g = false * true, h = true * 256 }; + + char i[(bool) 0.5 == true ? 1 : -1]; + char j[(bool) 0.0 == false ? 1 : -1]; + char k[sizeof (bool) > 0 ? 1 : -1]; + + struct sb { bool s: 1; bool t; } s; + char l[sizeof s.t > 0 ? 1 : -1]; + + /* The following fails for + HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */ + bool m[h]; + char n[sizeof m == h * sizeof m[0] ? 1 : -1]; + char o[-1 - (bool) 0 < 0 ? 1 : -1]; + /* Catch a bug in an HP-UX C compiler. See + https://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html + https://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html + */ + bool p = true; + bool *pp = &p; + + /* C 1999 specifies that bool, true, and false are to be + macros, but C++ 2011 and later overrule this. */ + #if __cplusplus < 201103 + #ifndef bool + #error "bool is not defined" + #endif + #ifndef false + #error "false is not defined" + #endif + #ifndef true + #error "true is not defined" + #endif + #endif + + /* If _Bool is available, repeat with it all the tests + above that used bool. */ + #ifdef HAVE__BOOL + struct sB { _Bool s: 1; _Bool t; } t; + + char q[(_Bool) 0.5 == true ? 1 : -1]; + char r[(_Bool) 0.0 == false ? 1 : -1]; + char u[sizeof (_Bool) > 0 ? 1 : -1]; + char v[sizeof t.t > 0 ? 1 : -1]; + + _Bool w[h]; + char x[sizeof m == h * sizeof m[0] ? 1 : -1]; + char y[-1 - (_Bool) 0 < 0 ? 1 : -1]; + _Bool z = true; + _Bool *pz = &p; + #endif + +int +main (void) +{ + + bool ps = &s; + *pp |= p; + *pp |= ! p; + + #ifdef HAVE__BOOL + _Bool pt = &t; + *pz |= z; + *pz |= ! z; + #endif + + /* Refer to every declared value, so they cannot be + discarded as unused. */ + return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !j + !k + + !l + !m + !n + !o + !p + !pp + !ps + #ifdef HAVE__BOOL + + !q + !r + !u + !v + !w + !x + !y + !z + !pt + #endif + ); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_header_stdbool_h=yes +else $as_nop + ac_cv_header_stdbool_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5 +printf "%s\n" "$ac_cv_header_stdbool_h" >&6; } + +if test $ac_cv_header_stdbool_h = yes; then + +printf "%s\n" "#define HAVE_STDBOOL_H 1" >>confdefs.h + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +printf %s "checking for inline... " >&6; } +if test ${ac_cv_c_inline+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo (void) {return 0; } +$ac_kw foo_t foo (void) {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +printf "%s\n" "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + + +# Checks for library functions. +#AC_FUNC_MALLOC +#AC_FUNC_REALLOC +ac_fn_c_check_func "$LINENO" "gethostbyaddr" "ac_cv_func_gethostbyaddr" +if test "x$ac_cv_func_gethostbyaddr" = xyes +then : + printf "%s\n" "#define HAVE_GETHOSTBYADDR 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" +if test "x$ac_cv_func_gethostbyname" = xyes +then : + printf "%s\n" "#define HAVE_GETHOSTBYNAME 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "memset" "ac_cv_func_memset" +if test "x$ac_cv_func_memset" = xyes +then : + printf "%s\n" "#define HAVE_MEMSET 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "pow" "ac_cv_func_pow" +if test "x$ac_cv_func_pow" = xyes +then : + printf "%s\n" "#define HAVE_POW 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "select" "ac_cv_func_select" +if test "x$ac_cv_func_select" = xyes +then : + printf "%s\n" "#define HAVE_SELECT 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket" +if test "x$ac_cv_func_socket" = xyes +then : + printf "%s\n" "#define HAVE_SOCKET 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "strchr" "ac_cv_func_strchr" +if test "x$ac_cv_func_strchr" = xyes +then : + printf "%s\n" "#define HAVE_STRCHR 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "strdup" "ac_cv_func_strdup" +if test "x$ac_cv_func_strdup" = xyes +then : + printf "%s\n" "#define HAVE_STRDUP 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "strpbrk" "ac_cv_func_strpbrk" +if test "x$ac_cv_func_strpbrk" = xyes +then : + printf "%s\n" "#define HAVE_STRPBRK 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "strrchr" "ac_cv_func_strrchr" +if test "x$ac_cv_func_strrchr" = xyes +then : + printf "%s\n" "#define HAVE_STRRCHR 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "strstr" "ac_cv_func_strstr" +if test "x$ac_cv_func_strstr" = xyes +then : + printf "%s\n" "#define HAVE_STRSTR 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "X509_check_host" "ac_cv_func_X509_check_host" +if test "x$ac_cv_func_X509_check_host" = xyes +then : + printf "%s\n" "#define HAVE_X509_CHECK_HOST 1" >>confdefs.h + +fi + + +ac_config_files="$ac_config_files Makefile po/Makefile.in src/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +printf "%s\n" "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +printf %s "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: done" >&5 +printf "%s\n" "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepOBJC_TRUE}" && test -z "${am__fastdepOBJC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepOBJC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WINDOWS_TRUE}" && test -z "${WINDOWS_FALSE}"; then + as_fn_error $? "conditional \"WINDOWS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${LINUX_TRUE}" && test -z "${LINUX_FALSE}"; then + as_fn_error $? "conditional \"LINUX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WINDOWS_TRUE}" && test -z "${WINDOWS_FALSE}"; then + as_fn_error $? "conditional \"WINDOWS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${OSX_TRUE}" && test -z "${OSX_FALSE}"; then + as_fn_error $? "conditional \"OSX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${FREEBSD_TRUE}" && test -z "${FREEBSD_FALSE}"; then + as_fn_error $? "conditional \"FREEBSD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_RADIOCO_TRUE}" && test -z "${WITH_RADIOCO_FALSE}"; then + as_fn_error $? "conditional \"WITH_RADIOCO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WITH_CLIENT_TRUE}" && test -z "${WITH_CLIENT_FALSE}"; then + as_fn_error $? "conditional \"WITH_CLIENT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${CLIENT_ONLY_TRUE}" && test -z "${CLIENT_ONLY_FALSE}"; then + as_fn_error $? "conditional \"CLIENT_ONLY\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +as_nop=: +if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 +then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else $as_nop + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + + +# Reset variables that may have inherited troublesome values from +# the environment. + +# IFS needs to be set, to space, tab, and newline, in precisely that order. +# (If _AS_PATH_WALK were called with IFS unset, it would have the +# side effect of setting IFS to empty, thus disabling word splitting.) +# Quoting is to prevent editors from complaining about space-tab. +as_nl=' +' +export as_nl +IFS=" "" $as_nl" + +PS1='$ ' +PS2='> ' +PS4='+ ' + +# Ensure predictable behavior from utilities with locale-dependent output. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# We cannot yet rely on "unset" to work, but we need these variables +# to be unset--not just set to an empty or harmless value--now, to +# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct +# also avoids known problems related to "unset" and subshell syntax +# in other old shells (e.g. bash 2.01 and pdksh 5.2.14). +for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH +do eval test \${$as_var+y} \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done + +# Ensure that fds 0, 1, and 2 are open. +if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi +if (exec 3>&2) ; then :; else exec 2>/dev/null; fi + +# The user is always right. +if ${PATH_SEPARATOR+false} :; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + test -r "$as_dir$0" && as_myself=$as_dir$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + printf "%s\n" "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null +then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else $as_nop + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null +then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else $as_nop + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + +# Determine whether it's possible to make 'echo' print without a newline. +# These variables are no longer used directly by Autoconf, but are AC_SUBSTed +# for compatibility with existing Makefiles. +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +# For backward compatibility with old third-party macros, we provide +# the shell variables $as_echo and $as_echo_n. New code should use +# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. +as_echo='printf %s\n' +as_echo_n='printf %s' + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by butt $as_me 1.45.0, which was +generated by GNU Autoconf 2.71. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` +ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config='$ac_cs_config_escaped' +ac_cs_version="\\ +butt config.status 1.45.0 +configured by $0, generated by GNU Autoconf 2.71, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2021 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + printf "%s\n" "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + printf "%s\n" "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + printf "%s\n" "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + printf "%s\n" "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" +# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake < 1.5. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "po-directories") CONFIG_COMMANDS="$CONFIG_COMMANDS po-directories" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files + test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers + test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +printf "%s\n" "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`printf "%s\n" "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + printf "%s\n" "/* $configure_input */" >&1 \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + printf "%s\n" "/* $configure_input */" >&1 \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +printf "%s\n" "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + case $CONFIG_FILES in #( + *\'*) : + eval set x "$CONFIG_FILES" ;; #( + *) : + set x $CONFIG_FILES ;; #( + *) : + ;; +esac + shift + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf + do + # Strip MF so we end up with the name of the file. + am_mf=`printf "%s\n" "$am_mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`$as_dirname -- "$am_mf" || +$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$am_mf" : 'X\(//\)[^/]' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X"$am_mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + am_filepart=`$as_basename -- "$am_mf" || +$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X/"$am_mf" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { echo "$as_me:$LINENO: cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles" >&5 + (cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } || am_rc=$? + done + if test $am_rc -ne 0; then + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE=\"gmake\" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking). +See \`config.log' for more details" "$LINENO" 5; } + fi + { am_dirpart=; unset am_dirpart;} + { am_filepart=; unset am_filepart;} + { am_mf=; unset am_mf;} + { am_rc=; unset am_rc;} + rm -f conftest-deps.mk +} + ;; + "po-directories":C) + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + # Treat a directory as a PO directory if and only if it has a + # POTFILES.in file. This allows packages to have multiple PO + # directories under different names or in different locations. + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + gt_tab=`printf '\t'` + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ${gt_tab}]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + done ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..90def16 --- /dev/null +++ b/configure.ac @@ -0,0 +1,278 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.68]) +AC_INIT([butt], [1.45.0], [BUG-REPORT-ADDRESS]) +AM_INIT_AUTOMAKE([subdir-objects foreign]) +AC_CANONICAL_HOST + +AC_CONFIG_SRCDIR([config.h.in]) +AC_CONFIG_HEADERS([config.h]) + +#predefined CXXFLAGS so AC_PROG_CXX does not add the -g flag +CXXFLAGS="$CXXFLAGS -O2" + +# Compile with address sanitizer +# CXXFLAGS="$CXXFLAGS -O2 -g -fsanitize=address" + +# Checks for programs. +AC_PROG_CXX +AC_PROG_CC +AC_PROG_OBJC + +LDFLAGS="$LDFLAGS -L/usr/local/lib" + +# Compile with address sanitizer +#LDFLAGS="$LDFLAGS -L/usr/local/lib -fsanitize=address" + + +AC_ARG_WITH([radioco], + AS_HELP_STRING([--with-radioco], [Include support for Radio.co])) + +AC_ARG_WITH([client], + AS_HELP_STRING([--with-client], [Build butt and butt-client]), + [with_client=yes], + [] + ) + +AC_ARG_WITH([butt], + AS_HELP_STRING([--without-butt], [Build only butt-client]), + [client_only=yes], + [], + ) + +AC_ARG_ENABLE([aac], + AS_HELP_STRING([--disable-aac], [Disable aac support])) + + +AS_IF([test "x$with_radioco" = "xyes"], + [ + AC_DEFINE([WITH_RADIOCO], [1], [Enable support for Radio.co authentification]) + ]) + +AS_IF([test "x$client_only" = "xyes"], + [ + AC_DEFINE([CLIENT_ONLY], [1], [build only butt-client]) + ]) + +AS_IF([test "x$with_client" = "xyes"], + [ + AC_DEFINE([WITH_CLIENT], [1], [build butt and butt-client]) + ]) + +AS_IF([test "x$client_only" != "xyes"], +[ +# Checks for libraries. +AC_CHECK_LIB([ogg], [ogg_stream_init], [], + [AC_MSG_ERROR([**** Could not find libogg ****])] + ) +AC_CHECK_LIB([vorbis], [vorbis_info_init], [], + [AC_MSG_ERROR([**** Could not find libvorbis ****])] + ) +AC_CHECK_LIB([vorbisenc], [vorbis_encode_init], [], + [AC_MSG_ERROR([**** Could not find libvorbisenc ****])] + ) +AC_CHECK_LIB([opus], [opus_encoder_create], [], + [AC_MSG_ERROR([**** Could not find libopus ****])] + ) +AC_CHECK_LIB([mp3lame], [lame_init], [], + [AC_MSG_ERROR([**** Could not find libmp3lame ****])] + + ) +AC_CHECK_LIB([FLAC], [FLAC__stream_encoder_new], [], + [AC_MSG_ERROR([**** Could not find libFLAC ****])] + ) +AC_CHECK_LIB([portaudio], [Pa_Initialize], [], + [AC_MSG_ERROR([**** Could not find libportaudio ****])] + ) +AC_CHECK_LIB([portmidi], [Pm_Initialize], [], + [AC_MSG_ERROR([**** Could not find libportmidi ****])] + ) +AC_CHECK_LIB([samplerate], [src_new], [], + [AC_MSG_ERROR([**** Could not find samplerate ****])] + ) +AC_CHECK_LIB([pthread], [pthread_create], [], + [AC_MSG_ERROR([**** Could not find libpthread ****])] + ) +AC_CHECK_LIB([curl], [curl_global_init], [], + [AC_MSG_ERROR([**** Could not find libcurl ****])] + ) +AC_CHECK_LIB([ssl], [SSL_CTX_new], [], + [AC_MSG_ERROR([**** Could not find libssl ****])] + ) +AC_CHECK_LIB([crypto], [EVP_EncryptInit], [], + [AC_MSG_ERROR([**** Could not find libcrypto ****])] + ) + +]) + +AC_CHECK_HEADER([winsock2.h], + [ + LIBS="$LIBS -lws2_32" + host_os="windows" + ], + ) + +AM_GNU_GETTEXT([external]) +AM_GNU_GETTEXT_VERSION([0.19]) + +AM_CONDITIONAL(WINDOWS, test "$host_os" = "windows") + + +build_linux=no +build_windows=no +build_mac=no +build_freebsd=no + +# Detect the target system +case "${host_os}" in + linux*) + build_linux=yes + AC_MSG_NOTICE([Linux detected]) + + AS_IF([test "x$enable_aac" != "xno" -a "x$client_only" != "xyes"], + [ + AC_CHECK_LIB([fdk-aac], [aacEncOpen], + [ + CPPFLAGS="$CPPFLAGS -DHAVE_LIBFDK_AAC" + LIBS="$LIBS -ldl" + ], + [AC_MSG_ERROR([**** Could not find libfdk-aac - run ./configure --disable-aac to build without aac support ****])] + ) + ]) + AC_ARG_ENABLE([webrtc], + AS_HELP_STRING([--enable-webrtc], [Enable WebRTC support]), + [ + AS_IF([test "x$client_only" != "xyes"], + [ + AC_CHECK_LIB([datachannel], [rtcCreatePeerConnection], [], + [AC_MSG_ERROR([**** Could not find datachannel ****])]) + ]) + ]) + ;; + cygwin*|mingw*|windows) + build_windows=yes + AC_MSG_NOTICE([Windows detected]) + + # Do NOT check for aac lib here because butt must not depend on libfdk-aac dll. + # Instead define HAVE_LIBFDK_AAC manually, so butt runs with and without the dll + CPPFLAGS="$CPPFLAGS -DHAVE_LIBFDK_AAC" + + AS_IF([test "x$client_only" != "xyes"], + [ + AC_CHECK_LIB([datachannel], [rtcCreatePeerConnection], [], + [AC_MSG_ERROR([**** Could not find datachannel ****])]) + ]) + ;; + darwin*) + build_mac=yes + AC_MSG_NOTICE([MacOS detected]) + CPPFLAGS="$CPPFLAGS -x objective-c++" + LIBS="$LIBS -framework AVFoundation -lintl -framework ScriptingBridge" + LDFLAGS="$LDFLAGS -rpath /usr/local/lib" + + AS_IF([test "x$client_only" != "xyes"], + [ + AC_CHECK_LIB([datachannel], [rtcCreatePeerConnection], [], + [AC_MSG_ERROR([**** Could not find datachannel ****])]) + ]) + ;; + freebsd*) + build_freebsd=yes + AC_MSG_NOTICE([FreeBSD detected]) + + AS_IF([test "x$enable_aac" != "xno" -a "x$client_only" != "xyes"], + [ + # By default AC_CHECK_LIB adds -lfdk-aac to the linker flags if the check succeeds. But as the library is loaded with dlopen() during runtime + # the linker flag is not needed. So we only define HAVE_LIBFDK_AAC in case the library was found + AC_CHECK_LIB([fdk-aac], [aacEncOpen], [CPPFLAGS="$CPPFLAGS -DHAVE_LIBFDK_AAC"], + [AC_MSG_ERROR([**** Could not find libfdk-aac - run ./configure --disable-aac to build without aac support ****])] + ) + ]) + + AC_ARG_ENABLE([webrtc], + AS_HELP_STRING([--enable-webrtc], [Enable WebRTC support]), + [ + AS_IF([test "x$client_only" != "xyes"], + [ + AC_CHECK_LIB([datachannel], [rtcCreatePeerConnection], [], + [AC_MSG_ERROR([**** Could not find datachannel ****])]) + ]) + ]) + ;; + *) + AC_MSG_ERROR(["OS $host_os is not supported"]) + ;; +esac + +# Pass the conditionals to automake +AM_CONDITIONAL([LINUX], [test "$build_linux" = "yes"]) +AM_CONDITIONAL([WINDOWS], [test "$build_windows" = "yes"]) +AM_CONDITIONAL([OSX], [test "$build_mac" = "yes"]) +AM_CONDITIONAL([FREEBSD], [test "$build_freebsd" = "yes"]) +AM_CONDITIONAL([WITH_RADIOCO], [test "x$with_radioco" = "xyes"]) +AM_CONDITIONAL([WITH_CLIENT], [test "x$with_client" = "xyes" -o "x$client_only" = "xyes"]) +AM_CONDITIONAL([CLIENT_ONLY], [test "x$client_only" = "xyes"]) + +AC_CHECK_PROG([FLTKCONFIG],[fltk-config], [fltk-config]) + +if test "x$client_only" != "xyes"; then + if test "$FLTKCONFIG" = "fltk-config"; then + AC_CHECK_LIB([fltk], [main], + [ + LIBS="$LIBS `fltk-config --ldflags --use-images`" + CXXFLAGS="$CXXFLAGS `fltk-config --cxxflags`" + ], + [AC_MSG_ERROR([**** Could not find libfltk ****])] + ) + else + AC_MSG_ERROR([**** Could not find fltk-config ****]) + fi +fi + + +#Add dbus library for Linux +if test "$build_linux" = "yes" -a "x$client_only" != "xyes"; then + AC_MSG_NOTICE([]) + PKG_CHECK_MODULES([DBUS], [dbus-1], [ + AC_DEFINE([HAVE_DBUS], [1], [Use dbus to get current tracks]) + LIBS="$LIBS $DBUS_LIBS" + CFLAGS="$CFLAGS $LIBS $DBUS_CFLAGS" + CXXFLAGS="$CXXFLAGS $DBUS_CFLAGS" + ], [ + AC_DEFINE([HAVE_DBUS], [0], [Use dbus to get current tracks]) + AC_MSG_ERROR([**** Coud not find dbus dev files]) + ]) + # Explicitly add X11 library because it is not added by fltk-config on OpenSUSE + LIBS="$LIBS -lX11" + +fi + +#Add dbus library for FreeBSD +if test "$build_freebsd" = "yes" -a "x$client_only" != "xyes"; then + AC_MSG_NOTICE([]) + PKG_CHECK_MODULES([DBUS], [dbus-1], [ + AC_DEFINE([HAVE_DBUS], [1], [Use dbus to get current tracks]) + LIBS="$LIBS $DBUS_LIBS" + CFLAGS="$CFLAGS $LIBS $DBUS_CFLAGS" + CXXFLAGS="$CXXFLAGS $DBUS_CFLAGS" + ], [ + AC_DEFINE([HAVE_DBUS], [0], [Use dbus to get current tracks]) + AC_MSG_ERROR([**** Coud not find dbus dev files]) + ]) +fi +# Checks for header files. +AC_PATH_X +AC_CHECK_HEADERS([fcntl.h limits.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_HEADER_STDBOOL +AC_C_INLINE + +# Checks for library functions. +#AC_FUNC_MALLOC +#AC_FUNC_REALLOC +AC_CHECK_FUNCS([gethostbyaddr gethostbyname memset pow select socket strchr strdup strpbrk strrchr strstr X509_check_host]) + +AC_CONFIG_FILES([Makefile po/Makefile.in src/Makefile]) +AC_OUTPUT diff --git a/depcomp b/depcomp new file mode 100755 index 0000000..715e343 --- /dev/null +++ b/depcomp @@ -0,0 +1,791 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 1999-2021 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The second -e expression handles DOS-style file names with drive + # letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/gettext.h b/gettext.h new file mode 100644 index 0000000..3b12b7c --- /dev/null +++ b/gettext.h @@ -0,0 +1,294 @@ +/* Convenience header for conditional use of GNU . + Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2016 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _LIBGETTEXT_H +#define _LIBGETTEXT_H 1 + +#include "config.h" + +/* NLS can be disabled through the configure --disable-nls option. */ +#if ENABLE_NLS + +/* Get declarations of GNU message catalog functions. */ +# include + +/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by + the gettext() and ngettext() macros. This is an alternative to calling + textdomain(), and is useful for libraries. */ +# ifdef DEFAULT_TEXT_DOMAIN +# undef gettext +# define gettext(Msgid) \ + dgettext (DEFAULT_TEXT_DOMAIN, Msgid) +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) +# endif + +#else + +/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which + chokes if dcgettext is defined as a macro. So include it now, to make + later inclusions of a NOP. We don't include + as well because people using "gettext.h" will not include , + and also including would fail on SunOS 4, whereas + is OK. */ +#if defined(__sun) +# include +#endif + +/* Many header files from the libstdc++ coming with g++ 3.3 or newer include + , which chokes if dcgettext is defined as a macro. So include + it now, to make later inclusions of a NOP. */ +#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) +# include +# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H +# include +# endif +#endif + +/* Disabled NLS. + The casts to 'const char *' serve the purpose of producing warnings + for invalid uses of the value returned from these functions. + On pre-ANSI systems without 'const', the config.h file is supposed to + contain "#define const". */ +# undef gettext +# define gettext(Msgid) ((const char *) (Msgid)) +# undef dgettext +# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) +# undef dcgettext +# define dcgettext(Domainname, Msgid, Category) \ + ((void) (Category), dgettext (Domainname, Msgid)) +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 \ + ? ((void) (Msgid2), (const char *) (Msgid1)) \ + : ((void) (Msgid1), (const char *) (Msgid2))) +# undef dngettext +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) +# undef dcngettext +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N)) +# undef textdomain +# define textdomain(Domainname) ((const char *) (Domainname)) +# undef bindtextdomain +# define bindtextdomain(Domainname, Dirname) \ + ((void) (Domainname), (const char *) (Dirname)) +# undef bind_textdomain_codeset +# define bind_textdomain_codeset(Domainname, Codeset) \ + ((void) (Domainname), (const char *) (Codeset)) + +#endif + +/* Prefer gnulib's setlocale override over libintl's setlocale override. */ +#ifdef GNULIB_defined_setlocale +# undef setlocale +# define setlocale rpl_setlocale +#endif + +/* A pseudo function call that serves as a marker for the automated + extraction of messages, but does not call gettext(). The run-time + translation is done at a different place in the code. + The argument, String, should be a literal string. Concatenated strings + and other string expressions won't work. + The macro's expansion is not parenthesized, so that it is suitable as + initializer for static 'char[]' or 'const char[]' variables. */ +#define gettext_noop(String) String + +/* The separator between msgctxt and msgid in a .mo file. */ +#define GETTEXT_CONTEXT_GLUE "\004" + +/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a + MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be + short and rarely need to change. + The letter 'p' stands for 'particular' or 'special'. */ +#ifdef DEFAULT_TEXT_DOMAIN +# define pgettext(Msgctxt, Msgid) \ + pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#else +# define pgettext(Msgctxt, Msgid) \ + pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#endif +#define dpgettext(Domainname, Msgctxt, Msgid) \ + pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ + pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) +#ifdef DEFAULT_TEXT_DOMAIN +# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#else +# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#endif +#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ + npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +pgettext_aux (const char *domain, + const char *msg_ctxt_id, const char *msgid, + int category) +{ + const char *translation = dcgettext (domain, msg_ctxt_id, category); + if (translation == msg_ctxt_id) + return msgid; + else + return translation; +} + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +npgettext_aux (const char *domain, + const char *msg_ctxt_id, const char *msgid, + const char *msgid_plural, unsigned long int n, + int category) +{ + const char *translation = + dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); + if (translation == msg_ctxt_id || translation == msgid_plural) + return (n == 1 ? msgid : msgid_plural); + else + return translation; +} + +/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID + can be arbitrary expressions. But for string literals these macros are + less efficient than those above. */ + +#include + +#if (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \ + /* || __STDC_VERSION__ >= 199901L */ ) +# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1 +#else +# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0 +#endif + +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS +#include +#endif + +#define pgettext_expr(Msgctxt, Msgid) \ + dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) +#define dpgettext_expr(Domainname, Msgctxt, Msgid) \ + dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +dcpgettext_expr (const char *domain, + const char *msgctxt, const char *msgid, + int category) +{ + size_t msgctxt_len = strlen (msgctxt) + 1; + size_t msgid_len = strlen (msgid) + 1; + const char *translation; +#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + char msg_ctxt_id[msgctxt_len + msgid_len]; +#else + char buf[1024]; + char *msg_ctxt_id = + (msgctxt_len + msgid_len <= sizeof (buf) + ? buf + : (char *) malloc (msgctxt_len + msgid_len)); + if (msg_ctxt_id != NULL) +#endif + { + int found_translation; + memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); + msg_ctxt_id[msgctxt_len - 1] = '\004'; + memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); + translation = dcgettext (domain, msg_ctxt_id, category); + found_translation = (translation != msg_ctxt_id); +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + if (msg_ctxt_id != buf) + free (msg_ctxt_id); +#endif + if (found_translation) + return translation; + } + return msgid; +} + +#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ + dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) +#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ + dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +dcnpgettext_expr (const char *domain, + const char *msgctxt, const char *msgid, + const char *msgid_plural, unsigned long int n, + int category) +{ + size_t msgctxt_len = strlen (msgctxt) + 1; + size_t msgid_len = strlen (msgid) + 1; + const char *translation; +#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + char msg_ctxt_id[msgctxt_len + msgid_len]; +#else + char buf[1024]; + char *msg_ctxt_id = + (msgctxt_len + msgid_len <= sizeof (buf) + ? buf + : (char *) malloc (msgctxt_len + msgid_len)); + if (msg_ctxt_id != NULL) +#endif + { + int found_translation; + memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); + msg_ctxt_id[msgctxt_len - 1] = '\004'; + memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); + translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); + found_translation = !(translation == msg_ctxt_id || translation == msgid_plural); +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + if (msg_ctxt_id != buf) + free (msg_ctxt_id); +#endif + if (found_translation) + return translation; + } + return (n == 1 ? msgid : msgid_plural); +} + +#endif /* _LIBGETTEXT_H */ diff --git a/icons/butt.icns b/icons/butt.icns new file mode 100644 index 0000000..fe20e05 Binary files /dev/null and b/icons/butt.icns differ diff --git a/icons/butt.ico b/icons/butt.ico new file mode 100644 index 0000000..0789ca3 Binary files /dev/null and b/icons/butt.ico differ diff --git a/icons/butt.xcf b/icons/butt.xcf new file mode 100644 index 0000000..4f13836 Binary files /dev/null and b/icons/butt.xcf differ diff --git a/icons/butt_yellow.ico b/icons/butt_yellow.ico new file mode 100644 index 0000000..0789ca3 Binary files /dev/null and b/icons/butt_yellow.ico differ diff --git a/icons/butt_yellow_512x512.jpg b/icons/butt_yellow_512x512.jpg new file mode 100644 index 0000000..557bdc4 Binary files /dev/null and b/icons/butt_yellow_512x512.jpg differ diff --git a/icons/butt_yellow_512x512.png b/icons/butt_yellow_512x512.png new file mode 100644 index 0000000..a55a112 Binary files /dev/null and b/icons/butt_yellow_512x512.png differ diff --git a/icons/butt_yellow_Mac_512x512.png b/icons/butt_yellow_Mac_512x512.png new file mode 100644 index 0000000..8a03625 Binary files /dev/null and b/icons/butt_yellow_Mac_512x512.png differ diff --git a/icons/icon_128x128.png b/icons/icon_128x128.png new file mode 100644 index 0000000..433c9ce Binary files /dev/null and b/icons/icon_128x128.png differ diff --git a/icons/icon_128x128@2x.png b/icons/icon_128x128@2x.png new file mode 100644 index 0000000..1feecf6 Binary files /dev/null and b/icons/icon_128x128@2x.png differ diff --git a/icons/icon_16x16.png b/icons/icon_16x16.png new file mode 100644 index 0000000..ab759d6 Binary files /dev/null and b/icons/icon_16x16.png differ diff --git a/icons/icon_16x16@2x.png b/icons/icon_16x16@2x.png new file mode 100644 index 0000000..f8550f5 Binary files /dev/null and b/icons/icon_16x16@2x.png differ diff --git a/icons/icon_22x22.png b/icons/icon_22x22.png new file mode 100644 index 0000000..ccbed83 Binary files /dev/null and b/icons/icon_22x22.png differ diff --git a/icons/icon_24x24.png b/icons/icon_24x24.png new file mode 100644 index 0000000..cf25d67 Binary files /dev/null and b/icons/icon_24x24.png differ diff --git a/icons/icon_256x256.png b/icons/icon_256x256.png new file mode 100644 index 0000000..b7cb5dc Binary files /dev/null and b/icons/icon_256x256.png differ diff --git a/icons/icon_256x256@2x.png b/icons/icon_256x256@2x.png new file mode 100644 index 0000000..0c73963 Binary files /dev/null and b/icons/icon_256x256@2x.png differ diff --git a/icons/icon_32x32.png b/icons/icon_32x32.png new file mode 100644 index 0000000..280993e Binary files /dev/null and b/icons/icon_32x32.png differ diff --git a/icons/icon_32x32@2x.png b/icons/icon_32x32@2x.png new file mode 100644 index 0000000..17e734a Binary files /dev/null and b/icons/icon_32x32@2x.png differ diff --git a/icons/icon_48x48.png b/icons/icon_48x48.png new file mode 100644 index 0000000..7252521 Binary files /dev/null and b/icons/icon_48x48.png differ diff --git a/icons/icon_512x512.png b/icons/icon_512x512.png new file mode 100644 index 0000000..0c73963 Binary files /dev/null and b/icons/icon_512x512.png differ diff --git a/icons/icon_512x512@2x.png b/icons/icon_512x512@2x.png new file mode 100644 index 0000000..97467d7 Binary files /dev/null and b/icons/icon_512x512@2x.png differ diff --git a/icons/icon_64x64.png b/icons/icon_64x64.png new file mode 100644 index 0000000..17a41ae Binary files /dev/null and b/icons/icon_64x64.png differ diff --git a/icons/icon_96x96.png b/icons/icon_96x96.png new file mode 100644 index 0000000..54bd8c6 Binary files /dev/null and b/icons/icon_96x96.png differ diff --git a/icons/icon_scalable.svg b/icons/icon_scalable.svg new file mode 100644 index 0000000..69f7434 --- /dev/null +++ b/icons/icon_scalable.svg @@ -0,0 +1,441 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/icons/icon_scalable_yellow.xcf b/icons/icon_scalable_yellow.xcf new file mode 100644 index 0000000..1e68f65 Binary files /dev/null and b/icons/icon_scalable_yellow.xcf differ diff --git a/icons/icon_yellow_512x512@2x.xcf b/icons/icon_yellow_512x512@2x.xcf new file mode 100644 index 0000000..5d4717e Binary files /dev/null and b/icons/icon_yellow_512x512@2x.xcf differ diff --git a/icons/radio_co_badge.png b/icons/radio_co_badge.png new file mode 100644 index 0000000..5957667 Binary files /dev/null and b/icons/radio_co_badge.png differ diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..ec298b5 --- /dev/null +++ b/install-sh @@ -0,0 +1,541 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2020-11-14.01; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +# Create dirs (including intermediate dirs) using mode 755. +# This is like GNU 'install' as of coreutils 8.32 (2020). +mkdir_umask=22 + +backupsuffix= +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -p pass -p to $cpprog. + -s $stripprog installed files. + -S SUFFIX attempt to back up existing files, with suffix SUFFIX. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG + +By default, rm is invoked with -f; when overridden with RMPROG, +it's up to you to specify -f if you want it. + +If -S is not specified, no backups are attempted. + +Email bug reports to bug-automake@gnu.org. +Automake home page: https://www.gnu.org/software/automake/ +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -p) cpprog="$cpprog -p";; + + -s) stripcmd=$stripprog;; + + -S) backupsuffix="$2" + shift;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + # Don't chown directories that already exist. + if test $dstdir_status = 0; then + chowncmd="" + fi + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dstbase=`basename "$src"` + case $dst in + */) dst=$dst$dstbase;; + *) dst=$dst/$dstbase;; + esac + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + case $dstdir in + */) dstdirslash=$dstdir;; + *) dstdirslash=$dstdir/;; + esac + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + # The $RANDOM variable is not portable (e.g., dash). Use it + # here however when possible just to lower collision chance. + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + + trap ' + ret=$? + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null + exit $ret + ' 0 + + # Because "mkdir -p" follows existing symlinks and we likely work + # directly in world-writeable /tmp, make sure that the '$tmpdir' + # directory is successfully created first before we actually test + # 'mkdir -p'. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=${dstdirslash}_inst.$$_ + rmtmp=${dstdirslash}_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && + { test -z "$stripcmd" || { + # Create $dsttmp read-write so that cp doesn't create it read-only, + # which would cause strip to fail. + if test -z "$doit"; then + : >"$dsttmp" # No need to fork-exec 'touch'. + else + $doit touch "$dsttmp" + fi + } + } && + $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # If $backupsuffix is set, and the file being installed + # already exists, attempt a backup. Don't worry if it fails, + # e.g., if mv doesn't support -f. + if test -n "$backupsuffix" && test -f "$dst"; then + $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null + fi + + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/m4/ChangeLog b/m4/ChangeLog new file mode 100644 index 0000000..9a90aab --- /dev/null +++ b/m4/ChangeLog @@ -0,0 +1,487 @@ +Version 0.1.41 (2024-03-17) +--------------------------- +* Add support for controlling BUTT via MIDI CC messages +* EQ and compressor can now be enabled independently for the stream and record path +* You can now use %N as a placeholder for the current server name in your record file/path +* Prevent BUTT from being disconnected by the server when using FLAC and the audio signal is 100% silent +* The signal and silence detection can now by activated/deactivated with a checkbox instead of simply setting the value to 0 +* Add -L parameter to get a list of available audio devices +* The ICY name and ICY description now support the same placeholders as the record file/path (activate the "expand variables" checkbox) +* Add Arabic language support (Thanks to Magd) +* Fix an issue that could lead BUTT to freeze on startup if no internet connection is available +* Overall stability improvements + +Version 0.1.40 (2023-11-24) +--------------------------- +* Support higher bitrates for AAC, Vorbis and Opus +* Add support for Plexamp on Linux +* Add Dutch language support (thanks to Timothy) +* Fix an issue with audio device names that contain special characters +* Fix possible buffer underflow when the connection to a shoutcast server fails + +Version 0.1.39 (2023-09-20) +--------------------------- +* Fix a bug that can cause the listener count to no longer be updated +* Fix a bug that can cause the split record file function to stop working +* Fix a bug that can cause butt not to reconnect after a connection loss +* Fix a bug that can cause undefined behaviour +* Clear song name if song file is empty + + +Version 0.1.38 (2023-08-05) +--------------------------- +* Users can now define a custom window title +* Add option to set a delay between automatic reconnects +* Add option to use the older Icecast SOURCE protocol instead of the newer PUT protocol +* Increase robustness of the config file importer +* Increase robustness of the show listeners function +* Use green instead of yellow to indicate a valid streaming connection +* Fix memory leak when using Icecast and showing the number of listeners +* Fix UI drawing issues +* Fix issue with the main window size on Windows 11 +* Fix issues with the tray agent on Windows + +Version 0.1.37 (2022-12-24) +--------------------------- +* Add support for a second audio device +* Streaming and recording volume can be set independently +* Add support for icecast-kh listener statistics +* Highlight connect and record buttons when active +* Restore window size if "Remember main window position" is active +* Increase size of slider knobs +* Start with default values in case the config file is damaged +* Always overwrite existing files when recording is started automatically or via butt client +* Do not stop recording if a butt client sends a disconnect command while butt is offline +* Fix an issue were butt mistakenly says "Connecting..." +* Fix memory leak if "Show listeners" is activate + +Version 0.1.36 (2022-10-03) +--------------------------- +* Number of current listeners can be displayed on the LCD (works only with original Icecast and Shoutcast implementations) +* Fix connection issue with AIS streaming server +* Fix connection issue with Icecast servers older than version 2.4.0 +* Fix issue with Shoutcast if mountpoint is already in use + + +Version 0.1.35 (2022-06-19) +--------------------------- +* Gain slider can be disabled to prevent inadvertently changing the volume +* Audio device initialization can be skipped by holding down CTRL during startup +* Fix crash if audio device can not be opened +* Fix crash if no default audio device can be found +* Fix wrong password detection for certain liquidsoap Shoutcast implementations +* Fix crash of command client and command server when very long song names are specified + +Version 0.1.34 (2022-04-21) +--------------------------- +* Added equalizer presets +* Added Spanish translation +* Use 32 bit float for internal audio processing instead of 16 bit integer +* FLAC can now be broadcasted and recorded as 16 bit or 24 bit +* WAV can now be recorded as 16 bit, 24 bit or 32 bit +* Massively improved client/server implementation for butt commands +* Fixed bug that caused overwriting the first wav samples of a recording +* Fixed read song name from Music.app for MacOS >= 11.0 +* Fixed record folder creation if folder contains format variables +* butt commands can now also be sent via UDP +* Added new fields to the server status message: + - stream seconds, stream kBytes + - record seconds, record kBytes + - volume left/right + - current song + - record path + +Version 0.1.33 (2022-02-06) +--------------------------- +* Windows: You can broadcast what's playing on your computer (audio device must support WASAPI) +* Windows/Linux: New butt-client for controlling running butt instances (Thanks to Hossam) +* Added support for higher samplerates (88.2 kHz and 96 kHz) +* Added Portuguese (Brazil) translation (Thanks to Bruno) +* Added signal and silence detection flags to the status information +* Time thresholds for signal detection can be changed via control commands (Thanks to Hossam) +* Format place holders (%Y %m %d etc.) can also be used in the folder name +* Song title update support for OPUS +* Fixed wrong file size in wav header +* Fixed compilation if --disable-ssl or --disable-aac was passed to ./configure + +Version 0.1.32 (2021-10-28) +--------------------------- +* Radio.co stations can now be easily added to butt +* Advanced codec settings for mp3, aac, ogg/vorbis and opus can now be adjusted +* The recordings folder may now contain environment variables like ~, $HOME and %USERPROFILE% +* Fixed issue with characters like $,%,&,§ in the song name +* Fixed connection issue in case the server domain has IPv4+6 addresses but Icecast is only listening on IPv4 +* Fixed missing song duration information in FLAC recordings + +Version 0.1.31 (2021-07-12) +--------------------------- +* A delay can now be added to the automatic song title update +* Increased equalizer from 5 to 10 frequency bands +* Fixed positioning issues on multi screen setups +* Maximum number of supported audio devices has been increased from 100 to 256 + +Version 0.1.30 (2021-05-14) +--------------------------- +* Added support for IPv6 +* Added French translation +* Right click on a slider knob brings up an input field where you can type in the slider value with the keyboard +* The selected audio device can now be remembered by device name instead by device id +* You can now rescan for new audio devices manually (no butt restart needed anymore after plugging in a new audio device) +* Holding the shift key during butt startup allows you to start with a fresh configuration file +* Updated Portaudio to version v19.7.0 +* Windows: Added support for WASAPI audio driver +* MacOS: Updated FLTK to version 1.3.6 +* MacOS: Native support for Apple Silicon (arm64) + +Version 0.1.29 (2021-03-28) +--------------------------- +* Added a new tool (butt Agent) which helps to minimize butt to tray and much more (Big thanks to Ivan Radolovic) +* Added an indicator to the compressor which lights up if the threshold is exceeded +* Added "Aggressive Mode" to the compressor. If activated, the signal power for threshold detection is not averraged +* Added new command line options: -q (quit) -n (split recording) -u (update song name) +* Added donation addresses for Bitcoin, Monero and Dash +* Fixed crash when butt can not find any input channels +* Fixed crash when reading song names from an UTF-8 formatted file that contains a BOM +* Fixed issue with icecast-kh14+ when connecting to a mountpoint which is already in use +* Fixed issue if both checkboxes "start recording after launch" and "start recording when connected" are checked +* Fixed butt.desktop file. Icon was not shown on GNOME panel +* Attack and Release compressor labels now have 2 decimal places instead of only 1 +* butt does not send bitrate information to the icecast server anymore if FLAC is used +* butt now searches for a free command server port if default port is already in use +* butt can now be started in minimized state +* The recording file name can now contain any well known date format specifier +* The window class name has been renamed from FLTK to butt_FLTK + +Version 0.1.28 (2021-02-07) +--------------------------- +* Fixed compressor issues +* Fixed song update when using Strawberry audio player +* The order of song update from an music app can be changed from "Title - Artist" to "Artist - Title" +* Increased accuracy of recording split timer +* VU-meter appearance can be changed to solid colors for better readability +* Log window can be vertically resized +* Windows: Changed default installation folder to %LOCALAPPDATA%\butt instead of %LOCALAPPDATA\butt- + + +Version 0.1.27 (2020-12-26) +--------------------------- +* Fixed loading of AAC codec selection from configuration file +* Fixed crash when using opus with a samplerate not equal to 48000 Hz + +Version 0.1.26 (2020-12-24) +--------------------------- +* Added ASIO support +* Added support for multi-channel audio devices +* Added multi-language support (i18n) +* Added German translation +* Added option to force reconnection regardless of the server response +* Added support for Strawberry audio player (Thanks to Stefan S.) +* Added config parameter to disable dithering (set disable_dithering=1 in cfg file) +* Fixed possible crash if server is not reachable +* Fixed possible crash when reconnecting +* Fixed possible crash when using FLAC and song update +* Fixed unwanted rounding of compressor values +* Fixed overwriting of a DSP setting if it was set to -1.0 +* Improved CPU usage +* Improved mono/stereo handling +* Improved overall song update implementation +* Compiles on FreeBSD (Thanks to Per G. and Tobias C. B.) + + +Version 0.1.25 (2020-10-26) +--------------------------- +* Added the ability to extend the song name with a prefix and a suffix +* Fixed issue with automatic song update from text files +* Fixed recording in FLAC + +Version 0.1.24 (2020-10-14) +--------------------------- +* VU-meter has been redesigned +* Fixed issues with usernames that contain special characters +* The port of the command server can be specified via command line +* Commands can be received via network +* It is possible to connect to a particular streaming server when sending the connect command +* You can ask a butt instance about its current status with the -S command +* butt can automatically check for updates after launch +* Update of song name works with FLAC +* Thresholds for signal detection can be specified +* Added -h command line option to get an overview of all available commands +* Updated the manual + +Version 0.1.23 (2020-09-27) +--------------------------- +* Fixed crash if the server is not reachable (e.g. unstable internet connections) +* Fixed issue with transfering song meta data from music apps to butt (MacOS) +* Improved handling of mic permissions dialog on MacOS + +Version 0.1.22 (2020-07-09) +--------------------------- +* Added Dynamic Range Compressor (thanks to Thomas P.) +* Added ability to check for new versions +* butt can now be controlled via command line +* Replaced experimental portaudio version with the stable portaudio version +* Fixed issue with stereo audio when using the Equalizer (thanks to Thomas P.) +* Fixed traffic calculation when using OPUS +* Fixed issue with OPUS encoding under some circumstances + +Version 0.1.21 (2020-05-26) +--------------------------- +* Streaming and recording can now be started automatically if an audio signal is present +* Fixed reconnection issue on unreliable network connections. Should now behave like 0.1.19 again +* wav recordings can now be up to 4 GB large +* Removed advanced section from the Audio tab. Buffer time can still be set in the configuration file if you need to + +Version 0.1.20 (2020-04-21) +--------------------------- +* Added SSL/TLS support for icecast +* Recording can now automatically be stopped if the user disconnects from the server +* Fixed icecast connection issue (mostly occurring on mobile internet connections like 4G/LTE) +* Fixed wrong password detection for liquidsoap based setups +* Fixed configuration export on MacOS +* Fixed logfile selection on MacOS +* Song name is not updated on reconnect anymore if the manual song name input field has been cleared +* Upgraded FLTK to version 1.3.5 + +Version 0.1.19 (2019-12-30) +--------------------------- +* The song name can now be read from the last line instead from the first line of a file +* Streaming and recording can now be automatically stopped after silence has been detected +* The last window position can be remembered. Useful when running multiple instances +* butt can now be started with hidden info window +* The vu-meter runs smoother and needs less cpu +* VU-meter peak hold is only active for the red light +* Closing butt while streaming or recording must be confirmed now +* Changes are now saved without asking for confirmation when closing the app +* Removed a new line character from the server name in the title bar +* Fixed recceiving song information from iTunes/Music in MacOS Catalina +* Fixed wrong counting of sent bytes when using AAC + + +Version 0.1.18 (2019-05-12) +--------------------------- +* Added support for automatic recording after starting butt +* Enabled AAC afterburner (improves audio quality) +* Fixed issue with configure.ac and s390x architecture +* Updated the FSF address in COPYING +* AAC libs are not delivered with the setup files anymore (read the manual on how to activate AAC support again) + + +Version 0.1.17 (2018-12-27) +--------------------------- +* Added support for FLAC streaming (icecast only) +* Added 5-band equalizer (thanks to Melchor Garau Madrigal) +* Added the ability to read song informations from several apps on MacOS and Linux (thanks to Melchor Garau Madrigal) +* Window title is automatically renamed to the connected server (useful when running multiple instances) +* Fixed connection issue with airtime +* Fixed integer overflow when gain is set too high +* Fixed compilation error on ubuntu 18 +* Changed color of windows icon from black to yellow. So people using Win10 can now find butt in their black taskbar ;-) + + +Version 0.1.16 (2017-09-17) +--------------------------- +* Fixed compatibility issues with shoutcast v2.5.5.732 +* Replaced portaudio by newest stable version v190600_20161030 +* When using AAC+ the best AAC profile for the current bitrate is selected automatically + + AAC+v2: bitrate < 48kBit/s (aac_aot = 29) + + AAC+v1: 48 kBit/s \<= bitrate < 96kBit/s (aac_aot = 5) + + AAC-LC: bitrate >= 96kBit/s (aac_aot = 2) + +* You can force the AAC codec to a specific profile by setting + aac_overwrite_aot = 1 and aac_aot to the appropriate aot value {2,5,29} in buttrc + + +Version 0.1.15 (2016-05-28) +--------------------------- +* Added AAC+ support +* Added a "Split now" button to instantly start a new recording file +* Improved look&feel on retina displays on OSX +* Improved compatibility with proxies/load balancers (thanks to boyska) +* Fixed handling of newline characters when reading the song name file +* Fixed evlauation of time/date variables when automatic file splitting is enabled +* Fixed compatibility with airtime servers +* Fixed ogg and opus support for ShoutCast + +Version 0.1.14 (2014-12-27) +--------------------------- +* Added FLAC support for recording +* Added Opus support (thanks to oneman) +* Added logfile support (thanks to mikko) +* Added support for more variables in the filename (%H %M %S) (thanks to mikko) +* Automatic file splitting can be synced to full hour now (thanks to mikko) +* LCD info can automatically rotate every 5 seconds now (thanks to mikko) +* Added ability to change audio buffer size +* Uncluttered LCD (thanks to mikko) +* File extension of record filename gets automatically updated now +* Dropped support of different samplerate/channels for stream and record +* Resorted settings elements/widgets +* Removed possible memleaks +* Connecting to an unreachable server does not freeze the GUI anymore +* Fixed icecast and shoutcast meta data handling +* ;ade update song from file more robust +* "update song name manually" reacts on Enter button now + +Version 0.1.13 (2014-05-02) +--------------------------- +* Has an icon now! - Thanks to Subrat (ipapuna) Nayak +* Added support for lower bitrates (24k, 16k, 8k) +* Added support for user defined configuration path e.g. "butt -c " +* Added support for user names in Icecast +* Added gain slider. This slider multiplies the audio input samples with the given factor +* Added .manifest file to disable the VirtualStore on Windows Vista and higher +* Added the ability to automatically split the recording every 'n' minutes +* Added feature for importing and exporting configuration files +* Compiles with Xcode 5 on OS X Mavericks +* Compiles with traditional GNU autoconf/automake environment on linux and mingw +* Improved robustness against faulty config files +* Improved compatibility to ShoutCast v2 servers +* Improved look&feel +* Fixed samplerate issues +* Fixed mono playback/recording +* Changed data volume information vom kBytes to MBytes +* Changed default recording path to users home folder +* Sends audio information (bitrate etc.) to Icecast server - Thanks to Dominik Durner +* Reimplemented VU-Meter with peak hold +* Comes with as an ubuntu package +* Windows: can be installed as user without admin rights +* Windows: uninstallation process also removes the configuration file +* Instead of canceling the automatic song update in case the given file is not +readable, butt now tries to reread the file every 5 seconds + +Version 0.1.12 (2010-04-10) +--------------------------- +* butt is now able to connect automatically after startup +* Shortened time between connect attempts (fixes Shouted.FM connection problems) +* Improved wrong password detection for shoutcast + +Version 0.1.11-2 (2008-12-14) +----------------------------- +* Fixed display info after automatic reconnection + +Version 0.1.11-1 (2008-11-09) +----------------------------- +* Fixed segfault if there is no '.' in the filename + +Version 0.1.11 (2008-10-26) +--------------------------- +* Fixed unintended disconnects +* Fixed recording problems +* Removed buffer overrun messages +* Recording can be now stopped with the stop-button +* Replaced pcm recording by wav recording +* Recording as ogg is now possible +* Added "stay on top" checkbox +* Fixed possible crash when changing mp3 settings while streaming + +Version 0.1.10 (2008-05-25) +--------------------------- +* Removed xrun "led". Instead the msg window informs the user about overruns +* Added dB values to the vu-meter +* Fixed bitrate/samplerate selection for ogg +* Network backend works with non-blocking sockets now +* libshout is not needed anymore +* Songname can be updated from a textfile now +* More samplerates are supported now +* Fixed samplerate selection problems +* Fixed crash when connecting to icecast server on MacOS 10.4 +* Fixed crash when changing the server type from shoutcast to icecast +* Some cosmetic changes (buttons, LEDs) + +Version 0.1.9 (2008-04-10) +-------------------------- +* Minor GUI makeup +* Made butt more verbose +* Fixed possible segfault when trying to EDIT stream info +* Fixed automatic reconnection +* Filenames can be indexed with the %i variable now +* Renamed "rec not until connected" checkbox to "start rec. when connected" +* Added orange record icon for "armed" state ("start rec. when connected" = 1) +* butt starts recording as soon as connected, when in "armed" state + +Version 0.1.8 (2008-03-30) +-------------------------- + +* Text/bg color can be changed in the [GUI] tab +* Removed the "Config saved" popup message +* Added pcm recording +* Improoved record handling +* The config menu is more user friendly now +* Fixed crash when connection loss +* The user may select the samplerate now +* The config window can be attached to the main window now +* Fixed bitrate and codec ShoutCast info + +Version 0.1.7rc1 (2008-01-04) +----------------------------- +* butt runs on MacOS 10.4 and 10.5 now! +* Added recording time to the display info +* Fixed bug with '&' in the song string +* Changing the display mode works only when connected now +* Added a checkbox which lets the user decide if the recording should start +right after selecting the output file or when connected +* Added a msg box which ask the user if he wants to stop the recording +when disconnecting + + +Version 0.1.6 (2007-12-08) +--------------------------- +* Added status symbols to the display +* Recording runs with a seperate thread now! +* Added a button for showing/hiding the server password + +Version 0.1.5 (2007-11-22) +--------------------------- +* Minor GUI changes +* Fixed streaming/recording with mp3 320kb/s +* Fixed segfault in Fl_ILM216.cpp +* The user may change the display colors now (right click on the display) +* The "connecting" info on the display updates faster now +* Changed default display colors to white/blue + +Version 0.1.5rc1 (2007-11-16) +----------------------------- +* Replaced ALSA by PortAudio -> OSS is supported now +* Ported butt to Microsoft Windows (tested with win2k and win xp) +* butt reminds the user about unsaved changes when closing now +* Starting the recording is possible at any time now +* Added mono encoding for OGG +* Improved some GUI stuff +* Improved CPU usage + +Version 0.1.4rc2 (2007-11-03) +----------------------------- +* butt should compile on more machines now + +Version 0.1.4rc1 (2007-11-01) +----------------------------- +* Added IceCast support (ogg and mp3) +* Added ./configure script +* butt is now able to send the "Current Song" value to the ShoutCast/IceCast server +* Changed stereo mode from joint-stereo to real-stereo +* Code cleanup + +Version 0.1.3 (2007-10-08) +--------------------------- +* Bugfix: butt crashed if you press "apply" in the server/icy tab without +having an server/ICY-entry +* Bugfix: butt crashed if you change the bitrate without having an ICY-entry +* Bugfix: there was some uncommented code in the [DEL]-server callback-routine +which shouldn't be uncommented +* Facelift: if you delete all server/ICY-entries, the input fields in the server/ICY +still showed the values of the last server/ICY-entry + +Version 0.1.2 (2007-10-07) +-------------------------- +* Added a GUI for configuring butt +* Comments behind config entries are not allowed anymore. +* Removed the network init part. It was nonsense +* Fixed mono playblack +* Fixed recording problems +* ICY entries can now be empty without causing butt to crash +* butt shows the real port in its "connecting to..."-info line now and the "pseudeo" port in parenthesis +* Fixed a bug which causes pcm data loss in some cases + +Version 0.1.1 (2007-09-16) +-------------------------- +* Added recording feature +* Fixed seg fault on startup when compiled with gcc-4.1.2 +* Fixed seg fault when encoding with high bitrates diff --git a/m4/gettext.m4 b/m4/gettext.m4 new file mode 100644 index 0000000..be247bf --- /dev/null +++ b/m4/gettext.m4 @@ -0,0 +1,401 @@ +# gettext.m4 serial 66 (gettext-0.18.2) +dnl Copyright (C) 1995-2014 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2006, 2008-2010. + +dnl Macro to add for using GNU gettext. + +dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). +dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The +dnl default (if it is not specified or empty) is 'no-libtool'. +dnl INTLSYMBOL should be 'external' for packages with no intl directory, +dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. +dnl If INTLSYMBOL is 'use-libtool', then a libtool library +dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, +dnl depending on --{enable,disable}-{shared,static} and on the presence of +dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library +dnl $(top_builddir)/intl/libintl.a will be created. +dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext +dnl implementations (in libc or libintl) without the ngettext() function +dnl will be ignored. If NEEDSYMBOL is specified and is +dnl 'need-formatstring-macros', then GNU gettext implementations that don't +dnl support the ISO C 99 formatstring macros will be ignored. +dnl INTLDIR is used to find the intl libraries. If empty, +dnl the value '$(top_builddir)/intl/' is used. +dnl +dnl The result of the configuration is one of three cases: +dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled +dnl and used. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 2) GNU gettext has been found in the system's C library. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 3) No internationalization, always use English msgid. +dnl Catalog format: none +dnl Catalog extension: none +dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. +dnl The use of .gmo is historical (it was needed to avoid overwriting the +dnl GNU format catalogs when building on a platform with an X/Open gettext), +dnl but we keep it in order not to force irrelevant filename changes on the +dnl maintainers. +dnl +AC_DEFUN([AM_GNU_GETTEXT], +[ + dnl Argument checking. + ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , + [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT +])])])])]) + ifelse(ifelse([$1], [], [old])[]ifelse([$1], [no-libtool], [old]), [old], + [AC_DIAGNOSE([obsolete], [Use of AM_GNU_GETTEXT without [external] argument is deprecated.])]) + ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , + [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT +])])])]) + define([gt_included_intl], + ifelse([$1], [external], + ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]), + [yes])) + define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], [])) + gt_NEEDS_INIT + AM_GNU_GETTEXT_NEED([$2]) + + AC_REQUIRE([AM_PO_SUBDIRS])dnl + ifelse(gt_included_intl, yes, [ + AC_REQUIRE([AM_INTL_SUBDIR])dnl + ]) + + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Sometimes libintl requires libiconv, so first search for libiconv. + dnl Ideally we would do this search only after the + dnl if test "$USE_NLS" = "yes"; then + dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT + dnl the configure script would need to contain the same shell code + dnl again, outside any 'if'. There are two solutions: + dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. + dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. + dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not + dnl documented, we avoid it. + ifelse(gt_included_intl, yes, , [ + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + ]) + + dnl Sometimes, on Mac OS X, libintl requires linking with CoreFoundation. + gt_INTL_MACOSX + + dnl Set USE_NLS. + AC_REQUIRE([AM_NLS]) + + ifelse(gt_included_intl, yes, [ + BUILD_INCLUDED_LIBINTL=no + USE_INCLUDED_LIBINTL=no + ]) + LIBINTL= + LTLIBINTL= + POSUB= + + dnl Add a version number to the cache macros. + case " $gt_needs " in + *" need-formatstring-macros "*) gt_api_version=3 ;; + *" need-ngettext "*) gt_api_version=2 ;; + *) gt_api_version=1 ;; + esac + gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" + gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + ifelse(gt_included_intl, yes, [ + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH([included-gettext], + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT([$nls_cv_force_use_gnu_gettext]) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + ]) + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If GNU gettext is available we use this. Else we have + dnl to fall back to GNU NLS library. + + if test $gt_api_version -ge 3; then + gt_revision_test_code=' +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +changequote(,)dnl +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +changequote([,])dnl +' + else + gt_revision_test_code= + fi + if test $gt_api_version -ge 2; then + gt_expression_test_code=' + * ngettext ("", "", 0)' + else + gt_expression_test_code= + fi + + AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings; + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings + ]])], + [eval "$gt_func_gnugettext_libc=yes"], + [eval "$gt_func_gnugettext_libc=no"])]) + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl Sometimes libintl requires libiconv, so first search for libiconv. + ifelse(gt_included_intl, yes, , [ + AM_ICONV_LINK + ]) + dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL + dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) + dnl because that would add "-liconv" to LIBINTL and LTLIBINTL + dnl even if libiconv doesn't exist. + AC_LIB_LINKFLAGS_BODY([intl]) + AC_CACHE_CHECK([for GNU gettext in libintl], + [$gt_func_gnugettext_libintl], + [gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + dnl Now see whether libintl exists and does not depend on libiconv. + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + ]])], + [eval "$gt_func_gnugettext_libintl=yes"], + [eval "$gt_func_gnugettext_libintl=no"]) + dnl Now see whether libintl exists and depends on libiconv. + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + ]])], + [LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + eval "$gt_func_gnugettext_libintl=yes" + ]) + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS"]) + fi + + dnl If an already present or preinstalled GNU gettext() is found, + dnl use it. But if this macro is used in GNU gettext, and GNU + dnl gettext is already preinstalled in libintl, we update this + dnl libintl. (Cf. the install rule in intl/Makefile.in.) + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ + || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + dnl Reset the values set by searching for libintl. + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + ifelse(gt_included_intl, yes, [ + if test "$gt_use_preinstalled_gnugettext" != "yes"; then + dnl GNU gettext is not found in the C library. + dnl Fall back on included GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + BUILD_INCLUDED_LIBINTL=yes + USE_INCLUDED_LIBINTL=yes + LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD" + LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD" + LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` + fi + + CATOBJEXT= + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions to use GNU gettext tools. + CATOBJEXT=.gmo + fi + ]) + + if test -n "$INTL_MACOSX_LIBS"; then + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Some extra flags are needed during linking. + LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" + LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" + fi + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + AC_DEFINE([ENABLE_NLS], [1], + [Define to 1 if translation of program messages to the user's native language + is requested.]) + else + USE_NLS=no + fi + fi + + AC_MSG_CHECKING([whether to use NLS]) + AC_MSG_RESULT([$USE_NLS]) + if test "$USE_NLS" = "yes"; then + AC_MSG_CHECKING([where the gettext function comes from]) + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + AC_MSG_RESULT([$gt_source]) + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + AC_MSG_CHECKING([how to link with libintl]) + AC_MSG_RESULT([$LIBINTL]) + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) + fi + + dnl For backward compatibility. Some packages may be using this. + AC_DEFINE([HAVE_GETTEXT], [1], + [Define if the GNU gettext() function is already present or preinstalled.]) + AC_DEFINE([HAVE_DCGETTEXT], [1], + [Define if the GNU dcgettext() function is already present or preinstalled.]) + fi + + dnl We need to process the po/ directory. + POSUB=po + fi + + ifelse(gt_included_intl, yes, [ + dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL + dnl to 'yes' because some of the testsuite requires it. + if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then + BUILD_INCLUDED_LIBINTL=yes + fi + + dnl Make all variables we use known to autoconf. + AC_SUBST([BUILD_INCLUDED_LIBINTL]) + AC_SUBST([USE_INCLUDED_LIBINTL]) + AC_SUBST([CATOBJEXT]) + + dnl For backward compatibility. Some configure.ins may be using this. + nls_cv_header_intl= + nls_cv_header_libgt= + + dnl For backward compatibility. Some Makefiles may be using this. + DATADIRNAME=share + AC_SUBST([DATADIRNAME]) + + dnl For backward compatibility. Some Makefiles may be using this. + INSTOBJEXT=.mo + AC_SUBST([INSTOBJEXT]) + + dnl For backward compatibility. Some Makefiles may be using this. + GENCAT=gencat + AC_SUBST([GENCAT]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLOBJS= + if test "$USE_INCLUDED_LIBINTL" = yes; then + INTLOBJS="\$(GETTOBJS)" + fi + AC_SUBST([INTLOBJS]) + + dnl Enable libtool support if the surrounding package wishes it. + INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix + AC_SUBST([INTL_LIBTOOL_SUFFIX_PREFIX]) + ]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLLIBS="$LIBINTL" + AC_SUBST([INTLLIBS]) + + dnl Make all documented variables known to autoconf. + AC_SUBST([LIBINTL]) + AC_SUBST([LTLIBINTL]) + AC_SUBST([POSUB]) +]) + + +dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized. +m4_define([gt_NEEDS_INIT], +[ + m4_divert_text([DEFAULTS], [gt_needs=]) + m4_define([gt_NEEDS_INIT], []) +]) + + +dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL]) +AC_DEFUN([AM_GNU_GETTEXT_NEED], +[ + m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"]) +]) + + +dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) +AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) diff --git a/m4/iconv.m4 b/m4/iconv.m4 new file mode 100644 index 0000000..4b29c5f --- /dev/null +++ b/m4/iconv.m4 @@ -0,0 +1,268 @@ +# iconv.m4 serial 18 (gettext-0.18.2) +dnl Copyright (C) 2000-2002, 2007-2014 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], +[ + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([iconv]) +]) + +AC_DEFUN([AM_ICONV_LINK], +[ + dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and + dnl those with the standalone portable GNU libiconv installed). + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + + dnl Add $INCICONV to CPPFLAGS before performing the following checks, + dnl because if the user has installed libiconv and not disabled its use + dnl via --without-libiconv-prefix, he wants to use it. The first + dnl AC_LINK_IFELSE will then fail, the second AC_LINK_IFELSE will succeed. + am_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) + + AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [ + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_func_iconv=yes]) + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_lib_iconv=yes] + [am_cv_func_iconv=yes]) + LIBS="$am_save_LIBS" + fi + ]) + if test "$am_cv_func_iconv" = yes; then + AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [ + dnl This tests against bugs in AIX 5.1, AIX 6.1..7.1, HP-UX 11.11, + dnl Solaris 10. + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +int main () +{ + int result = 0; + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 1; + iconv_close (cd_utf8_to_88591); + } + } + /* Test against Solaris 10 bug: Failures are not distinguishable from + successful returns. */ + { + iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); + if (cd_ascii_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\263"; + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_ascii_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 2; + iconv_close (cd_ascii_to_88591); + } + } + /* Test against AIX 6.1..7.1 bug: Buffer overrun. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304"; + static char buf[2] = { (char)0xDE, (char)0xAD }; + const char *inptr = input; + size_t inbytesleft = 1; + char *outptr = buf; + size_t outbytesleft = 1; + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) + result |= 4; + iconv_close (cd_88591_to_utf8); + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + result |= 8; + iconv_close (cd_88591_to_utf8); + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + result |= 16; + return result; +}]])], + [am_cv_func_iconv_works=yes], + [am_cv_func_iconv_works=no], + [ +changequote(,)dnl + case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac +changequote([,])dnl + ]) + LIBS="$am_save_LIBS" + ]) + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + AC_DEFINE([HAVE_ICONV], [1], + [Define if you have the iconv() function and it works.]) + fi + if test "$am_cv_lib_iconv" = yes; then + AC_MSG_CHECKING([how to link with libiconv]) + AC_MSG_RESULT([$LIBICONV]) + else + dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV + dnl either. + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + AC_SUBST([LIBICONV]) + AC_SUBST([LTLIBICONV]) +]) + +dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to +dnl avoid warnings like +dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required". +dnl This is tricky because of the way 'aclocal' is implemented: +dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN. +dnl Otherwise aclocal's initial scan pass would miss the macro definition. +dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions. +dnl Otherwise aclocal would emit many "Use of uninitialized value $1" +dnl warnings. +m4_define([gl_iconv_AC_DEFUN], + m4_version_prereq([2.64], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [m4_ifdef([gl_00GNULIB], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [[AC_DEFUN( + [$1], [$2])]])])) +gl_iconv_AC_DEFUN([AM_ICONV], +[ + AM_ICONV_LINK + if test "$am_cv_func_iconv" = yes; then + AC_MSG_CHECKING([for iconv declaration]) + AC_CACHE_VAL([am_cv_proto_iconv], [ + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif + ]], + [[]])], + [am_cv_proto_iconv_arg1=""], + [am_cv_proto_iconv_arg1="const"]) + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) + am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + AC_MSG_RESULT([ + $am_cv_proto_iconv]) + AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1], + [Define as const if the declaration of iconv() needs const.]) + dnl Also substitute ICONV_CONST in the gnulib generated . + m4_ifdef([gl_ICONV_H_DEFAULTS], + [AC_REQUIRE([gl_ICONV_H_DEFAULTS]) + if test -n "$am_cv_proto_iconv_arg1"; then + ICONV_CONST="const" + fi + ]) + fi +]) diff --git a/m4/intlmacosx.m4 b/m4/intlmacosx.m4 new file mode 100644 index 0000000..8a045f6 --- /dev/null +++ b/m4/intlmacosx.m4 @@ -0,0 +1,56 @@ +# intlmacosx.m4 serial 5 (gettext-0.18.2) +dnl Copyright (C) 2004-2014 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Checks for special options needed on Mac OS X. +dnl Defines INTL_MACOSX_LIBS. +AC_DEFUN([gt_INTL_MACOSX], +[ + dnl Check for API introduced in Mac OS X 10.2. + AC_CACHE_CHECK([for CFPreferencesCopyAppValue], + [gt_cv_func_CFPreferencesCopyAppValue], + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[CFPreferencesCopyAppValue(NULL, NULL)]])], + [gt_cv_func_CFPreferencesCopyAppValue=yes], + [gt_cv_func_CFPreferencesCopyAppValue=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], [1], + [Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) + fi + dnl Check for API introduced in Mac OS X 10.3. + AC_CACHE_CHECK([for CFLocaleCopyCurrent], [gt_cv_func_CFLocaleCopyCurrent], + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[CFLocaleCopyCurrent();]])], + [gt_cv_func_CFLocaleCopyCurrent=yes], + [gt_cv_func_CFLocaleCopyCurrent=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], [1], + [Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + AC_SUBST([INTL_MACOSX_LIBS]) +]) diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4 new file mode 100644 index 0000000..ddc569f --- /dev/null +++ b/m4/lib-ld.m4 @@ -0,0 +1,119 @@ +# lib-ld.m4 serial 6 +dnl Copyright (C) 1996-2003, 2009-2014 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Subroutines of libtool.m4, +dnl with replacements s/_*LT_PATH/AC_LIB_PROG/ and s/lt_/acl_/ to avoid +dnl collision with libtool.m4. + +dnl From libtool-2.4. Sets the variable with_gnu_ld to yes or no. +AC_DEFUN([AC_LIB_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld], +[# I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 /dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo "$ac_prog"| sed 's%\\\\%/%g'` + while echo "$ac_prog" | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL([acl_cv_path_LD], +[if test -z "$LD"; then + acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$acl_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 = 1.10 to complain if config.rpath is missing. + m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) + AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS + AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld + AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host + AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir + AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [ + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + ]) + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + dnl Determine whether the user wants rpath handling at all. + AC_ARG_ENABLE([rpath], + [ --disable-rpath do not hardcode runtime library paths], + :, enable_rpath=yes) +]) + +dnl AC_LIB_FROMPACKAGE(name, package) +dnl declares that libname comes from the given package. The configure file +dnl will then not have a --with-libname-prefix option but a +dnl --with-package-prefix option. Several libraries can come from the same +dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar +dnl macro call that searches for libname. +AC_DEFUN([AC_LIB_FROMPACKAGE], +[ + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_frompackage_]NAME, [$2]) + popdef([NAME]) + pushdef([PACK],[$2]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_libsinpackage_]PACKUP, + m4_ifdef([acl_libsinpackage_]PACKUP, [m4_defn([acl_libsinpackage_]PACKUP)[, ]],)[lib$1]) + popdef([PACKUP]) + popdef([PACK]) +]) + +dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. +dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found +dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_LINKFLAGS_BODY], +[ + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])]) + dnl Autoconf >= 2.61 supports dots in --with options. + pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[m4_translit(PACK,[.],[_])],PACK)]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_ARG_WITH(P_A_C_K[-prefix], +[[ --with-]]P_A_C_K[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib + --without-]]P_A_C_K[[-prefix don't search for ]PACKLIBS[ in includedir and libdir]], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi +]) + dnl Search the library and its dependencies in $additional_libdir and + dnl $LDFLAGS. Using breadth-first-seach. + LIB[]NAME= + LTLIB[]NAME= + INC[]NAME= + LIB[]NAME[]_PREFIX= + dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been + dnl computed. So it has to be reset here. + HAVE_LIB[]NAME= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='$1 $2' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + dnl See if it was already located by an earlier AC_LIB_LINKFLAGS + dnl or AC_LIB_HAVE_LINKFLAGS call. + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" + else + dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined + dnl that this library doesn't exist. So just drop it. + : + fi + else + dnl Search the library lib$name in $additional_libdir and $LDFLAGS + dnl and the already constructed $LIBNAME/$LTLIBNAME. + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + dnl The same code as in the loop below: + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + dnl Found the library. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + dnl Linking with a shared library. We attempt to hardcode its + dnl directory into the executable's runpath, unless it's the + dnl standard /usr/lib. + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + dnl No hardcoding is needed. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + dnl The hardcoding into $LIBNAME is system dependent. + if test "$acl_hardcode_direct" = yes; then + dnl Using DIR/libNAME.so during linking hardcodes DIR into the + dnl resulting binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + dnl Rely on "-L$found_dir". + dnl But don't add it if it's already contained in the LDFLAGS + dnl or the already constructed $LIBNAME + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH + dnl here, because this doesn't fit in flags passed to the + dnl compiler. So give up. No hardcoding. This affects only + dnl very old systems. + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + dnl Linking with a static library. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" + else + dnl We shouldn't come here, but anyway it's good to have a + dnl fallback. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" + fi + fi + dnl Assume the include files are nearby. + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + dnl Potentially add $additional_includedir to $INCNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's /usr/local/include and we are using GCC on Linux, + dnl 3. if it's already present in $CPPFLAGS or the already + dnl constructed $INCNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INC[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $INCNAME. + INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + dnl Look for dependencies. + if test -n "$found_la"; then + dnl Read the .la file. It defines the variables + dnl dlname, library_names, old_library, dependency_libs, current, + dnl age, revision, installed, dlopen, dlpreopen, libdir. + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + dnl We use only dependency_libs. + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's /usr/local/lib and we are using GCC on Linux, + dnl 3. if it's already present in $LDFLAGS or the already + dnl constructed $LIBNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LIBNAME. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LTLIBNAME. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + dnl Handle this in the next round. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + dnl Handle this in the next round. Throw away the .la's + dnl directory; it is already contained in a preceding -L + dnl option. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + dnl Most likely an immediate library name. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" + ;; + esac + done + fi + else + dnl Didn't find the library; assume it is in the system directories + dnl known to the linker and runtime loader. (All the system + dnl directories known to the linker should also be known to the + dnl runtime loader, otherwise the system is severely misconfigured.) + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user must + dnl pass all path elements in one option. We can arrange that for a + dnl single library, but not when more than one $LIBNAMEs are used. + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl. + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + else + dnl The -rpath options are cumulative. + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + dnl When using libtool, the option that works for both libraries and + dnl executables is -R. The -R options are cumulative. + for found_dir in $ltrpathdirs; do + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" + done + fi + popdef([P_A_C_K]) + popdef([PACKLIBS]) + popdef([PACKUP]) + popdef([PACK]) + popdef([NAME]) +]) + +dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, +dnl unless already present in VAR. +dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes +dnl contains two or three consecutive elements that belong together. +AC_DEFUN([AC_LIB_APPENDTOVAR], +[ + for element in [$2]; do + haveit= + for x in $[$1]; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + [$1]="${[$1]}${[$1]:+ }$element" + fi + done +]) + +dnl For those cases where a variable contains several -L and -l options +dnl referring to unknown libraries and directories, this macro determines the +dnl necessary additional linker options for the runtime path. +dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) +dnl sets LDADDVAR to linker options needed together with LIBSVALUE. +dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, +dnl otherwise linking without libtool is assumed. +AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], +[ + AC_REQUIRE([AC_LIB_RPATH]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + $1= + if test "$enable_rpath" != no; then + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode directories into the resulting + dnl binary. + rpathdirs= + next= + for opt in $2; do + if test -n "$next"; then + dir="$next" + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= + else + case $opt in + -L) next=yes ;; + -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= ;; + *) next= ;; + esac + fi + done + if test "X$rpathdirs" != "X"; then + if test -n ""$3""; then + dnl libtool is used for linking. Use -R options. + for dir in $rpathdirs; do + $1="${$1}${$1:+ }-R$dir" + done + else + dnl The linker is used for linking directly. + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user + dnl must pass all path elements in one option. + alldirs= + for dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="$flag" + else + dnl The -rpath options are cumulative. + for dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="${$1}${$1:+ }$flag" + done + fi + fi + fi + fi + fi + AC_SUBST([$1]) +]) diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4 new file mode 100644 index 0000000..31f49e4 --- /dev/null +++ b/m4/lib-prefix.m4 @@ -0,0 +1,224 @@ +# lib-prefix.m4 serial 7 (gettext-0.18) +dnl Copyright (C) 2001-2005, 2008-2014 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and +dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't +dnl require excessive bracketing. +ifdef([AC_HELP_STRING], +[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], +[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) + +dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed +dnl to access previously installed libraries. The basic assumption is that +dnl a user will want packages to use other packages he previously installed +dnl with the same --prefix option. +dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate +dnl libraries, but is otherwise very convenient. +AC_DEFUN([AC_LIB_PREFIX], +[ + AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib-prefix], +[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib + --without-lib-prefix don't search for libraries in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi +]) + if test $use_additional = yes; then + dnl Potentially add $additional_includedir to $CPPFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's already present in $CPPFLAGS, + dnl 3. if it's /usr/local/include and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + for x in $CPPFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $CPPFLAGS. + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" + fi + fi + fi + fi + dnl Potentially add $additional_libdir to $LDFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's already present in $LDFLAGS, + dnl 3. if it's /usr/local/lib and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + for x in $LDFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LDFLAGS. + LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" + fi + fi + fi + fi + fi +]) + +dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, +dnl acl_final_exec_prefix, containing the values to which $prefix and +dnl $exec_prefix will expand at the end of the configure script. +AC_DEFUN([AC_LIB_PREPARE_PREFIX], +[ + dnl Unfortunately, prefix and exec_prefix get only finally determined + dnl at the end of configure. + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the +dnl variables prefix and exec_prefix bound to the values they will have +dnl at the end of the configure script. +AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], +[ + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + $1 + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_PREPARE_MULTILIB creates +dnl - a variable acl_libdirstem, containing the basename of the libdir, either +dnl "lib" or "lib64" or "lib/64", +dnl - a variable acl_libdirstem2, as a secondary possible value for +dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or +dnl "lib/amd64". +AC_DEFUN([AC_LIB_PREPARE_MULTILIB], +[ + dnl There is no formal standard regarding lib and lib64. + dnl On glibc systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine + dnl the compiler's default mode by looking at the compiler's library search + dnl path. If at least one of its elements ends in /lib64 or points to a + dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI. + dnl Otherwise we use the default, namely "lib". + dnl On Solaris systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or + dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib. + AC_REQUIRE([AC_CANONICAL_HOST]) + acl_libdirstem=lib + acl_libdirstem2= + case "$host_os" in + solaris*) + dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment + dnl . + dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link." + dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the + dnl symlink is missing, so we set acl_libdirstem2 too. + AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit], + [AC_EGREP_CPP([sixtyfour bits], [ +#ifdef _LP64 +sixtyfour bits +#endif + ], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no]) + ]) + if test $gl_cv_solaris_64bit = yes; then + acl_libdirstem=lib/64 + case "$host_cpu" in + sparc*) acl_libdirstem2=lib/sparcv9 ;; + i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; + esac + fi + ;; + *) + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + */../ | */.. ) + # Better ignore directories of this form. They are misleading. + ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + ;; + esac + test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" +]) diff --git a/m4/nls.m4 b/m4/nls.m4 new file mode 100644 index 0000000..53cdc8b --- /dev/null +++ b/m4/nls.m4 @@ -0,0 +1,32 @@ +# nls.m4 serial 5 (gettext-0.18) +dnl Copyright (C) 1995-2003, 2005-2006, 2008-2014 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ([2.50]) + +AC_DEFUN([AM_NLS], +[ + AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE([nls], + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT([$USE_NLS]) + AC_SUBST([USE_NLS]) +]) diff --git a/m4/po.m4 b/m4/po.m4 new file mode 100644 index 0000000..84659ea --- /dev/null +++ b/m4/po.m4 @@ -0,0 +1,453 @@ +# po.m4 serial 22 (gettext-0.19) +dnl Copyright (C) 1995-2014 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ([2.60]) + +dnl Checks for all prerequisites of the po subdirectory. +AC_DEFUN([AM_PO_SUBDIRS], +[ + AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AC_PROG_MKDIR_P])dnl + AC_REQUIRE([AC_PROG_SED])dnl + AC_REQUIRE([AM_NLS])dnl + + dnl Release version of the gettext macros. This is used to ensure that + dnl the gettext macros and po/Makefile.in.in are in sync. + AC_SUBST([GETTEXT_MACRO_VERSION], [0.19]) + + dnl Perform the following tests also if --disable-nls has been given, + dnl because they are needed for "make dist" to work. + + dnl Search for GNU msgfmt in the PATH. + dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. + dnl The second test excludes FreeBSD msgfmt. + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + AC_PATH_PROG([GMSGFMT], [gmsgfmt], [$MSGFMT]) + + dnl Test whether it is GNU msgfmt >= 0.15. +changequote(,)dnl + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([MSGFMT_015]) +changequote(,)dnl + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([GMSGFMT_015]) + + dnl Search for GNU xgettext 0.12 or newer in the PATH. + dnl The first test excludes Solaris xgettext and early GNU xgettext versions. + dnl The second test excludes FreeBSD xgettext. + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + dnl Remove leftover from FreeBSD xgettext call. + rm -f messages.po + + dnl Test whether it is GNU xgettext >= 0.15. +changequote(,)dnl + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac +changequote([,])dnl + AC_SUBST([XGETTEXT_015]) + + dnl Search for GNU msgmerge 0.11 or newer in the PATH. + AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, + [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :) + + dnl Installation directories. + dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we + dnl have to define it here, so that it can be used in po/Makefile. + test -n "$localedir" || localedir='${datadir}/locale' + AC_SUBST([localedir]) + + dnl Support for AM_XGETTEXT_OPTION. + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + AC_SUBST([XGETTEXT_EXTRA_OPTIONS]) + + AC_CONFIG_COMMANDS([po-directories], [[ + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + # Treat a directory as a PO directory if and only if it has a + # POTFILES.in file. This allows packages to have multiple PO + # directories under different names or in different locations. + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + gt_tab=`printf '\t'` + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ${gt_tab}]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + done]], + [# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake < 1.5. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + ]) +]) + +dnl Postprocesses a Makefile in a directory containing PO files. +AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], +[ + # When this code is run, in config.status, two variables have already been + # set: + # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, + # - LINGUAS is the value of the environment variable LINGUAS at configure + # time. + +changequote(,)dnl + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + # Find a way to echo strings without interpreting backslash. + if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='echo' + else + if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='printf %s\n' + else + echo_func () { + cat < "$ac_file.tmp" + tab=`printf '\t'` + if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + cat >> "$ac_file.tmp" < /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` + cat >> "$ac_file.tmp" <> "$ac_file.tmp" <, 1996. + +AC_PREREQ([2.50]) + +# Search path for a program which passes the given test. + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN([AM_PATH_PROG_WITH_TEST], +[ +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL([ac_cv_path_$1], +[case "[$]$1" in + [[\\/]]* | ?:[[\\/]]*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in ifelse([$5], , $PATH, [$5]); do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then + AC_MSG_RESULT([$][$1]) +else + AC_MSG_RESULT([no]) +fi +AC_SUBST([$1])dnl +]) diff --git a/missing b/missing new file mode 100755 index 0000000..1fe1611 --- /dev/null +++ b/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 1996-2021 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=https://www.perl.org/ +flex_URL=https://github.com/westes/flex +gnu_software_URL=https://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/player_plugins/amarok/butt_amarok.amarokscript.tar.bz2 b/player_plugins/amarok/butt_amarok.amarokscript.tar.bz2 new file mode 100644 index 0000000..0bcf2f4 Binary files /dev/null and b/player_plugins/amarok/butt_amarok.amarokscript.tar.bz2 differ diff --git a/player_plugins/amarok/butt_amarok.rb b/player_plugins/amarok/butt_amarok.rb new file mode 100755 index 0000000..a9930ab --- /dev/null +++ b/player_plugins/amarok/butt_amarok.rb @@ -0,0 +1,66 @@ +#!/usr/bin/env ruby +# +# Now playing script for IRC. + +# Use with the "/exec -o" command of your client. You can bind an alias like this: +# /alias np exec -o /home/myself/amaroknowplaying.rb +# +# (c) 2005-2006 Mark Kretschmann +# License: GNU General Public License V2 +# +# modified by Daniel Nöthen for use in combination with butt + + +loop do + message = gets().chomp() #Read message from stdin + command = /[A-Za-z]*/.match( message ).to_s() + + case command + when "configure" + msg = '"This script does not have configuration options."' + `dcop amarok playlist popupMessage "#{msg}"` + + when "trackChange" + + title = `dcop amarok player title 2> /dev/null`.chomp + exit( 1 ) unless $?.success? # Abort if Amarok isn't running + artist = `dcop amarok player artist`.chomp + album = `dcop amarok player album`.chomp + year = `dcop amarok player year`.chomp + lastfm = `dcop amarok player lastfmStation`.chomp + + output = "" + + if title.empty? + output += `dcop amarok player nowPlaying`.chomp + else + # Strip file extension + extensions = ".ogg", ".mp3", ".wav", ".flac", ".fla", ".wma", ".mpc" + ext = File.extname( title ).downcase + + if extensions.include?( ext ) + title = title[0, title.length - ext.length] + end + + if artist.empty? + output += "#{title}" + else + output += "#{artist} - #{title}" + end + + unless album.empty? + output += " [#{album}" + output += ", #{year}" unless year == "0" + output += "]" + end + + unless lastfm.empty? + output += " (Last.fm #{lastfm})" + end + end + f = File.open(File.expand_path("~/.amarok_song"), File::WRONLY|File::TRUNC|File::CREAT) + f.puts "#{output}" + f.close + + end +end diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..ca92e19 --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1 @@ +ar de es fr pt_BR nl diff --git a/po/Makefile.in.in b/po/Makefile.in.in new file mode 100644 index 0000000..65184f6 --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,475 @@ +# Makefile for PO directory in any package using GNU gettext. +# Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU General Public +# License but which still want to provide support for the GNU gettext +# functionality. +# Please note that the actual code of GNU gettext is covered by the GNU +# General Public License and is *not* in the public domain. +# +# Origin: gettext-0.19 +GETTEXT_MACRO_VERSION = 0.19 + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ + +SED = @SED@ +SHELL = /bin/sh +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datarootdir = @datarootdir@ +datadir = @datadir@ +localedir = @localedir@ +gettextsrcdir = $(datadir)/gettext/po + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +# We use $(mkdir_p). +# In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as +# "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions, +# @install_sh@ does not start with $(SHELL), so we add it. +# In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined +# either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake +# versions, $(mkinstalldirs) and $(install_sh) are unused. +mkinstalldirs = $(SHELL) @install_sh@ -d +install_sh = $(SHELL) @install_sh@ +MKDIR_P = @MKDIR_P@ +mkdir_p = @mkdir_p@ + +GMSGFMT_ = @GMSGFMT@ +GMSGFMT_no = @GMSGFMT@ +GMSGFMT_yes = @GMSGFMT_015@ +GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT)) +MSGFMT_ = @MSGFMT@ +MSGFMT_no = @MSGFMT@ +MSGFMT_yes = @MSGFMT_015@ +MSGFMT = $(MSGFMT_$(USE_MSGCTXT)) +XGETTEXT_ = @XGETTEXT@ +XGETTEXT_no = @XGETTEXT@ +XGETTEXT_yes = @XGETTEXT_015@ +XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT)) +MSGMERGE = msgmerge +MSGMERGE_UPDATE = @MSGMERGE@ --update +MSGINIT = msginit +MSGCONV = msgconv +MSGFILTER = msgfilter + +POFILES = @POFILES@ +GMOFILES = @GMOFILES@ +UPDATEPOFILES = @UPDATEPOFILES@ +DUMMYPOFILES = @DUMMYPOFILES@ +DISTFILES.common = Makefile.in.in remove-potcdate.sin \ +$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) +DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \ +$(POFILES) $(GMOFILES) \ +$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) + +POTFILES = \ + +CATALOGS = @CATALOGS@ + +POFILESDEPS_ = $(srcdir)/$(DOMAIN).pot +POFILESDEPS_yes = $(POFILESDEPS_) +POFILESDEPS_no = +POFILESDEPS = $(POFILESDEPS_$(PO_DEPENDS_ON_POT)) + +DISTFILESDEPS_ = update-po +DISTFILESDEPS_yes = $(DISTFILESDEPS_) +DISTFILESDEPS_no = +DISTFILESDEPS = $(DISTFILESDEPS_$(DIST_DEPENDS_ON_UPDATE_PO)) + +# Makevars gets inserted here. (Don't remove this line!) + +.SUFFIXES: +.SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update + +.po.mo: + @echo "$(MSGFMT) -c -o $@ $<"; \ + $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ + +.po.gmo: + @lang=`echo $* | sed -e 's,.*/,,'`; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.po"; \ + cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo + +.sin.sed: + sed -e '/^#/d' $< > t-$@ + mv t-$@ $@ + + +all: all-@USE_NLS@ + +all-yes: stamp-po +all-no: + +# Ensure that the gettext macros and this Makefile.in.in are in sync. +CHECK_MACRO_VERSION = \ + test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \ + || { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \ + exit 1; \ + } + +# $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no +# internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because +# we don't want to bother translators with empty POT files). We assume that +# LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. +# In this case, stamp-po is a nop (i.e. a phony target). + +# stamp-po is a timestamp denoting the last time at which the CATALOGS have +# been loosely updated. Its purpose is that when a developer or translator +# checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, +# "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent +# invocations of "make" will do nothing. This timestamp would not be necessary +# if updating the $(CATALOGS) would always touch them; however, the rule for +# $(POFILES) has been designed to not touch files that don't need to be +# changed. +stamp-po: $(srcdir)/$(DOMAIN).pot + @$(CHECK_MACRO_VERSION) + test ! -f $(srcdir)/$(DOMAIN).pot || \ + test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) + @test ! -f $(srcdir)/$(DOMAIN).pot || { \ + echo "touch stamp-po" && \ + echo timestamp > stamp-poT && \ + mv stamp-poT stamp-po; \ + } + +# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', +# otherwise packages like GCC can not be built if only parts of the source +# have been downloaded. + +# This target rebuilds $(DOMAIN).pot; it is an expensive operation. +# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed. +# The determination of whether the package xyz is a GNU one is based on the +# heuristic whether some file in the top level directory mentions "GNU xyz". +# If GNU 'find' is available, we avoid grepping through monster files. +$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed + package_gnu="$(PACKAGE_GNU)"; \ + test -n "$$package_gnu" || { \ + if { if (LC_ALL=C find --version) 2>/dev/null | grep GNU >/dev/null; then \ + LC_ALL=C find -L $(top_srcdir) -maxdepth 1 -type f \ + -size -10000000c -exec grep 'GNU @PACKAGE@' \ + /dev/null '{}' ';' 2>/dev/null; \ + else \ + LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null; \ + fi; \ + } | grep -v 'libtool:' >/dev/null; then \ + package_gnu=yes; \ + else \ + package_gnu=no; \ + fi; \ + }; \ + if test "$$package_gnu" = "yes"; then \ + package_prefix='GNU '; \ + else \ + package_prefix=''; \ + fi; \ + if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ + msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ + else \ + msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \ + fi; \ + case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + *) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --package-name="$${package_prefix}@PACKAGE@" \ + --package-version='@VERSION@' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + esac + test ! -f $(DOMAIN).po || { \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ + sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ + if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \ + else \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + else \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + } + +# This rule has no dependencies: we don't need to update $(DOMAIN).pot at +# every "make" invocation, only create it when it is missing. +# Only "make $(DOMAIN).pot-update" or "make dist" will force an update. +$(srcdir)/$(DOMAIN).pot: + $(MAKE) $(DOMAIN).pot-update + +# This target rebuilds a PO file if $(DOMAIN).pot has changed. +# Note that a PO file is not touched if it doesn't need to be changed. +$(POFILES): $(POFILESDEPS) + @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ + if test -f "$(srcdir)/$${lang}.po"; then \ + test -f $(srcdir)/$(DOMAIN).pot || $(MAKE) $(srcdir)/$(DOMAIN).pot; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \ + cd $(srcdir) \ + && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ + $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \ + *) \ + $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot;; \ + esac; \ + }; \ + else \ + $(MAKE) $${lang}.po-create; \ + fi + + +install: install-exec install-data +install-exec: +install-data: install-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + for file in $(DISTFILES.common) Makevars.template; do \ + $(INSTALL_DATA) $(srcdir)/$$file \ + $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + for file in Makevars; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +install-data-no: all +install-data-yes: all + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ + $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ + echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ + fi; \ + done; \ + done + +install-strip: install + +installdirs: installdirs-exec installdirs-data +installdirs-exec: +installdirs-data: installdirs-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + else \ + : ; \ + fi +installdirs-data-no: +installdirs-data-yes: + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + fi; \ + done; \ + done + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: uninstall-exec uninstall-data +uninstall-exec: +uninstall-data: uninstall-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + for file in $(DISTFILES.common) Makevars.template; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +uninstall-data-no: +uninstall-data-yes: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + done; \ + done + +check: all + +info dvi ps pdf html tags TAGS ctags CTAGS ID: + +mostlyclean: + rm -f remove-potcdate.sed + rm -f stamp-poT + rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po + rm -fr *.o + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES *.mo + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f stamp-po $(GMOFILES) + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: + test -z "$(DISTFILESDEPS)" || $(MAKE) $(DISTFILESDEPS) + @$(MAKE) dist2 +# This is a separate target because 'update-po' must be executed before. +dist2: stamp-po $(DISTFILES) + dists="$(DISTFILES)"; \ + if test "$(PACKAGE)" = "gettext-tools"; then \ + dists="$$dists Makevars.template"; \ + fi; \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + dists="$$dists $(DOMAIN).pot stamp-po"; \ + fi; \ + if test -f $(srcdir)/ChangeLog; then \ + dists="$$dists ChangeLog"; \ + fi; \ + for i in 0 1 2 3 4 5 6 7 8 9; do \ + if test -f $(srcdir)/ChangeLog.$$i; then \ + dists="$$dists ChangeLog.$$i"; \ + fi; \ + done; \ + if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ + for file in $$dists; do \ + if test -f $$file; then \ + cp -p $$file $(distdir) || exit 1; \ + else \ + cp -p $(srcdir)/$$file $(distdir) || exit 1; \ + fi; \ + done + +update-po: Makefile + $(MAKE) $(DOMAIN).pot-update + test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) + $(MAKE) update-gmo + +# General rule for creating PO files. + +.nop.po-create: + @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ + echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ + exit 1 + +# General rule for updating PO files. + +.nop.po-update: + @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ + if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ + cd $(srcdir); \ + if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ + $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + *) \ + $(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + esac; \ + }; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "msgmerge for $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +$(DUMMYPOFILES): + +update-gmo: Makefile $(GMOFILES) + @: + +# Recreate Makefile by invoking config.status. Explicitly invoke the shell, +# because execution permission bits may not work on the current file system. +# Use @SHELL@, which is the shell determined by autoconf for the use by its +# scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient. +Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@ + cd $(top_builddir) \ + && @SHELL@ ./config.status $(subdir)/$@.in po-directories + +force: + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/Makevars b/po/Makevars new file mode 100644 index 0000000..555ef1f --- /dev/null +++ b/po/Makevars @@ -0,0 +1,78 @@ +# Makefile variables for PO directory in any package using GNU gettext. + +# Usually the message domain is the same as the package name. +DOMAIN = $(PACKAGE) + +# These two variables depend on the location of this directory. +subdir = po +top_builddir = .. + +# These options get passed to xgettext. +XGETTEXT_OPTIONS = --keyword=_ --from-code=UTF-8 + +# This is the copyright holder that gets inserted into the header of the +# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding +# package. (Note that the msgstr strings, extracted from the package's +# sources, belong to the copyright holder of the package.) Translators are +# expected to transfer the copyright for their translations to this person +# or entity, or to disclaim their copyright. The empty string stands for +# the public domain; in this case the translators are expected to disclaim +# their copyright. +COPYRIGHT_HOLDER = Daniel Nöthen + +# This tells whether or not to prepend "GNU " prefix to the package +# name that gets inserted into the header of the $(DOMAIN).pot file. +# Possible values are "yes", "no", or empty. If it is empty, try to +# detect it automatically by scanning the files in $(top_srcdir) for +# "GNU packagename" string. +PACKAGE_GNU = no + +# This is the email address or URL to which the translators shall report +# bugs in the untranslated strings: +# - Strings which are not entire sentences, see the maintainer guidelines +# in the GNU gettext documentation, section 'Preparing Strings'. +# - Strings which use unclear terms or require additional context to be +# understood. +# - Strings which make invalid assumptions about notation of date, time or +# money. +# - Pluralisation problems. +# - Incorrect English spelling. +# - Incorrect formatting. +# It can be your email address, or a mailing list address where translators +# can write to without being subscribed, or the URL of a web page through +# which the translators can contact you. +MSGID_BUGS_ADDRESS = butt@danielnoethen.de + +# This is the list of locale categories, beyond LC_MESSAGES, for which the +# message catalogs shall be used. It is usually empty. +EXTRA_LOCALE_CATEGORIES = + +# This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt' +# context. Possible values are "yes" and "no". Set this to yes if the +# package uses functions taking also a message context, like pgettext(), or +# if in $(XGETTEXT_OPTIONS) you define keywords with a context argument. +USE_MSGCTXT = no + +# These options get passed to msgmerge. +# Useful options are in particular: +# --previous to keep previous msgids of translated messages, +# --quiet to reduce the verbosity. +MSGMERGE_OPTIONS = + +# These options get passed to msginit. +# If you want to disable line wrapping when writing PO files, add +# --no-wrap to MSGMERGE_OPTIONS, XGETTEXT_OPTIONS, and +# MSGINIT_OPTIONS. +MSGINIT_OPTIONS = + +# This tells whether or not to regenerate a PO file when $(DOMAIN).pot +# has changed. Possible values are "yes" and "no". Set this to no if +# the POT file is checked in the repository and the version control +# program ignores timestamps. +PO_DEPENDS_ON_POT = yes + +# This tells whether or not to forcibly update $(DOMAIN).pot and +# regenerate PO files on "make dist". Possible values are "yes" and +# "no". Set this to no if the POT file and PO files are maintained +# externally. +DIST_DEPENDS_ON_UPDATE_PO = yes diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..3ab7234 --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,15 @@ +# List of source files which contain translatable strings. +src/AskForMicPermission.m +src/butt.cpp +src/cfg.cpp +src/FLTK/flgui.cpp +src/FLTK/fl_timer_funcs.cpp +src/FLTK/fl_callbacks.cpp +src/FLTK/flgui.cpp +src/FLTK/fl_funcs.cpp +src/icecast.cpp +src/lame_encode.cpp +src/port_audio.cpp +src/port_midi.cpp +src/shoutcast.cpp +src/tls.cpp diff --git a/po/Rules-quot b/po/Rules-quot new file mode 100644 index 0000000..7b92c7e --- /dev/null +++ b/po/Rules-quot @@ -0,0 +1,58 @@ +# This file, Rules-quot, can be copied and used freely without restrictions. +# Special Makefile rules for English message catalogs with quotation marks. + +DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot + +.SUFFIXES: .insert-header .po-update-en + +en@quot.po-create: + $(MAKE) en@quot.po-update +en@boldquot.po-create: + $(MAKE) en@boldquot.po-update + +en@quot.po-update: en@quot.po-update-en +en@boldquot.po-update: en@boldquot.po-update-en + +.insert-header.po-update-en: + @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \ + if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + ll=`echo $$lang | sed -e 's/@.*//'`; \ + LC_ALL=C; export LC_ALL; \ + cd $(srcdir); \ + if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$lang -o - 2>/dev/null \ + | $(SED) -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | \ + { case `$(MSGFILTER) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-8] | 0.1[0-8].*) \ + $(MSGFILTER) $(SED) -f `echo $$lang | sed -e 's/.*@//'`.sed \ + ;; \ + *) \ + $(MSGFILTER) `echo $$lang | sed -e 's/.*@//'` \ + ;; \ + esac } 2>/dev/null > $$tmpdir/$$lang.new.po \ + ; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "creation of $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +en@quot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header + +en@boldquot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header + +mostlyclean: mostlyclean-quot +mostlyclean-quot: + rm -f *.insert-header diff --git a/po/ar.gmo b/po/ar.gmo new file mode 100644 index 0000000..71b3d6b Binary files /dev/null and b/po/ar.gmo differ diff --git a/po/ar.po b/po/ar.po new file mode 100644 index 0000000..0003723 --- /dev/null +++ b/po/ar.po @@ -0,0 +1,3173 @@ +# Arabic translations for butt-0.1.41 package. +# Copyright (C) Daniel Nöthen +# This file is distributed under the same license as the butt package. +# Magd Almuntaser , 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: butt 1.45.0\n" +"Report-Msgid-Bugs-To: butt@danielnoethen.de\n" +"POT-Creation-Date: 2025-04-19 14:55+0200\n" +"PO-Revision-Date: 2025-04-19 15:27+0200\n" +"Last-Translator: Magd Almuntaser \n" +"Language-Team: Yemen\n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.0.1\n" + +#: src/AskForMicPermission.m:20 +msgid "Microphone access" +msgstr "الوصول إلى الميكروÙون" + +#: src/AskForMicPermission.m:21 +msgid "" +"butt needs access to your microphone.\n" +"\n" +"Please go to\n" +"System Preferences->Privacy & Security->Microphone\n" +"and activate the check mark next to the butt entry." +msgstr "" +"butt يحتاج إلى الوصول إلى الميكروÙون الخاص بك\n" +"الرجاء الذهاب إلى\n" +"ØªÙØ¶ÙŠÙ„ات النظام->الأمان والخصوصية->الخصوصية->الميكروÙون\n" +"وقم بتنشيط علامة الاختيار بجانب إدخال butt." + +#: src/butt.cpp:219 +msgid "No home-directory found" +msgstr "لم يتم العثور على الدليل الرئيسي" + +#: src/butt.cpp:230 +#, c-format +msgid "" +"The shift key was held down during startup.\n" +"Do you want to start butt with a new configuration file?\n" +"This will overwrite your existing configuration file at\n" +"%s" +msgstr "" +"تم الضغط باستمرار على Ù…ÙØªØ§Ø­ Shift أثناء بدء التشغيل.\n" +"هل تريد أن تبدأ بمل٠تكوين جديد؟\n" +"سيؤدي هذا إلى استبدال مل٠التكوين الموجود لديك على\n" +"%s" + +#: src/butt.cpp:233 +msgid "Start with old" +msgstr "البدء بالقديم" + +#: src/butt.cpp:233 +msgid "Start with new" +msgstr "البدء بالجديد" + +#: src/butt.cpp:236 src/butt.cpp:253 +#, c-format +msgid "" +"Could not create config %s\n" +"butt is going to close now" +msgstr "" +"لا يمكن إنشاء التكوين %s\n" +"butt سو٠يغلق الآن" + +#: src/butt.cpp:242 +#, c-format +msgid "Reading config %s\n" +msgstr "قراءة التكوين %s\n" + +#: src/butt.cpp:250 +#, c-format +msgid "Could not find config %s\n" +msgstr "تعذر العثور على التكوين %s\n" + +#: src/butt.cpp:257 +#, c-format +msgid "" +"butt created a default config at\n" +"%s\n" +msgstr "" +"butt قام بإنشاء تكوين Ø§ÙØªØ±Ø§Ø¶ÙŠ ÙÙŠ\n" +"%s\n" + +#: src/butt.cpp:265 +msgid "" +"Could not find any audio device with input channels.\n" +"butt requires at least one audio device with input channels in order to " +"work.\n" +"This can either be a built-in audio device, an external audio device or a " +"virtual audio device.\n" +"\n" +"butt is going to close now." +msgstr "" +"تعذر العثور على أي جهاز صوتي بقنوات إدخال.\n" +"يتطلب \"butt\" وجود ما لا يقل عن جهاز صوتي واحد يحتوي على قنوات إدخال " +"للعمل.\n" +"يمكن أن يكون ذلك إما جهاز صوت مدمج أو جهاز صوت خارجي أو جهاز صوت Ø§ÙØªØ±Ø§Ø¶ÙŠ.\n" +"\n" +"سيتم إغلاق \"butt\" الآن." + +#: src/butt.cpp:358 +#, c-format +msgid "Illegal argument: Threshold must be a non-negative number\n" +msgstr "وسيط غير قانوني: يجب أن يكون الحد رقمًا غير سالب\n" + +#: src/butt.cpp:382 +#, c-format +msgid "%c threshold set to %0.1f\n" +msgstr "تم ضبط حد %c الى %0.1f\n" + +#: src/butt.cpp:464 +#, c-format +msgid "Illegal argument: Port must be a number between 1023 and 65535\n" +msgstr "" +"وسيط غير قانوني: يجب أن يكون رقم Ø§Ù„Ù…Ù†ÙØ° (Port) رقمًا بين 1023 Ùˆ 65535.\n" + +#: src/butt.cpp:472 src/butt.cpp:482 src/butt.cpp:489 src/butt.cpp:496 +#: src/butt.cpp:503 src/butt.cpp:510 src/butt.cpp:521 src/butt.cpp:540 +#: src/butt.cpp:550 src/butt.cpp:597 +#, c-format +msgid "" +"Warning: You may only pass one control option. Option -%c has been ignored.\n" +msgstr "تحذير: يمكنك تمرير خيار تحكم واحد Ùقط. تم تجاهل الخيار -%c.\n" + +#: src/butt.cpp:559 +#, c-format +msgid "" +"\n" +"Options:\n" +"-h\tPrint this help text\n" +"-v\tPrint version information\n" +msgstr "" +"\n" +"الخيارات:\n" +"-h\tطباعة نص المساعدة هذا\n" +"-v\tطباعة معلومات الإصدار\n" + +#: src/butt.cpp:563 +#, c-format +msgid "" +"\n" +"Options for operating mode:\n" +"-c\tPath to configuration file\n" +"-L\tPrint available audio devices\n" +"-A\tCommand server will be accessible from your network/internet (default: " +"localhost only)\n" +"-U\tCommand server will use UDP instead of TCP\n" +"-x\tDo not start a command server\n" +"-p\tPort where the command server shall listen to (default: 1256)\n" +msgstr "" +"\n" +"خيارات وضع التشغيل:\n" +"-c\tالمسار إلى مل٠التكوين\n" +"-L\tطباعة أجهزة الصوت المتاحة\n" +"-A\tسيكون Ù…Ù†ÙØ° الأوامر متاحًا من شبكتك/الإنترنت (Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ: محلي Ùقط)\n" +"-U\tسيستخدم خادم الأوامر UDP بدلاً من TCP\n" +"-x\tلا تبدأ خادم الأوامر\n" +"-p\tØ§Ù„Ù…Ù†ÙØ° الذي سيستمع عليه خادم الأوامر (Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ: 1256)\n" + +#: src/butt.cpp:572 +#, c-format +msgid "" +"\n" +"Options for control mode:\n" +"-s\tConnect to streaming server\n" +"-d\tDisconnect from streaming server\n" +"-r\tStart recording\n" +"-t\tStop recording\n" +"-n\tSplit recording\n" +"-q\tQuit butt\n" +"-u\tupdate song name\n" +"-S\tRequest status\n" +"-M\tSet streaming signal threshold (seconds)\n" +"-m\tSet streaming silence threshold (seconds)\n" +"-O\tSet recording signal threshold (seconds)\n" +"-o\tSet recording silence threshold (seconds)\n" +"-U\tConnect via UDP instead of TCP\n" +"-a\tAddress of the butt instance to be controlled (default: 127.0.0.1)\n" +"-p\tPort of the butt instance to be controlled (default: 1256)\n" +msgstr "" +"\n" +"خيارات وضع التحكم:\n" +"-s\tالاتصال بخادم البث\n" +"-d\tÙØµÙ„ الاتصال من خادم البث\n" +"-r\tبدء التسجيل\n" +"-t\tإيقا٠التسجيل\n" +"-n\tتقسيم التسجيل\n" +"-q\tإنهاء برنامج butt\n" +"-u\tتحديث اسم الأغنية\n" +"-S\tطلب الحالة\n" +"-M\tتعيين عتبة إشارة البث (ثوان)\n" +"-m\tتعيين عتبة صمت البث (ثوان)\n" +"-O\tتعيين عتبة إشارة التسجيل (ثوان)\n" +"-o\tتعيين عتبة صمت التسجيل (ثوان)\n" +"-U\tالاتصال عبر UDP بدلاً من TCP\n" +"-a\tعنوان نسخة butt التي سيتم التحكم بها (Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ: 127.0.0.1)\n" +"-p\tÙ…Ù†ÙØ° نسخة butt التي سيتم التحكم بها (Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ: 1256)\n" + +#: src/butt.cpp:591 +#, c-format +msgid "" +"Illegal option -%c.\n" +"Type butt -h to get a list of supported options.\n" +msgstr "" +"خيار غير قانوني -%c.\n" +"اكتب \"butt -h\" للحصول على قائمة بالخيارات المدعومة.\n" + +#: src/butt.cpp:603 +#, c-format +msgid "Option -%c requires an argument\n" +msgstr "الخيار -%c يتطلب وسيطًا.\n" + +#: src/butt.cpp:607 +#, c-format +msgid "Command line parsing failed\n" +msgstr "ÙØ´Ù„ تحليل سطر الأوامر.\n" + +#: src/butt.cpp:630 +#, c-format +msgid "No butt instance running on %s at port %d\n" +msgstr "لا توجد نسخة من \"butt\" قيد التشغيل على %s ÙÙŠ Ø§Ù„Ù…Ù†ÙØ° %d.\n" + +#: src/butt.cpp:635 +#, c-format +msgid "Error while sending command\n" +msgstr "خطأ أثناء إرسال الأمر.\n" + +#: src/butt.cpp:640 +#, c-format +msgid "Error: Did not receive response packet\n" +msgstr "خطأ: لم يتم استلام حزمة الاستجابة.\n" + +#: src/butt.cpp:653 +#, c-format +msgid "Error: You may only request one status packet per second\n" +msgstr "خطأ: ÙŠÙØ³Ù…Ø­ Ùقط بطلب حزمة حالة واحدة ÙÙŠ الثانية.\n" + +#: src/butt.cpp:657 +#, c-format +msgid "Error: Did not receive status packet (UDP server not running?)\n" +msgstr "خطأ: لم يتم استلام حزمة الحالة (هل خادم UDP غير قيد التشغيل؟)\n" + +#: src/butt.cpp:661 +#, c-format +msgid "Network error while receiving status packet: %d\n" +msgstr "خطأ ÙÙŠ الشبكة أثناء استلام حزمة الحالة: %d\n" + +#: src/butt.cpp:665 +#, c-format +msgid "Error: Client and server versions do not match\n" +msgstr "خطأ: إصدارات العميل والخادم غير متطابقة.\n" + +#: src/butt.cpp:676 +#, c-format +msgid "" +"connected: %d\n" +"connecting: %d\n" +"recording: %d\n" +"signal present: %d\n" +"signal absent: %d\n" +msgstr "" +"متصل: %d\n" +"جاري الاتصال: %d\n" +"جاري التسجيل: %d\n" +"الإشارة موجودة: %d\n" +"الإشارة غير موجودة: %d\n" + +#: src/butt.cpp:681 +#, c-format +msgid "stream seconds: %lu\n" +msgstr "ثواني البث: %lu\n" + +#: src/butt.cpp:682 +#, c-format +msgid "stream kBytes: %lu\n" +msgstr "كيلوبايت البث: %lu\n" + +#: src/butt.cpp:683 +#, c-format +msgid "record seconds: %lu\n" +msgstr "ثواني التسجيل: %lu\n" + +#: src/butt.cpp:684 +#, c-format +msgid "record kBytes: %lu\n" +msgstr "كيلوبايت التسجيل: %lu\n" + +#: src/butt.cpp:685 +#, c-format +msgid "volume left: %0.1f\n" +msgstr "مستوى الصوت الأيسر: %0.1f\n" + +#: src/butt.cpp:686 +#, c-format +msgid "volume right: %0.1f\n" +msgstr "مستوى الصوت الأيمن: %0.1f\n" + +#: src/butt.cpp:687 +#, c-format +msgid "song: %s\n" +msgstr "الأغنية: %s\n" + +#: src/butt.cpp:688 +#, c-format +msgid "record path: %s\n" +msgstr "مسار التسجيل: %s\n" + +#: src/butt.cpp:689 +#, c-format +msgid "listeners: %d\n" +msgstr "المستمعين: %d\n" + +#: src/butt.cpp:703 +msgid "" +"The control key was held down during startup.\n" +"butt will start without opening an audio device.\n" +"Please select your preferred audio device in settings->audio" +msgstr "" +"تم الضغط على Ù…ÙØªØ§Ø­ التحكم أثناء بدء التشغيل.\n" +"سيبدأ \"butt\" دون ÙØªØ­ جهاز صوت.\n" +"يرجى تحديد جهاز الصوت Ø§Ù„Ù…ÙØ¶Ù„ ÙÙŠ الإعدادات->الصوت" + +#: src/butt.cpp:712 +msgid "" +"PortAudio init failed\n" +"butt is going to close now" +msgstr "" +"ÙØ´Ù„ تهيئة PortAudio.\n" +"سيتم إغلاق \"butt\" الآن" + +#: src/butt.cpp:747 src/FLTK/fl_timer_funcs.cpp:476 +#: src/FLTK/fl_callbacks.cpp:123 src/FLTK/fl_callbacks.cpp:899 +#: src/FLTK/fl_callbacks.cpp:977 src/FLTK/fl_funcs.cpp:1047 +msgid "idle" +msgstr "idle" + +#: src/butt.cpp:780 +#, c-format +msgid "" +"Starting %s\n" +"Written by Daniel Nöthen\n" +"iPhone/iPad client: https://izicast.de\n" +"Donate: paypal@danielnoethen.de\n" +msgstr "" +"البداية: %s\n" +"مكتوب بواسطة Daniel Nöthen\n" +"العميل لـ iPhone/iPad: https://izicast.de\n" +"التبرع: paypal@danielnoethen.de\n" + +#: src/butt.cpp:792 src/butt.cpp:793 src/cfg.cpp:577 src/port_audio.cpp:1314 +#: src/port_audio.cpp:1315 +msgid "Default PCM device (default)" +msgstr "الجهاز Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ Ù„ØªØ±Ù…ÙŠØ² PCM (Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ)" + +#: src/butt.cpp:796 src/butt.cpp:797 src/cfg.cpp:578 +#: src/FLTK/fl_callbacks.cpp:2820 src/FLTK/fl_funcs.cpp:227 +msgid "None" +msgstr "لا شيء" + +#: src/butt.cpp:800 +msgid "" +"Could not open audio device.\n" +"Please select your preferred audio device in settings->audio" +msgstr "" +"تعذر ÙØªØ­ جهاز الصوت.\n" +"يرجى اختيار جهاز الصوت Ø§Ù„Ù…ÙØ¶Ù„ ÙÙŠ الإعدادات->الصوت" + +#: src/butt.cpp:803 +msgid "" +"butt could not open previously used audio device.\n" +"The system default audio device will be used.\n" +msgstr "" +"لم يتمكن butt من ÙØªØ­ جهاز الصوت المستخدم سابقًا.\n" +"سيتم استخدام جهاز الصوت Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ Ù„Ù„Ù†Ø¸Ø§Ù….\n" + +#: src/butt.cpp:830 +#, c-format +msgid "Command server listening on port %d\n" +msgstr "خادم الأوامر يستمع على Ø§Ù„Ù…Ù†ÙØ° %d.\n" + +#: src/butt.cpp:837 +#, c-format +msgid "Warning: could not start command server on port %d\n" +msgstr "تحذير: تعذر بدء خادم الأوامر على Ø§Ù„Ù…Ù†ÙØ° %d.\n" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:4225 +#, c-format +msgid "" +"New version available: %s\n" +"You have version %s" +msgstr "" +"إصدار جديد متاح: %s\n" +"لديك الإصدار %s" + +#: src/butt.cpp:853 +msgid "Don't ask again" +msgstr "لا تسأل مرة أخرى" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:1594 +#: src/FLTK/fl_callbacks.cpp:4225 +msgid "Cancel" +msgstr "إلغاء" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:4225 +msgid "Get new version" +msgstr "الحصول على الإصدار الجديد" + +#: src/butt.cpp:874 +#, c-format +msgid "Could not initialize PortMidi: %s" +msgstr "تعذر تهيئة PortMidi: %s" + +#: src/butt.cpp:902 +msgid "butt was built without WebRTC support" +msgstr "تم إنشاء butt بدون دعم WebRTC" + +#: src/cfg.cpp:55 +#, c-format +msgid "Could not write to file: %s" +msgstr "تعذر الكتابة ÙÙŠ الملÙ: %s" + +#: src/cfg.cpp:550 +#, c-format +msgid "Config written to %s" +msgstr "تمت كتابة التكوين إلى %s" + +#: src/cfg.cpp:674 +msgid "" +"error while parsing config. Missing main/server entry.\n" +"butt will start with default settings" +msgstr "" +"خطأ أثناء تحليل التكوين. الإدخال الرئيسي/الخادم Ù…Ùقود.\n" +"سيبدأ butt بالإعدادات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©" + +#: src/cfg.cpp:680 +msgid "" +"error while parsing config. Missing main/srv_ent entry.\n" +"butt will start with default settings" +msgstr "" +"خطأ أثناء تحليل التكوين. الإدخال srv_ent الرئيسي Ù…Ùقود.\n" +"سيبدأ butt بالإعدادات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©" + +#: src/cfg.cpp:699 +#, c-format +msgid "" +"error while parsing config. Missing type entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"خطأ أثناء تحليل التكوين. إدخال النوع Ù…Ùقود للخادم \"%s\".\n" +"سيبدأ butt بالإعدادات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©" + +#: src/cfg.cpp:707 +#, c-format +msgid "" +"error while parsing config. Missing address entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"خطأ أثناء تحليل التكوين. إدخال العنوان Ù…Ùقود للخادم \"%s\".\n" +"سيبدأ butt بالإعدادات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©" + +#: src/cfg.cpp:716 +#, c-format +msgid "" +"error while parsing config. Missing port entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"خطأ أثناء تحليل التكوين. إدخال Ø§Ù„Ù…Ù†ÙØ° Ù…Ùقود للخادم \"%s\".\n" +"سيبدأ butt بالإعدادات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©" + +#: src/cfg.cpp:725 +#, c-format +msgid "" +"error while parsing config. Missing password entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"خطأ أثناء تحليل التكوين. إدخال كلمة المرور Ù…Ùقود للخادم \"%s\".\n" +"سيبدأ butt بالإعدادات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©" + +#: src/cfg.cpp:734 +#, c-format +msgid "" +"error while parsing config. Missing mount entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"خطأ أثناء تحليل التكوين. إدخال المسار (mount) Ù…Ùقود للخادم \"%s\".\n" +"سيبدأ butt بالإعدادات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©" + +#: src/cfg.cpp:790 +msgid "" +"error while parsing config. Missing main/icy entry.\n" +"butt will start with default settings" +msgstr "" +"خطأ أثناء تحليل التكوين. إدخال icy الرئيسي Ù…Ùقود.\n" +"سيبدأ butt بالإعدادات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©" + +#: src/cfg.cpp:795 +msgid "" +"error while parsing config. Missing main/icy_ent entry.\n" +"butt will start with default settings" +msgstr "" +"خطأ أثناء تحليل التكوين. الإدخال الرئيسي/الخادم icy_ent Ù…Ùقود.\n" +"سيبدأ butt بالإعدادات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©" + +#: src/cfg.cpp:821 +#, c-format +msgid "" +"error while parsing config. Missing pub entry for icy \"%s\".\n" +"butt will start with default settings" +msgstr "" +"خطأ أثناء تحليل التكوين. إدخال النشر (pub) Ù…Ùقود لـ icy \"%s\".\n" +"سيبدأ butt بالإعدادات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©" + +#: src/FLTK/flgui.cpp:3088 +msgid "Bitcoin address has been copied to clipboard." +msgstr "تم نسخ عنوان البيتكوين إلى Ø§Ù„Ø­Ø§ÙØ¸Ø©." + +#: src/FLTK/flgui.cpp:3099 +msgid "Litecoin address has been copied to clipboard." +msgstr "تم نسخ عنوان الليتكوين إلى Ø§Ù„Ø­Ø§ÙØ¸Ø©." + +#: src/FLTK/flgui.cpp:3110 +msgid "Monero address has been copied to clipboard." +msgstr "تم نسخ عنوان المونيرو إلى Ø§Ù„Ø­Ø§ÙØ¸Ø©." + +#: src/FLTK/flgui.cpp:4041 +msgid "press left mouse to toggle lcd info" +msgstr "اضغط بزر الماوس الأيسر لتبديل معلومات lcd" + +#: src/FLTK/flgui.cpp:4053 src/FLTK/fl_callbacks.cpp:4078 +msgid "Streaming volume" +msgstr "مستوى البث" + +#: src/FLTK/flgui.cpp:4057 +msgid "Mixer" +msgstr "المكسر" + +#: src/FLTK/flgui.cpp:4058 +msgid "show/hide mixer window" +msgstr "عرض/Ø¥Ø®ÙØ§Ø¡ Ù†Ø§ÙØ°Ø© المكسر" + +#: src/FLTK/flgui.cpp:4065 +msgid "@circle" +msgstr "@circle" + +#: src/FLTK/flgui.cpp:4066 +msgid "start/stop recording" +msgstr "بدء/إيقا٠التسجيل" + +#: src/FLTK/flgui.cpp:4077 +msgid "@square" +msgstr "@square" + +#: src/FLTK/flgui.cpp:4078 +msgid "disconnect from server" +msgstr "Ø§Ù„ÙØµÙ„ من الخادم" + +#: src/FLTK/flgui.cpp:4089 +msgid "@>" +msgstr "@>" + +#: src/FLTK/flgui.cpp:4090 +msgid "connect to server" +msgstr "الاتصال بالخادم" + +#: src/FLTK/flgui.cpp:4106 src/FLTK/flgui.cpp:4438 src/FLTK/flgui.cpp:4657 +#: src/FLTK/fl_callbacks.cpp:4077 +msgid "Streaming" +msgstr "البث" + +#: src/FLTK/flgui.cpp:4110 src/FLTK/flgui.cpp:4469 src/FLTK/flgui.cpp:4771 +msgid "Recording" +msgstr "التسجيل" + +#: src/FLTK/flgui.cpp:4140 +msgid "Settings" +msgstr "الإعدادات" + +#: src/FLTK/flgui.cpp:4141 +msgid "show/hide config window" +msgstr "عرض/Ø¥Ø®ÙØ§Ø¡ Ù†Ø§ÙØ°Ø© التكوين" + +#: src/FLTK/flgui.cpp:4148 src/FLTK/fl_callbacks.cpp:1098 +msgid "Show log" +msgstr "عرض السجل" + +#: src/FLTK/flgui.cpp:4149 +msgid "show/hide info window" +msgstr "عرض/Ø¥Ø®ÙØ§Ø¡ Ù†Ø§ÙØ°Ø© المعلومات" + +#: src/FLTK/flgui.cpp:4156 +msgid "-24 dB" +msgstr "-24 dB" + +#: src/FLTK/flgui.cpp:4159 +msgid "Gain" +msgstr "المكسب" + +#: src/FLTK/flgui.cpp:4160 src/FLTK/fl_callbacks.cpp:3663 +#: src/FLTK/fl_funcs.cpp:810 +msgid "Master Gain" +msgstr "المكسب الرئيسي" + +#: src/FLTK/flgui.cpp:4178 +msgid "+24 dB" +msgstr "+24 dB" + +#: src/FLTK/flgui.cpp:4185 +msgid "Listeners: 0" +msgstr "المستمعين: 0" + +#: src/FLTK/flgui.cpp:4200 +msgid "butt settings" +msgstr "إعدادات butt" + +#: src/FLTK/flgui.cpp:4213 +msgid "Main" +msgstr "الرئيسي" + +#: src/FLTK/flgui.cpp:4215 +msgid "Server Settings" +msgstr "إعدادات الخادم" + +#: src/FLTK/flgui.cpp:4218 +msgid "Server" +msgstr "الخادم" + +#: src/FLTK/flgui.cpp:4219 +msgid "Server to connect to" +msgstr "الخادم الذي يجب الاتصال به" + +#: src/FLTK/flgui.cpp:4224 src/FLTK/flgui.cpp:4245 +msgid "ADD" +msgstr "Ø¥Ø¶Ø§ÙØ©" + +#: src/FLTK/flgui.cpp:4225 src/FLTK/flgui.cpp:5550 +msgid "Add server" +msgstr "Ø¥Ø¶Ø§ÙØ© خادم" + +#: src/FLTK/flgui.cpp:4229 src/FLTK/flgui.cpp:4250 +msgid "EDIT" +msgstr "تعديل" + +#: src/FLTK/flgui.cpp:4230 +msgid "Edit selected server" +msgstr "تحرير الخادم المحدد" + +#: src/FLTK/flgui.cpp:4234 src/FLTK/flgui.cpp:4255 +msgid "DEL" +msgstr "حذÙ" + +#: src/FLTK/flgui.cpp:4235 +msgid "Delete selected server" +msgstr "حذ٠الخادم المحدد" + +#: src/FLTK/flgui.cpp:4239 +msgid "Stream Infos" +msgstr "معلومات البث" + +#: src/FLTK/flgui.cpp:4240 +msgid "Stream info that shall be used" +msgstr "معلومات البث التي يجب استخدامها" + +#: src/FLTK/flgui.cpp:4246 src/FLTK/flgui.cpp:5671 +msgid "Add stream info" +msgstr "Ø¥Ø¶Ø§ÙØ© معلومات البث" + +#: src/FLTK/flgui.cpp:4251 +msgid "Edit stream info" +msgstr "تحرير معلومات البث" + +#: src/FLTK/flgui.cpp:4256 +msgid "Delete stream info" +msgstr "حذ٠معلومات البث" + +#: src/FLTK/flgui.cpp:4262 +msgid "Log File" +msgstr "مل٠السجل" + +#: src/FLTK/flgui.cpp:4266 +msgid "Log file path" +msgstr "مسار مل٠السجل" + +#: src/FLTK/flgui.cpp:4271 +msgid "Select log file" +msgstr "اختيار مل٠السجل" + +#: src/FLTK/flgui.cpp:4278 +msgid "Configuration" +msgstr "التكوين" + +#: src/FLTK/flgui.cpp:4281 src/FLTK/fl_callbacks.cpp:4128 +msgid "Import..." +msgstr "استيراد..." + +#: src/FLTK/flgui.cpp:4282 +msgid "Import settings from config file" +msgstr "استيراد الإعدادات من مل٠التكوين" + +#: src/FLTK/flgui.cpp:4286 src/FLTK/flgui.cpp:5615 src/FLTK/flgui.cpp:5717 +msgid "&Save" +msgstr "&Ø­ÙØ¸" + +#: src/FLTK/flgui.cpp:4287 +msgid "Save settings" +msgstr "Ø­ÙØ¸ الإعدادات" + +#: src/FLTK/flgui.cpp:4291 +msgid "Export..." +msgstr "تصدير..." + +#: src/FLTK/flgui.cpp:4292 +msgid "export settings" +msgstr "إعدادات التصدير" + +#: src/FLTK/flgui.cpp:4298 +msgid "Butt Agent" +msgstr "Butt وكيل" + +#: src/FLTK/flgui.cpp:4301 +msgid "Start agent at startup" +msgstr "بدء الوكيل عند التشغيل" + +#: src/FLTK/flgui.cpp:4302 +msgid "Start the butt agent when butt starts" +msgstr "ابدأ تشغيل وكيل butt عندما يبدأ butt" + +#: src/FLTK/flgui.cpp:4306 src/FLTK/flgui.cpp:4307 +msgid "Minimize butt to tray" +msgstr "تقليص البرنامج إلى علبة النظام" + +#: src/FLTK/flgui.cpp:4311 +msgid "Start Agent" +msgstr "بدء الوكيل" + +#: src/FLTK/flgui.cpp:4312 +msgid "Start the butt agent now" +msgstr "بدء وكيل butt الان" + +#: src/FLTK/flgui.cpp:4316 +msgid "Stop Agent" +msgstr "إيقا٠الوكيل" + +#: src/FLTK/flgui.cpp:4317 +msgid "Stop the butt agent" +msgstr "إيقا٠وكيل butt" + +#: src/FLTK/flgui.cpp:4323 +msgid "Updates" +msgstr "تحديث" + +#: src/FLTK/flgui.cpp:4326 +msgid "Check at startup" +msgstr "تحقق عند بدء التشغيل" + +#: src/FLTK/flgui.cpp:4327 +msgid "Check for updates at start" +msgstr "التحقق من وجود تحديثات ÙÙŠ البداية" + +#: src/FLTK/flgui.cpp:4331 +msgid "Check now" +msgstr "تحقق الان" + +#: src/FLTK/flgui.cpp:4332 +msgid "Check if a new version is available" +msgstr "تحقق مما إذا كان الإصدار الجديد متاحًا" + +#: src/FLTK/flgui.cpp:4338 +msgid "Help" +msgstr "مساعدة" + +#: src/FLTK/flgui.cpp:4341 +msgid "Manual" +msgstr "الدليل" + +#: src/FLTK/flgui.cpp:4345 +msgid " YouTube" +msgstr " اليوتيوب" + +#: src/FLTK/flgui.cpp:4355 +msgid "Audio" +msgstr "الصوت" + +#: src/FLTK/flgui.cpp:4357 +msgid "Main Audio Settings" +msgstr "إعدادات الصوت الرئيسية" + +#: src/FLTK/flgui.cpp:4360 +msgid "Channel mode" +msgstr "وضع القناة" + +#: src/FLTK/flgui.cpp:4361 +msgid "Select input channel" +msgstr "حدد قناة الادخال" + +#: src/FLTK/flgui.cpp:4374 +msgid "Samplerate" +msgstr "معدل العينة" + +#: src/FLTK/flgui.cpp:4375 +msgid "Select input sample rate" +msgstr "حدد معدل عينة الإدخال" + +#: src/FLTK/flgui.cpp:4380 +msgid "Remember Device by" +msgstr "تذكر الجهاز حسب" + +#: src/FLTK/flgui.cpp:4383 +msgid "ID" +msgstr "الرقم" + +#: src/FLTK/flgui.cpp:4388 +msgid "Name" +msgstr "الاسم" + +#: src/FLTK/flgui.cpp:4395 +msgid "Update devices" +msgstr "تحديث الأجهزة" + +#: src/FLTK/flgui.cpp:4396 +msgid "Rescan audio devices" +msgstr "إعادة ÙØ­Øµ أجهزة الصوت" + +#: src/FLTK/flgui.cpp:4400 +msgid "Primary Audio Device" +msgstr "الجهاز الصوت الأساسي" + +#: src/FLTK/flgui.cpp:4401 +msgid "Select your primary sound card device" +msgstr "حدد جهاز الصوت الاساسي" + +#: src/FLTK/flgui.cpp:4406 src/FLTK/flgui.cpp:4424 +msgid "Left" +msgstr "يسار" + +#: src/FLTK/flgui.cpp:4407 src/FLTK/flgui.cpp:4425 +msgid "Select left audio channel" +msgstr "حدد قناة الصوت اليسرى" + +#: src/FLTK/flgui.cpp:4412 src/FLTK/flgui.cpp:4430 +msgid "Right" +msgstr "يمين" + +#: src/FLTK/flgui.cpp:4413 src/FLTK/flgui.cpp:4431 +msgid "Select right audio channel" +msgstr "حدد قناة الصوت اليمنى" + +#: src/FLTK/flgui.cpp:4418 +msgid "Secondary Audio Device" +msgstr "جهاز الصوت الثانوي" + +#: src/FLTK/flgui.cpp:4419 +msgid "Select your secondary sound card device" +msgstr "حدد جهاز الصوت الثانوي" + +#: src/FLTK/flgui.cpp:4441 src/FLTK/flgui.cpp:4472 +msgid "Codec" +msgstr "الترميز" + +#: src/FLTK/flgui.cpp:4442 +msgid "Select streaming codec" +msgstr "حدد ترميز البث" + +#: src/FLTK/flgui.cpp:4455 src/FLTK/flgui.cpp:4486 +msgid "Bitrate" +msgstr "معدل البت" + +#: src/FLTK/flgui.cpp:4456 +msgid "Select streaming bitrate" +msgstr "حدد معدل البت للبث" + +#: src/FLTK/flgui.cpp:4473 +msgid "Select recording codec" +msgstr "حدد ترميز التسجيل" + +#: src/FLTK/flgui.cpp:4487 +msgid "Select recording bitrate" +msgstr "حدد عدل البث للتسجيل" + +#: src/FLTK/flgui.cpp:4499 +msgid "Advanced..." +msgstr "متقدم..." + +#: src/FLTK/flgui.cpp:4505 +msgid "Buffer (ms)" +msgstr "حجم الذاكرة المؤقتة (بالمللي ثانية)" + +#: src/FLTK/flgui.cpp:4514 +msgid "Resample Quality" +msgstr "جودة إعادة العينة" + +#: src/FLTK/flgui.cpp:4529 +msgid "Signal detection levels" +msgstr "مستويات الكش٠عن الإشارة" + +#: src/FLTK/flgui.cpp:4532 +msgid "Signal present" +msgstr "الإشارة موجودة" + +#: src/FLTK/flgui.cpp:4539 src/FLTK/flgui.cpp:4549 +msgid "dB" +msgstr "dB" + +#: src/FLTK/flgui.cpp:4542 +msgid "Signal absent" +msgstr "الإشارة غير موجودة" + +#: src/FLTK/flgui.cpp:4556 src/FLTK/flgui.cpp:4833 src/FLTK/flgui.cpp:5084 +msgid "Stream" +msgstr "البث" + +#: src/FLTK/flgui.cpp:4558 +msgid "Update song name from file" +msgstr "تحديث اسم الأغنية من الملÙ" + +#: src/FLTK/flgui.cpp:4562 +msgid "Filename that holds the current song name" +msgstr "اسم المل٠الذي يحمل اسم الأغنية الحالية" + +#: src/FLTK/flgui.cpp:4568 +msgid "Select file that holds the current song name" +msgstr "حدد المل٠الذي يحمل اسم الأغنية الحالية" + +#: src/FLTK/flgui.cpp:4573 src/FLTK/flgui.cpp:4606 src/FLTK/flgui.cpp:4724 +msgid "Activate" +msgstr "ØªÙØ¹ÙŠÙ„" + +#: src/FLTK/flgui.cpp:4574 src/FLTK/flgui.cpp:4579 +msgid "Activate auto update song name from file" +msgstr "ØªÙØ¹ÙŠÙ„ التحديث التلقائي لاسم الأغنية من الملÙ" + +#: src/FLTK/flgui.cpp:4578 +msgid "Read last line instead of first" +msgstr "اقرأ السطر الأخير بدلاً من الأول" + +#: src/FLTK/flgui.cpp:4585 +msgid "Update song name from application" +msgstr "تحديث اسم الأغنية من التطبيق" + +#: src/FLTK/flgui.cpp:4589 +msgid "Changes the song through an running application" +msgstr "تغيير الأغنية من خلال تطبيق قيد التشغيل" + +#: src/FLTK/flgui.cpp:4594 +msgid "Title - Artist" +msgstr "العنوان - الÙنان" + +#: src/FLTK/flgui.cpp:4599 +msgid "Artist - Title" +msgstr "الÙنان - العنوان" + +#: src/FLTK/flgui.cpp:4612 +msgid "Update song name manually" +msgstr "قم بتحديث اسم الأغنية يدويًا" + +#: src/FLTK/flgui.cpp:4616 +msgid "Current song name" +msgstr "اسم الاغنية الحالية" + +#: src/FLTK/flgui.cpp:4622 src/FLTK/fl_callbacks.cpp:1594 +msgid "OK" +msgstr "مواÙÙ‚" + +#: src/FLTK/flgui.cpp:4623 +msgid "Send current song name to the server" +msgstr "إرسال اسم الأغنية الحالية إلى الخادم" + +#: src/FLTK/flgui.cpp:4631 +msgid "Update song name delay" +msgstr "تأخير تحديث اسم الأغنية" + +#: src/FLTK/flgui.cpp:4635 +msgid "Introduces a delay until the song name is actually updated" +msgstr "تقديم تأخير حتى يتم تحديث اسم الأغنية ÙØ¹Ù„ياً" + +#: src/FLTK/flgui.cpp:4642 +msgid "Extend song name" +msgstr "توسيع اسم الأغنية" + +#: src/FLTK/flgui.cpp:4645 +msgid "Prefix:" +msgstr "البادئة:" + +#: src/FLTK/flgui.cpp:4650 +msgid "Suffix:" +msgstr "اللاحقة:" + +#: src/FLTK/flgui.cpp:4660 src/FLTK/flgui.cpp:4789 +msgid "Start if signal is present for" +msgstr "ابدأ إذا كانت الإشارة موجودة" + +#: src/FLTK/flgui.cpp:4661 +msgid "" +"Start streaming if the audio level exceeds the \"Signal present\" level set " +"in the \"Audio\" tab" +msgstr "" +"ابدأ البث إذا تجاوز مستوى الصوت مستوى \"الإشارة موجودة\" المحدد ÙÙŠ علامة " +"التبويب \"الصوت\"" + +#: src/FLTK/flgui.cpp:4670 src/FLTK/flgui.cpp:4683 src/FLTK/flgui.cpp:4702 +#: src/FLTK/flgui.cpp:4799 src/FLTK/flgui.cpp:4812 src/FLTK/flgui.cpp:5499 +msgid "seconds" +msgstr "ثواني" + +#: src/FLTK/flgui.cpp:4673 src/FLTK/flgui.cpp:4802 +msgid "Stop if signal is absent for" +msgstr "توق٠إذا كانت الإشارة غير موجودة" + +#: src/FLTK/flgui.cpp:4674 +msgid "" +"Stop streaming if the audio level falls below the \"Signal absent level set " +"in the \"Audio\" tab" +msgstr "" +"أوق٠البث إذا Ø§Ù†Ø®ÙØ¶ مستوى الصوت عن مستوى \"الإشارة الغائبة\" المحدد ÙÙŠ علامة " +"التبويب \"الصوت" + +#: src/FLTK/flgui.cpp:4686 +msgid "Start streaming after launch" +msgstr "ابدأ البث بعد الإطلاق" + +#: src/FLTK/flgui.cpp:4687 +msgid "Connect automatically to a server after launch" +msgstr "الاتصال تلقائيًا بالخادم بعد الإطلاق" + +#: src/FLTK/flgui.cpp:4691 +msgid "Force reconnecting" +msgstr "ÙØ±Ø¶ إعادة الاتصال" + +#: src/FLTK/flgui.cpp:4692 +msgid "If enabled butt keeps reconnecting regardless of the error message" +msgstr "" +"إذا تم تمكينه، ÙØ¥Ù† butt سيستمر ÙÙŠ إعادة الاتصال بغض النظر عن رسالة الخطأ" + +#: src/FLTK/flgui.cpp:4696 +msgid "Reconnect delay:" +msgstr "تأخير إعادة الاتصال:" + +#: src/FLTK/flgui.cpp:4707 +msgid "Update song name from URL" +msgstr "تحديث اسم الأغنية من عنوان URL" + +#: src/FLTK/flgui.cpp:4711 +msgid "URL to get song name from" +msgstr "عنوان URL للحصول على اسم الأغنية من" + +#: src/FLTK/flgui.cpp:4716 +msgid "Update interval" +msgstr "تحديث Ø§Ù„ÙØ§ØµÙ„ الزمني" + +#: src/FLTK/flgui.cpp:4717 +msgid "Update interval in seconds" +msgstr "Ø§Ù„ÙØ§ØµÙ„ الزمني للتحديث بالثواني" + +#: src/FLTK/flgui.cpp:4732 +msgid "Record" +msgstr "تسجيل" + +#: src/FLTK/flgui.cpp:4734 +msgid "Record File Name:" +msgstr "اسم مل٠التسجيل:" + +#: src/FLTK/flgui.cpp:4735 +msgid "Record file name" +msgstr "اسم مل٠التسجيل" + +#: src/FLTK/flgui.cpp:4740 +msgid "Record Directory:" +msgstr "مجلد التسجيل:" + +#: src/FLTK/flgui.cpp:4741 +msgid "Directory of recordings" +msgstr "مجلد التسجيلات" + +#: src/FLTK/flgui.cpp:4747 +msgid "Select recording directory" +msgstr "حدد مجلد التسجيل" + +#: src/FLTK/flgui.cpp:4752 +msgid "Split file" +msgstr "تقسيم الملÙ" + +#: src/FLTK/flgui.cpp:4755 +msgid "every" +msgstr "كل" + +#: src/FLTK/flgui.cpp:4758 +msgid "minutes" +msgstr "دقيقة" + +#: src/FLTK/flgui.cpp:4760 src/FLTK/flgui.cpp:4761 +msgid "Sync to full hour" +msgstr "المزامنة إلى ساعة كاملة" + +#: src/FLTK/flgui.cpp:4765 +msgid "Split now" +msgstr "تقسيم الآن" + +#: src/FLTK/flgui.cpp:4774 src/FLTK/flgui.cpp:4775 +msgid "Start recording when connected" +msgstr "بدء التسجيل عند الاتصال" + +#: src/FLTK/flgui.cpp:4779 +msgid "Stop recording when disconnected" +msgstr "إيقا٠التسجيل عند انقطاع الاتصال" + +#: src/FLTK/flgui.cpp:4780 +msgid "Start recording when disconnected" +msgstr "بدء التسجيل عند انقطاع الاتصال" + +#: src/FLTK/flgui.cpp:4784 src/FLTK/flgui.cpp:4785 +msgid "Start recording after launch" +msgstr "بدء التسجيل بعد التشغيل" + +#: src/FLTK/flgui.cpp:4790 +msgid "" +"Start recording if the audio level exceeds the \"Signal present\" level set " +"in the \"Audio\" tab" +msgstr "" +"ابدأ التسجيل إذا تجاوز مستوى الصوت مستوى \"الإشارة الموجودة\" المحدد ÙÙŠ " +"علامة التبويب \"الصوت\"" + +#: src/FLTK/flgui.cpp:4803 +msgid "" +"Stop recording if the audio level falls below the \"Signal absent level set " +"in the \"Audio\" tab" +msgstr "" +"أوق٠التسجيل إذا Ø§Ù†Ø®ÙØ¶ مستوى الصوت عن مستوى \"الإشارة الغائبة\" المحدد ÙÙŠ " +"علامة التبويب \"الصوت" + +#: src/FLTK/flgui.cpp:4815 +msgid "Overwrite existing files" +msgstr "الكتابة Ùوق Ø§Ù„Ù…Ù„ÙØ§Øª الموجودة" + +#: src/FLTK/flgui.cpp:4823 +msgid "DSP" +msgstr "DSP" + +#: src/FLTK/flgui.cpp:4825 src/FLTK/flgui.cpp:5076 src/FLTK/flgui.cpp:6478 +msgid "Reset" +msgstr "إعادة تعيين" + +#: src/FLTK/flgui.cpp:4830 +msgid "Equalizer" +msgstr "المعادل" + +#: src/FLTK/flgui.cpp:4837 src/FLTK/flgui.cpp:5088 +msgid "Rec" +msgstr "تسجيل" + +#: src/FLTK/flgui.cpp:4842 +msgid "Equalizer Preset" +msgstr "ضبط المعادل مسبقاً" + +#: src/FLTK/flgui.cpp:4854 src/FLTK/flgui.cpp:4876 src/FLTK/flgui.cpp:4898 +#: src/FLTK/flgui.cpp:4920 src/FLTK/flgui.cpp:4942 src/FLTK/flgui.cpp:4964 +#: src/FLTK/flgui.cpp:4986 src/FLTK/flgui.cpp:5008 src/FLTK/flgui.cpp:5030 +#: src/FLTK/flgui.cpp:5052 src/FLTK/flgui.cpp:5096 src/FLTK/flgui.cpp:5118 +#: src/FLTK/flgui.cpp:5186 +msgid "+0.0" +msgstr "+0.0" + +#: src/FLTK/flgui.cpp:4858 +msgid "32Hz" +msgstr "32Hz" + +#: src/FLTK/flgui.cpp:4880 +msgid "64Hz" +msgstr "64Hz" + +#: src/FLTK/flgui.cpp:4902 +msgid "125Hz" +msgstr "125Hz" + +#: src/FLTK/flgui.cpp:4924 +msgid "250Hz" +msgstr "250Hz" + +#: src/FLTK/flgui.cpp:4946 +msgid "500Hz" +msgstr "500Hz" + +#: src/FLTK/flgui.cpp:4968 +msgid "1kHz" +msgstr "1kHz" + +#: src/FLTK/flgui.cpp:4990 +msgid "2kHz" +msgstr "2kHz" + +#: src/FLTK/flgui.cpp:5012 +msgid "4kHz" +msgstr "4kHz" + +#: src/FLTK/flgui.cpp:5034 +msgid "8kHz" +msgstr "8kHz" + +#: src/FLTK/flgui.cpp:5056 +msgid "16kHz" +msgstr "16kHz" + +#: src/FLTK/flgui.cpp:5081 +msgid "Dynamic Range Compressor" +msgstr "ضاغط النطاق الديناميكي" + +#: src/FLTK/flgui.cpp:5092 +msgid "Aggressive Mode" +msgstr "الوضع العدائي" + +#: src/FLTK/flgui.cpp:5100 +msgid "Threshold" +msgstr "العتبة" + +#: src/FLTK/flgui.cpp:5122 +msgid "Ratio" +msgstr "النسبة" + +#: src/FLTK/flgui.cpp:5140 src/FLTK/flgui.cpp:5163 +msgid "+0.00" +msgstr "+0.00" + +#: src/FLTK/flgui.cpp:5144 +msgid "Attack" +msgstr "هجوم" + +#: src/FLTK/flgui.cpp:5167 +msgid "Release" +msgstr "الإصدار" + +#: src/FLTK/flgui.cpp:5190 +msgid "MakeupGain" +msgstr "زيادة التسوية" + +#: src/FLTK/flgui.cpp:5224 src/FLTK/flgui.cpp:5237 +msgid "MIDI" +msgstr "MIDI" + +#: src/FLTK/flgui.cpp:5226 +msgid "MIDI Device" +msgstr "جهاز MIDI" + +#: src/FLTK/flgui.cpp:5227 +msgid "Select your MIDI device" +msgstr "حدد جهاز MIDI الخاص بك" + +#: src/FLTK/flgui.cpp:5232 +msgid "Rescan" +msgstr "إعادة Ø§Ù„ÙØ­Øµ" + +#: src/FLTK/flgui.cpp:5233 +msgid "Rescan MIDI devices" +msgstr "إعادة ÙØ­Øµ أجهزة MIDI" + +#: src/FLTK/flgui.cpp:5238 +msgid "MIDI signal indicator" +msgstr "مؤشر إشارة MIDI" + +#: src/FLTK/flgui.cpp:5250 +msgid "MIDI Commands" +msgstr "أوامر MIDI" + +#: src/FLTK/flgui.cpp:5255 +msgid "Enable" +msgstr "ØªÙØ¹ÙŠÙ„" + +#: src/FLTK/flgui.cpp:5256 +msgid "Enable/Disable the selected MIDI command" +msgstr "تمكين/تعطيل أمر MIDI المحدد" + +#: src/FLTK/flgui.cpp:5262 +msgid "Channel" +msgstr "القناة" + +#: src/FLTK/flgui.cpp:5263 +msgid "Select MIDI channel" +msgstr "حدد قناة MIDI" + +#: src/FLTK/flgui.cpp:5277 +msgid "CC" +msgstr "CC" + +#: src/FLTK/flgui.cpp:5278 +msgid "Select CC number" +msgstr "حدد رقم CC" + +#: src/FLTK/flgui.cpp:5283 src/FLTK/fl_callbacks.cpp:6425 +msgid "Learn" +msgstr "تعلّم" + +#: src/FLTK/flgui.cpp:5284 +msgid "Activate to auto detect the channel and CC number" +msgstr "Ø§Ù„ØªÙØ¹ÙŠÙ„ للكش٠التلقائي عن القناة ورقم CC" + +#: src/FLTK/flgui.cpp:5289 +msgid "CC Mode" +msgstr "وضع CC" + +#: src/FLTK/flgui.cpp:5290 +msgid "Select CC mode" +msgstr "تحديد وضع CC" + +#: src/FLTK/flgui.cpp:5304 +msgid "Soft takeover" +msgstr "الاستحواذ الناعم" + +#: src/FLTK/flgui.cpp:5305 +msgid "Prevents jumps when controlling a slider in absolute mode" +msgstr "يمنع Ø§Ù„Ù‚ÙØ²Ø§Øª عند التحكم ÙÙŠ شريط التمرير ÙÙŠ الوضع المطلق" + +#: src/FLTK/flgui.cpp:5313 +msgid "TLS" +msgstr "TLS" + +#: src/FLTK/flgui.cpp:5315 src/FLTK/flgui.cpp:5619 +msgid "SSL/TLS" +msgstr "SSL/TLS" + +#: src/FLTK/flgui.cpp:5318 +msgid "" +"If your server uses a certificate from\n" +"Let's Encrypt or another well known\n" +"CA, you can leave these fields blank." +msgstr "" +"إذا كان خادمك يستخدم شهادة من\n" +"Let's Encrypt أو شهادة أخرى well known\n" +"CAØŒ يمكنك ترك هذه الحقول ÙØ§Ø±ØºØ©." + +#: src/FLTK/flgui.cpp:5322 +msgid "CA Certificate File:" +msgstr "مل٠شهادة CA:" + +#: src/FLTK/flgui.cpp:5323 +msgid "Certificate file" +msgstr "مل٠الشهادة" + +#: src/FLTK/flgui.cpp:5329 +msgid "Select certificate file" +msgstr "حدد مل٠الشهادة" + +#: src/FLTK/flgui.cpp:5334 +msgid "CA Certificate Directory:" +msgstr "مجلد شهادة CA:" + +#: src/FLTK/flgui.cpp:5335 +msgid "Certificate directory" +msgstr "مجلد الشهادة" + +#: src/FLTK/flgui.cpp:5341 +msgid "Select certificate directory" +msgstr "حدد مجلد الشهادة" + +#: src/FLTK/flgui.cpp:5350 +msgid "GUI" +msgstr "GUI" + +#: src/FLTK/flgui.cpp:5352 +msgid "Language" +msgstr "اللغة" + +#: src/FLTK/flgui.cpp:5369 +msgid "Display Color" +msgstr "لون العرض" + +#: src/FLTK/flgui.cpp:5372 +msgid "Text" +msgstr "النص" + +#: src/FLTK/flgui.cpp:5373 +msgid "Select text color" +msgstr "حدد لون الكتابة" + +#: src/FLTK/flgui.cpp:5379 +msgid "Background" +msgstr "لون الخلÙية" + +#: src/FLTK/flgui.cpp:5380 +msgid "Select background color" +msgstr "حدد لون الخلÙية" + +#: src/FLTK/flgui.cpp:5388 +msgid "VU meter" +msgstr "مقياس VU" + +#: src/FLTK/flgui.cpp:5391 +msgid "Gradient colors" +msgstr "ألوان متدرجة" + +#: src/FLTK/flgui.cpp:5396 +msgid "Solid colors" +msgstr "ألوان سادة" + +#: src/FLTK/flgui.cpp:5401 +msgid "Always show tabs" +msgstr "إظهار علامات التبويب دائماً" + +#: src/FLTK/flgui.cpp:5406 +msgid "Select lower range color" +msgstr "حدد نطاق اللون الأدنى" + +#: src/FLTK/flgui.cpp:5413 +msgid "Select mid range color" +msgstr "حدد نطاق اللون المستوط" + +#: src/FLTK/flgui.cpp:5420 +msgid "Select high range color" +msgstr "حدد نطاق اللون العالي" + +#: src/FLTK/flgui.cpp:5427 +msgid "Low range start value (dB)" +msgstr "قيمة بدء النطاق Ø§Ù„Ù…Ù†Ø®ÙØ¶ (dB)" + +#: src/FLTK/flgui.cpp:5431 +msgid "Mid range start value (dB)" +msgstr "قيمة بدء النطاق المتوسط (dB)" + +#: src/FLTK/flgui.cpp:5440 +msgid "High range start value (dB)" +msgstr "قيمة بدء النطاق العالي (dB)" + +#: src/FLTK/flgui.cpp:5450 +msgid "Misc" +msgstr "Ù…ØªÙØ±Ù‚ات" + +#: src/FLTK/flgui.cpp:5453 +msgid "Attach settings window to main window" +msgstr "Ø¥Ø±ÙØ§Ù‚ Ù†Ø§ÙØ°Ø© الإعدادات Ø¨Ø§Ù„Ù†Ø§ÙØ°Ø© الرئيسية" + +#: src/FLTK/flgui.cpp:5454 +msgid "Attach this window to the butt window" +msgstr "اربط هذه Ø§Ù„Ù†Ø§ÙØ°Ø© Ø¨Ù†Ø§ÙØ°Ø© butt" + +#: src/FLTK/flgui.cpp:5458 src/FLTK/flgui.cpp:5459 +msgid "Stay always on top" +msgstr "البقاء دائماً ÙÙŠ المقدمة" + +#: src/FLTK/flgui.cpp:5463 src/FLTK/flgui.cpp:5464 +msgid "Remember main window position" +msgstr "تذكر موضع Ø§Ù„Ù†Ø§ÙØ°Ø© الرئيسية" + +#: src/FLTK/flgui.cpp:5468 src/FLTK/flgui.cpp:5469 +msgid "Hide log window after start up" +msgstr "Ø¥Ø®ÙØ§Ø¡ Ù†Ø§ÙØ°Ø© السجل بعد بدء التشغيل" + +#: src/FLTK/flgui.cpp:5473 src/FLTK/flgui.cpp:5474 +msgid "Change display mode every 5 seconds" +msgstr "تغيير طريقة العرض كل 4 ثواني" + +#: src/FLTK/flgui.cpp:5478 +msgid "Start minimized" +msgstr "بدء التشغيل المصغر" + +#: src/FLTK/flgui.cpp:5479 +msgid "Minimize butt at startup" +msgstr "تصغير butt عند بدء التشغيل" + +#: src/FLTK/flgui.cpp:5483 +msgid "Disable gain control" +msgstr "تعطيل تحكم الاكتساب" + +#: src/FLTK/flgui.cpp:5489 +msgid "Show listeners" +msgstr "عرض المستمعين" + +#: src/FLTK/flgui.cpp:5490 +msgid "Show current listeners in the display (not always available)" +msgstr "إظهار المستمعين الحاليين ÙÙŠ الشاشة (غير Ù…ØªÙˆÙØ± دائمًا)" + +#: src/FLTK/flgui.cpp:5494 +msgid "Update rate:" +msgstr "معدل التحديث:" + +#: src/FLTK/flgui.cpp:5504 +msgid "Custom window title:" +msgstr "عنوان Ø§Ù„Ù†Ø§ÙØ°Ø© المخصص:" + +#: src/FLTK/flgui.cpp:5505 +msgid "Define a custom window title" +msgstr "تحديد عنوان Ù†Ø§ÙØ°Ø© مخصصة" + +#: src/FLTK/flgui.cpp:5515 +msgid "Donate" +msgstr "التبرع" + +#: src/FLTK/flgui.cpp:5517 +msgid "Donation" +msgstr "التبرع" + +#: src/FLTK/flgui.cpp:5520 +msgid "" +"Keeping this software up to date, adding\n" +"new features and answering support mails\n" +"takes a lot of time and effort. If you can\n" +"afford it, please consider supporting this\n" +"project.\n" +"\n" +"Thank you!" +msgstr "" +"Ø§Ù„Ø­ÙØ§Ø¸ على تحديث هذا البرنامج ÙˆØ¥Ø¶Ø§ÙØ©\n" +"ميزات جديدة والرد على رسائل الدعم\n" +"يستغرق الكثير من الوقت والجهد. إذا كنت تستطيع\n" +"تحمله، يرجى النظر ÙÙŠ دعم هذا\n" +"المشروع.\n" +"\n" +"شكراً لكم!" + +#: src/FLTK/flgui.cpp:5525 +msgid "&Donate via PayPal" +msgstr "تبرع عبر الباي بال" + +#: src/FLTK/flgui.cpp:5529 +msgid "Become a &patron" +msgstr "تبرع عبر باترون" + +#: src/FLTK/flgui.cpp:5533 +msgid "&Apple Pay, Google Pay, CC and more" +msgstr "تبرع عبر ابل باي، قوقل باي، CC والمزيد" + +#: src/FLTK/flgui.cpp:5537 +msgid "&Bitcoin && Co" +msgstr "تبرع عبر شركة بتكوين" + +#: src/FLTK/flgui.cpp:5552 src/FLTK/flgui.cpp:5673 +msgid "Name:" +msgstr "الاسم:" + +#: src/FLTK/flgui.cpp:5556 +msgid "Address:" +msgstr "العنوان:" + +#: src/FLTK/flgui.cpp:5560 +msgid "Port:" +msgstr "Ø§Ù„Ù…Ù†ÙØ°:" + +#: src/FLTK/flgui.cpp:5564 +msgid "Password:" +msgstr "كلمة المرور:" + +#: src/FLTK/flgui.cpp:5569 +msgid "Icecast mountpoint:" +msgstr "نقطة icecast:" + +#: src/FLTK/flgui.cpp:5573 +msgid "Icecast user:" +msgstr "اسم مستخدم icecast:" + +#: src/FLTK/flgui.cpp:5577 src/FLTK/fl_callbacks.cpp:1136 +#: src/FLTK/fl_callbacks.cpp:1215 src/FLTK/fl_callbacks.cpp:1623 +msgid "Show" +msgstr "عرض" + +#: src/FLTK/flgui.cpp:5578 +msgid "show/hide password" +msgstr "عرض/Ø¥Ø®ÙØ§Ø¡ كلمة المرور" + +#: src/FLTK/flgui.cpp:5582 +msgid "Type" +msgstr "النوع" + +#: src/FLTK/flgui.cpp:5585 +msgid "Shoutcast" +msgstr "Shoutcast" + +#: src/FLTK/flgui.cpp:5590 +msgid "Icecast" +msgstr "Icecast" + +#: src/FLTK/flgui.cpp:5595 +msgid "WebRTC" +msgstr "WebRTC" + +#: src/FLTK/flgui.cpp:5600 +msgid "Radio.co" +msgstr "Radio.co" + +#: src/FLTK/flgui.cpp:5607 src/FLTK/flgui.cpp:5709 +msgid "&Cancel" +msgstr "&الغاء" + +#: src/FLTK/flgui.cpp:5611 src/FLTK/flgui.cpp:5713 +msgid "&ADD" +msgstr "ا&Ø¶Ø§ÙØ©" + +#: src/FLTK/flgui.cpp:5622 +msgid "Use SSL/TLS" +msgstr "استخدام SSL/TLS" + +#: src/FLTK/flgui.cpp:5625 +msgid "Revoke certificate trust" +msgstr "إلغاء الثقة بالشهادة" + +#: src/FLTK/flgui.cpp:5631 +msgid "Radio.co Stations" +msgstr "محطات Radio.co" + +#: src/FLTK/flgui.cpp:5634 +msgid "Get Stations" +msgstr "الحصول على المحطات" + +#: src/FLTK/flgui.cpp:5638 +msgid "Select all" +msgstr "تحديد الكل" + +#: src/FLTK/flgui.cpp:5642 +msgid "Deselect all" +msgstr "الغاء تحديد الكل" + +#: src/FLTK/flgui.cpp:5646 +msgid "Use legacy Icecast protocol" +msgstr "استخدام بروتوكول Icecast القديم" + +#: src/FLTK/flgui.cpp:5647 +msgid "" +"Activate this if you want to use the older SOURCE protocol instead of the " +"newer PUT protocol" +msgstr "" +"قم بتنشيط هذا إذا كنت ترغب ÙÙŠ استخدام بروتوكول SOURCE الأقدم بدلاً من " +"بروتوكول PUT الأحدث" + +#: src/FLTK/flgui.cpp:5651 +msgid "ICE server (optional):" +msgstr "خادم ICE (اختياري):" + +#: src/FLTK/flgui.cpp:5654 +msgid "WebRTC (WHIP) URL:" +msgstr "عنوان WebRTC (WHIP):" + +#: src/FLTK/flgui.cpp:5657 +msgid "Bearer token (optional):" +msgstr "رمز المصادقة:" + +#: src/FLTK/flgui.cpp:5660 +msgid "Custom listener URL (optional):" +msgstr "عنوان URL لعدد المستمعين (اختياري):" + +#: src/FLTK/flgui.cpp:5664 +msgid "Custom listener mountpoint (optional):" +msgstr "نقطة التحميل لعدد المستمعين (اختياري):" + +#: src/FLTK/flgui.cpp:5674 +msgid "The name of your new ICY-entrie" +msgstr "اسم مركز ICY-entrie الجديد الخاص بك" + +#: src/FLTK/flgui.cpp:5678 +msgid "Description:" +msgstr "الوصÙ:" + +#: src/FLTK/flgui.cpp:5682 +msgid "Genre:" +msgstr "النوع:" + +#: src/FLTK/flgui.cpp:5686 +msgid "URL:" +msgstr "الرابط:" + +#: src/FLTK/flgui.cpp:5690 +msgid "ICQ:" +msgstr "ICQ:" + +#: src/FLTK/flgui.cpp:5694 +msgid "IRC:" +msgstr "IRC:" + +#: src/FLTK/flgui.cpp:5698 +msgid "AIM:" +msgstr "AIM:" + +#: src/FLTK/flgui.cpp:5702 +msgid "Make server public" +msgstr "جعل الخادم عام" + +#: src/FLTK/flgui.cpp:5705 +msgid "Expand variables" +msgstr "توسيع المتغيرات" + +#: src/FLTK/flgui.cpp:5706 +msgid "Activate to expand date variables in name and description" +msgstr "تنشيط لتوسيع متغيرات التاريخ ÙÙŠ الاسم والوصÙ" + +#: src/FLTK/flgui.cpp:5736 +msgid "Donate Cryptocurrency" +msgstr "التبرع بالعملة Ø§Ù„Ù…Ø´ÙØ±Ø©" + +#: src/FLTK/flgui.cpp:5747 +msgid "Bitcoin" +msgstr "بتكوين" + +#: src/FLTK/flgui.cpp:5752 src/FLTK/flgui.cpp:5761 src/FLTK/flgui.cpp:5770 +msgid "Copy" +msgstr "نسخ" + +#: src/FLTK/flgui.cpp:5756 +msgid "Litecoin" +msgstr "لايتكوين" + +#: src/FLTK/flgui.cpp:5765 +msgid "Monero" +msgstr "مونيرو" + +#: src/FLTK/flgui.cpp:5774 src/FLTK/flgui.cpp:6106 src/FLTK/flgui.cpp:6461 +#: src/FLTK/flgui.cpp:6669 +msgid "&Close" +msgstr "اغ&لاق" + +#: src/FLTK/flgui.cpp:5780 +msgid "Streaming Codec Settings" +msgstr "إعدادات ترميز البث" + +#: src/FLTK/flgui.cpp:5792 src/FLTK/flgui.cpp:6124 +msgid "MP3" +msgstr "MP3" + +#: src/FLTK/flgui.cpp:5793 src/FLTK/flgui.cpp:6125 +msgid "Encoding Quality" +msgstr "جودة الترميز" + +#: src/FLTK/flgui.cpp:5806 src/FLTK/flgui.cpp:6138 +msgid "Stereo Mode" +msgstr "وضع الاستريو" + +#: src/FLTK/flgui.cpp:5819 src/FLTK/flgui.cpp:5949 src/FLTK/flgui.cpp:6015 +#: src/FLTK/flgui.cpp:6071 src/FLTK/flgui.cpp:6151 src/FLTK/flgui.cpp:6281 +#: src/FLTK/flgui.cpp:6334 src/FLTK/flgui.cpp:6403 +msgid "Bitrate Mode" +msgstr "وضع معدل البت" + +#: src/FLTK/flgui.cpp:5832 src/FLTK/flgui.cpp:6164 +msgid "VBR" +msgstr "VBR" + +#: src/FLTK/flgui.cpp:5835 src/FLTK/flgui.cpp:5989 src/FLTK/flgui.cpp:6167 +#: src/FLTK/flgui.cpp:6347 +msgid "Quality" +msgstr "الجودة" + +#: src/FLTK/flgui.cpp:5848 src/FLTK/flgui.cpp:6180 +msgid "Min. Bitrate" +msgstr "اقل معدل البت" + +#: src/FLTK/flgui.cpp:5861 src/FLTK/flgui.cpp:6193 +msgid "Max. Bitrate" +msgstr "اعلى معدل البت" + +#: src/FLTK/flgui.cpp:5874 src/FLTK/flgui.cpp:6206 +msgid "Force" +msgstr "ÙØ±Ø¶" + +#: src/FLTK/flgui.cpp:5875 src/FLTK/flgui.cpp:6207 +msgid "Strictly enforce mininum Bitrate (-F option of the lame encoder)" +msgstr "ÙØ±Ø¶ الحد الأدنى لمعدل البت بدقة (خيار -F من Ø§Ù„Ù…Ø´ÙØ± الأعرج)" + +#: src/FLTK/flgui.cpp:5881 src/FLTK/flgui.cpp:6227 +msgid "Lowpass (kHz)" +msgstr "تجاوز Ù…Ù†Ø®ÙØ¶ (كيلوهرتز)" + +#: src/FLTK/flgui.cpp:5884 src/FLTK/flgui.cpp:5909 src/FLTK/flgui.cpp:6230 +#: src/FLTK/flgui.cpp:6255 +msgid "Frequency" +msgstr "التكرار" + +#: src/FLTK/flgui.cpp:5890 src/FLTK/flgui.cpp:5915 src/FLTK/flgui.cpp:6236 +#: src/FLTK/flgui.cpp:6261 +msgid "Width" +msgstr "العرض" + +#: src/FLTK/flgui.cpp:5906 src/FLTK/flgui.cpp:6252 +msgid "Highpass (kHz)" +msgstr "تجاوز عال (كيلوهرتز)" + +#: src/FLTK/flgui.cpp:5931 src/FLTK/flgui.cpp:6213 +msgid "Resampling" +msgstr "إعادة أخذ العينات" + +#: src/FLTK/flgui.cpp:5932 src/FLTK/flgui.cpp:6214 +msgid "Resample to the selected sample rate" +msgstr "إعادة العينة إلى معدل العينة المحدد" + +#: src/FLTK/flgui.cpp:5947 src/FLTK/flgui.cpp:6279 +msgid "OGG" +msgstr "OGG" + +#: src/FLTK/flgui.cpp:5962 src/FLTK/flgui.cpp:6294 +msgid "VBR Quality" +msgstr "جودة VBR" + +#: src/FLTK/flgui.cpp:5975 src/FLTK/flgui.cpp:6307 +msgid "VBR min. Bitrate" +msgstr "اقل VBR. معدل البت" + +#: src/FLTK/flgui.cpp:5980 src/FLTK/flgui.cpp:6312 +msgid "VBR max. Bitrate" +msgstr "اعلى VBR. معدل البت" + +#: src/FLTK/flgui.cpp:5987 src/FLTK/flgui.cpp:6319 +msgid "OPUS" +msgstr "OPUS" + +#: src/FLTK/flgui.cpp:6002 src/FLTK/flgui.cpp:6321 +msgid "Optimize for" +msgstr "التحسين من أجل" + +#: src/FLTK/flgui.cpp:6028 src/FLTK/flgui.cpp:6360 +msgid "Max. Bandwidth" +msgstr "اعلى. الباندويث" + +#: src/FLTK/flgui.cpp:6043 src/FLTK/flgui.cpp:6375 +msgid "AAC" +msgstr "AAC" + +#: src/FLTK/flgui.cpp:6045 src/FLTK/flgui.cpp:6377 +msgid "Profile" +msgstr "المل٠الشخصي" + +#: src/FLTK/flgui.cpp:6058 src/FLTK/flgui.cpp:6390 +msgid "Afterburner" +msgstr "زيادة الاشارة" + +#: src/FLTK/flgui.cpp:6086 src/FLTK/flgui.cpp:6418 +msgid "FLAC" +msgstr "FLAC" + +#: src/FLTK/flgui.cpp:6088 src/FLTK/flgui.cpp:6420 src/FLTK/flgui.cpp:6438 +msgid "Bit depth" +msgstr "عمق الـ Bit" + +#: src/FLTK/flgui.cpp:6090 src/FLTK/flgui.cpp:6422 src/FLTK/flgui.cpp:6440 +msgid "16 bit" +msgstr "16 bit" + +#: src/FLTK/flgui.cpp:6095 src/FLTK/flgui.cpp:6427 src/FLTK/flgui.cpp:6450 +msgid "24 bit" +msgstr "24 bit" + +#: src/FLTK/flgui.cpp:6112 +msgid "Recording Codec Settings" +msgstr "إعدادات ترميز التسجيل" + +#: src/FLTK/flgui.cpp:6436 +msgid "WAV" +msgstr "WAV" + +#: src/FLTK/flgui.cpp:6445 +msgid "32 bit" +msgstr "32 bit" + +#: src/FLTK/flgui.cpp:6467 +msgid "butt audio mixer" +msgstr "butt ميكسر الصوت" + +#: src/FLTK/flgui.cpp:6483 +msgid "Audio Mixer" +msgstr "ميكسر الصوت" + +#: src/FLTK/flgui.cpp:6486 src/FLTK/flgui.cpp:6516 src/FLTK/flgui.cpp:6546 +#: src/FLTK/flgui.cpp:6569 src/FLTK/flgui.cpp:6592 +msgid "+0.0 dB" +msgstr "+0.0 dB" + +#: src/FLTK/flgui.cpp:6491 src/FLTK/flgui.cpp:6634 +msgid "" +"Primary\n" +"Device" +msgstr "" +"الجهاز\n" +"الاساسي" + +#: src/FLTK/flgui.cpp:6509 src/FLTK/flgui.cpp:6510 src/FLTK/flgui.cpp:6539 +#: src/FLTK/flgui.cpp:6540 +msgid "Mute" +msgstr "كتم" + +#: src/FLTK/flgui.cpp:6521 src/FLTK/flgui.cpp:6642 +msgid "" +"Secondary\n" +"Device" +msgstr "" +"الجهاز\n" +"الثانوي" + +#: src/FLTK/flgui.cpp:6551 +msgid "" +"Streaming\n" +"Gain" +msgstr "" +"مستوى\n" +"البث" + +#: src/FLTK/flgui.cpp:6574 +msgid "" +"Recording\n" +"Gain" +msgstr "" +"مستوى\n" +"التسجيل" + +#: src/FLTK/flgui.cpp:6597 +msgid "" +"Master\n" +"Gain" +msgstr "" +"مستوى\n" +"الماستر" + +#: src/FLTK/flgui.cpp:6615 +msgid "" +"\n" +"Cross Fader" +msgstr "" +"\n" +"التداخل" + +#: src/FLTK/flgui.cpp:6638 +msgid "|" +msgstr "|" + +#: src/FLTK/flgui.cpp:6650 +msgid "Alert" +msgstr "تنبيه" + +#: src/FLTK/flgui.cpp:6661 +msgid "&Open the manual" +msgstr "&Ø§ÙØªØ­ الدليل" + +#: src/FLTK/flgui.cpp:6665 +msgid "" +"Could not find aac library.\n" +"\n" +"Please follow the instructions in the manual\n" +"for adding aac support." +msgstr "" +"تعذر العثور على مكتبة AAC.\n" +"\n" +"يرجى اتباع التعليمات الموجودة ÙÙŠ الدليل\n" +"Ù„Ø¥Ø¶Ø§ÙØ© دعم AAC." + +#: src/FLTK/fl_timer_funcs.cpp:318 +#, c-format +msgid "" +"stream sent\n" +"%0.2lfMB" +msgstr "" +"stream sent\n" +"%0.2lfMB" + +#: src/FLTK/fl_timer_funcs.cpp:323 +#, c-format +msgid "" +"stream time\n" +"%s" +msgstr "" +"stream time\n" +"%s" + +# Please do not translate! +#: src/FLTK/fl_timer_funcs.cpp:330 +#, c-format +msgid "" +"On Air\n" +"Listeners %5d" +msgstr "" + +# Please do not translate! +#: src/FLTK/fl_timer_funcs.cpp:333 +#, c-format +msgid "" +"On Air\n" +"Listeners>%5d" +msgstr "" + +# Please do not translate! +#: src/FLTK/fl_timer_funcs.cpp:337 +#, c-format +msgid "On Air" +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:343 +#, c-format +msgid "" +"record time\n" +"%s" +msgstr "" +"record time\n" +"%s" + +#: src/FLTK/fl_timer_funcs.cpp:348 +#, c-format +msgid "" +"record size\n" +"%0.2lfMB" +msgstr "" +"record size\n" +"%0.2lfMB" + +#: src/FLTK/fl_timer_funcs.cpp:479 +#, c-format +msgid "" +"ERROR: Connection lost\n" +"reconnecting in %d seconds..." +msgstr "" +"خطأ: تم Ùقدان الاتصال\n" +"إعادة الاتصال ÙÙŠ %d ثانية..." + +#: src/FLTK/fl_timer_funcs.cpp:483 +msgid "" +"ERROR: Connection lost\n" +"reconnecting..." +msgstr "" +"خطأ: تم Ùقدان الاتصال\n" +"إعادة الاتصال..." + +#: src/FLTK/fl_timer_funcs.cpp:608 +msgid "Listeners" +msgstr "المستمعين" + +#: src/FLTK/fl_timer_funcs.cpp:674 +msgid "" +"Could not find a file extension in current filename\n" +"Automatic file splitting is deactivated" +msgstr "" +"تعذر العثور على امتداد مل٠ÙÙŠ اسم المل٠الحالي.\n" +"تم إلغاء ØªÙØ¹ÙŠÙ„ التقسيم التلقائي للملÙ" + +#: src/FLTK/fl_timer_funcs.cpp:704 +msgid "" +"Could not find a valid filename for next file\n" +"butt keeps recording to current file" +msgstr "" +"تعذر العثور على اسم مل٠صالح للمل٠التالي.\n" +"butt مستمر ÙÙŠ التسجيل ÙÙŠ المل٠الحالي" + +#: src/FLTK/fl_timer_funcs.cpp:717 src/FLTK/fl_callbacks.cpp:1033 +#, c-format +msgid "" +"Could not open:\n" +"%s" +msgstr "" +"تعذر ÙØªØ­:\n" +"%s" + +#: src/FLTK/fl_timer_funcs.cpp:721 src/port_audio.cpp:938 +msgid "Recording to:" +msgstr "التسجيل الى:" + +#: src/FLTK/fl_timer_funcs.cpp:964 +#, c-format +msgid "" +"Warning\n" +"Could not open: %s.\n" +"Will retry in 5 seconds" +msgstr "" +"تحذير\n" +"لا يمك ÙØªØ­ %s.\n" +"ستتم الإعادة بعد 5 ثواني" + +#: src/FLTK/fl_callbacks.cpp:145 +msgid "connecting" +msgstr "connecting" + +#: src/FLTK/fl_callbacks.cpp:187 +msgid "" +"Error: No server entry found.\n" +"Please add a server in the settings-window." +msgstr "" +"خطأ: لم يتم العثور على الخادم.\n" +"يرجى Ø¥Ø¶Ø§ÙØ© خادم ÙÙŠ Ù†Ø§ÙØ°Ø© الإعدادات." + +#: src/FLTK/fl_callbacks.cpp:192 +msgid "" +"Error: ogg vorbis encoder doesn't support bitrates\n" +"lower than 48kbit" +msgstr "" +"خطأ: ترميز ogg vorbis لا يدعم معدلات البت\n" +"أقل من 48 كيلوبت ÙÙŠ الثانية" + +#: src/FLTK/fl_callbacks.cpp:200 +#, c-format +msgid "Warning: %s is not supported by every Shoutcast version" +msgstr "تحذير: %s لا يدعمه كل إصدار من Shoutcast" + +#: src/FLTK/fl_callbacks.cpp:204 +msgid "Error: FLAC is not supported by ShoutCast" +msgstr "خطأ: FLAC غير معتمد من قبل ShoutCast" + +#: src/FLTK/fl_callbacks.cpp:211 +#, c-format +msgid "Error: Radio.co supports only mp3 and aac" +msgstr "خطأ: Radio.co يدعم Ùقط mp3 Ùˆ aac" + +#: src/FLTK/fl_callbacks.cpp:219 +#, c-format +msgid "Error: WebRTC only supports opus" +msgstr "خطأ: WebRTC يدعم Ùقط Opus" + +#: src/FLTK/fl_callbacks.cpp:226 +#, c-format +msgid "Connecting to %s via %s ..." +msgstr "جاري الاتصال بـ %s عبر %s ..." + +#: src/FLTK/fl_callbacks.cpp:229 +#, c-format +msgid "Connecting to %s:%u ..." +msgstr "جار٠الاتصال بـ %s:%u ..." + +#: src/FLTK/fl_callbacks.cpp:232 +#, c-format +msgid "Connecting to %s:%u (%u) ..." +msgstr "جار٠الاتصال بـ %s:%u (%u) ..." + +#: src/FLTK/fl_callbacks.cpp:328 +msgid "Connection established" +msgstr "تم الاتصال" + +#: src/FLTK/fl_callbacks.cpp:342 src/FLTK/fl_callbacks.cpp:4275 +#: src/FLTK/fl_callbacks.cpp:4281 +msgid "no" +msgstr "لا" + +#: src/FLTK/fl_callbacks.cpp:342 src/FLTK/fl_callbacks.cpp:4275 +#: src/FLTK/fl_callbacks.cpp:4281 +msgid "yes" +msgstr "نعم" + +#: src/FLTK/fl_callbacks.cpp:344 +#, c-format +msgid "Device 1:\t%s\n" +msgstr "الجهاز 1:\t%s\n" + +#: src/FLTK/fl_callbacks.cpp:345 +#, c-format +msgid "Device 2:\t%s\n" +msgstr "الجهاز 2:\t%s\n" + +#: src/FLTK/fl_callbacks.cpp:396 +#, c-format +msgid "Connected to: %s" +msgstr "تم الاتصال بـ: %s" + +#: src/FLTK/fl_callbacks.cpp:567 src/FLTK/fl_callbacks.cpp:1669 +msgid "The custom listener URL must start with http:// or https://" +msgstr "يجب أن يبدأ عنوان URL إما ب http:// أو https://" + +#: src/FLTK/fl_callbacks.cpp:574 src/FLTK/fl_callbacks.cpp:1676 +msgid "" +"No mountpoint specified\n" +"Setting mountpoint to \"stream\"" +msgstr "" +"لم يتم تحديد النقطه\n" +"جار٠تحديد النقطه الى \"stream\"" + +#: src/FLTK/fl_callbacks.cpp:578 src/FLTK/fl_callbacks.cpp:1680 +msgid "" +"No user specified\n" +"Setting user to \"source\"" +msgstr "" +"لم يتم تحديد المستخدم\n" +"جار٠تحديد المستخدم الى \"source\"" + +#: src/FLTK/fl_callbacks.cpp:586 src/FLTK/fl_callbacks.cpp:1688 +msgid "" +"Unsupported listener URL.\n" +"The listener URL must end with status-json.xsl, 7.xsl, 7.html or contain " +"stats?sid" +msgstr "" +"عنوان URL للمستمع غير مدعو\n" +"يجب أن ينتهي عنوان URL للمستمع بـ status-json.xsl أو 7.xsl أو 7.html أو " +"يحتوي على stats?sid." + +#: src/FLTK/fl_callbacks.cpp:592 src/FLTK/fl_callbacks.cpp:1694 +#: src/FLTK/fl_callbacks.cpp:1857 src/FLTK/fl_callbacks.cpp:2545 +msgid "No name specified" +msgstr "لم يتم تحديد اسم" + +#: src/FLTK/fl_callbacks.cpp:597 src/FLTK/fl_callbacks.cpp:1699 +msgid "" +"The number of characters of all your server names exeeds 1000\n" +"Please reduce the number of characters of each server name" +msgstr "" +"عدد الأحر٠ÙÙŠ جميع أسماء الخوادم يتجاوز 1000 حرÙًا.\n" +"يرجى تقليل عدد الأحر٠لكل اسم خادم" + +#: src/FLTK/fl_callbacks.cpp:603 src/FLTK/fl_callbacks.cpp:1705 +msgid "Newline characters and [];/\\ are not allowed within the server name" +msgstr "لا ÙŠÙØ³Ù…Ø­ بوجود أحر٠سطر جديد Ùˆ [];/\\ غير مسموح بها داخل اسم الخادم" + +#: src/FLTK/fl_callbacks.cpp:609 src/FLTK/fl_callbacks.cpp:1710 +msgid "No address specified" +msgstr "لم يتم تحديد عنوان" + +#: src/FLTK/fl_callbacks.cpp:613 src/FLTK/fl_callbacks.cpp:1714 +msgid "No password specified" +msgstr "لم يتم تحديد كلمة مرور" + +#: src/FLTK/fl_callbacks.cpp:617 src/FLTK/fl_callbacks.cpp:1718 +msgid "No port specified" +msgstr "لم يتم تحديد Ù…Ù†ÙØ°" + +#: src/FLTK/fl_callbacks.cpp:621 src/FLTK/fl_callbacks.cpp:1722 +msgid "" +"Invalid port number\n" +"The port number must be between 1 and 65535" +msgstr "" +"رقم Ø§Ù„Ù…Ù†ÙØ° غير صالح\n" +"يجب أن يكون رقم Ø§Ù„Ù…Ù†ÙØ° بين 1 Ùˆ65535" + +#: src/FLTK/fl_callbacks.cpp:628 src/FLTK/fl_callbacks.cpp:1729 +msgid "No WHIP URL specified" +msgstr "لم يتم تحديد عنوان WHIP محدد" + +#: src/FLTK/fl_callbacks.cpp:637 src/FLTK/fl_callbacks.cpp:1740 +#: src/FLTK/fl_callbacks.cpp:2564 +msgid "Server name already exist!" +msgstr "اسم Ø§Ù„Ø³ÙŠØ±ÙØ± موجود مسبقاً!" + +#: src/FLTK/fl_callbacks.cpp:966 +msgid "stop recording?" +msgstr "إيقا٠التسجيل؟" + +#: src/FLTK/fl_callbacks.cpp:966 src/FLTK/fl_funcs.cpp:1462 +msgid "No" +msgstr "لا" + +#: src/FLTK/fl_callbacks.cpp:966 +msgid "Yes" +msgstr "نعم" + +#: src/FLTK/fl_callbacks.cpp:1005 +msgid "No recording filename specified" +msgstr "لم يتم تحديد اسم مل٠التسجيل" + +#: src/FLTK/fl_callbacks.cpp:1015 +#, c-format +msgid "%s already exists!" +msgstr "%s موجود مسبقاً!" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "overwrite" +msgstr "الكتابة على" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "cancel" +msgstr "الغاء" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "append" +msgstr "إلحاق" + +#: src/FLTK/fl_callbacks.cpp:1021 +msgid "Recording canceled" +msgstr "تم إلغاء التسجيل" + +#: src/FLTK/fl_callbacks.cpp:1090 src/FLTK/fl_funcs.cpp:1308 +msgid "Hide log" +msgstr "Ø¥Ø®ÙØ§Ø¡ السجل" + +#: src/FLTK/fl_callbacks.cpp:1123 +msgid "Add Server" +msgstr "Ø¥Ø¶Ø§ÙØ© خادم" + +#: src/FLTK/fl_callbacks.cpp:1176 +msgid "Edit Server" +msgstr "تعديل خادم" + +#: src/FLTK/fl_callbacks.cpp:1181 +msgid "Radio.co stations cannot be edited." +msgstr "محطات Radio.co لا يمكن تعديلها." + +#: src/FLTK/fl_callbacks.cpp:1267 +msgid "Add Server Infos" +msgstr "Ø¥Ø¶Ø§ÙØ© معلومات الخادم" + +#: src/FLTK/fl_callbacks.cpp:1302 +msgid "Song update failed: WebRTC does not support song names" +msgstr "ÙØ´Ù„ تحديث الأغنية: لا يدعم WebRTC أسماء الأغاني" + +#: src/FLTK/fl_callbacks.cpp:1345 +#, c-format +msgid "" +"Updated songname to:\n" +"%s\n" +msgstr "" +"تم تحديث اسم الأغنية إلى:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:1354 +msgid "Updating songname failed" +msgstr "ÙØ´Ù„ تحديث اسم الاغنية" + +#: src/FLTK/fl_callbacks.cpp:1428 +#, c-format +msgid "Audio buffer has been set to %d ms" +msgstr "تم ضبط المخزن الصوتي المؤقت على %d مللي ثانية" + +#: src/FLTK/fl_callbacks.cpp:1592 +msgid "" +"butt will open Radio.co in a new browser window.\n" +"\n" +"Login to Radio.co and allow butt access to your account." +msgstr "" +"Ø³ÙŠÙØªØ­ تطبيق butt موقع Radio.co ÙÙŠ Ù†Ø§ÙØ°Ø© Ù…ØªØµÙØ­ جديدة.\n" +"\n" +"قم بتسجيل الدخول إلى Radio.co واسمح لـ butt بالوصول إلى حسابك." + +#: src/FLTK/fl_callbacks.cpp:1618 +msgid "Hide" +msgstr "Ø§Ø®ÙØ§Ø¡" + +#: src/FLTK/fl_callbacks.cpp:1638 +msgid "Could not revoke trust for certificate" +msgstr "تعذر إلغاء الثقة للشهادة" + +#: src/FLTK/fl_callbacks.cpp:1862 +msgid "" +"The number of characters of all your icy names exeeds 1000\n" +"Please reduce the count of characters of each icy name" +msgstr "" +"يزيد عدد أحر٠جميع الأسماء Icy عن 1000 حرÙ\n" +"ÙŠÙØ±Ø¬Ù‰ تقليل عدد أحر٠كل اسم icy" + +#: src/FLTK/fl_callbacks.cpp:1868 src/FLTK/fl_callbacks.cpp:2557 +msgid "Newline characters and [];/\\ are not allowed within the icy name" +msgstr "لا يسمح بوجود أحر٠سطر جديد Ùˆ [];/\\ غير مسموح بها داخل الاسم icy" + +#: src/FLTK/fl_callbacks.cpp:1877 +msgid "Icy name already exist!" +msgstr "اسم icy موجود مسبقاً!" + +#: src/FLTK/fl_callbacks.cpp:2002 src/FLTK/fl_callbacks.cpp:2015 +#: src/FLTK/fl_callbacks.cpp:2029 src/FLTK/fl_callbacks.cpp:2044 +#: src/FLTK/fl_callbacks.cpp:2233 src/FLTK/fl_callbacks.cpp:2246 +#: src/FLTK/fl_callbacks.cpp:2260 src/FLTK/fl_callbacks.cpp:2275 +#: src/FLTK/fl_callbacks.cpp:2290 +msgid "" +"Warning:\n" +"The stream Sample-/Bitrate combination is invalid" +msgstr "" +"تحذير:\n" +"مجموعة عينة الدÙÙ‚-/معدل البت غير صالحة" + +#: src/FLTK/fl_callbacks.cpp:2008 src/FLTK/fl_callbacks.cpp:2021 +#: src/FLTK/fl_callbacks.cpp:2035 src/FLTK/fl_callbacks.cpp:2050 +msgid "The previous values have been set\n" +msgstr "تم تعيين القيم السابقة\n" + +#: src/FLTK/fl_callbacks.cpp:2056 +#, c-format +msgid "Stream bitrate set to: %dk" +msgstr "تم تعيين معدل بت البث إلى: %dk" + +#: src/FLTK/fl_callbacks.cpp:2142 src/FLTK/fl_callbacks.cpp:2155 +#: src/FLTK/fl_callbacks.cpp:2169 src/FLTK/fl_callbacks.cpp:2184 +#: src/FLTK/fl_callbacks.cpp:2313 src/FLTK/fl_callbacks.cpp:2326 +#: src/FLTK/fl_callbacks.cpp:2340 src/FLTK/fl_callbacks.cpp:2355 +#: src/FLTK/fl_callbacks.cpp:2369 +msgid "" +"Warning:\n" +"The record Sample-/Bitrate combination is invalid" +msgstr "" +"تحذير:\n" +"مجموعة عينة التسجل-/معدل البت غير صالحة" + +#: src/FLTK/fl_callbacks.cpp:2148 src/FLTK/fl_callbacks.cpp:2161 +#: src/FLTK/fl_callbacks.cpp:2175 src/FLTK/fl_callbacks.cpp:2190 +#: src/FLTK/fl_callbacks.cpp:2239 src/FLTK/fl_callbacks.cpp:2252 +#: src/FLTK/fl_callbacks.cpp:2266 src/FLTK/fl_callbacks.cpp:2281 +#: src/FLTK/fl_callbacks.cpp:2296 src/FLTK/fl_callbacks.cpp:2319 +#: src/FLTK/fl_callbacks.cpp:2332 src/FLTK/fl_callbacks.cpp:2346 +#: src/FLTK/fl_callbacks.cpp:2361 src/FLTK/fl_callbacks.cpp:2375 +msgid "The previous values have been set" +msgstr "تم تعيين القيم السابقة" + +#: src/FLTK/fl_callbacks.cpp:2196 +#, c-format +msgid "Record bitrate set to: %dk" +msgstr "تم تعيين معدل بت التسجيل الى: %dk" + +#: src/FLTK/fl_callbacks.cpp:2383 +#, c-format +msgid "Samplerate set to: %dHz" +msgstr "تم تعيين معدل أخذ العينات على: %dHz" + +#: src/FLTK/fl_callbacks.cpp:2449 +msgid "Channels set to: stereo" +msgstr "القنوات مضبوطة على: ستيريو" + +#: src/FLTK/fl_callbacks.cpp:2512 +msgid "Channels set to: mono" +msgstr "القنوات مضبوطة على: احادي" + +#: src/FLTK/fl_callbacks.cpp:2551 +msgid "" +"The number of characters of all your icy names exeeds 1000\n" +"Please reduce the number of characters of each icy name" +msgstr "" +"عدد أحر٠جميع الأسماء icy الخاصة بك يتجاوز 1000 حرÙ\n" +"ÙŠÙØ±Ø¬Ù‰ تقليل عدد أحر٠كل اسم icy" + +#: src/FLTK/fl_callbacks.cpp:2659 +msgid "Edit Server Infos" +msgstr "تعديل معلومات الخادم" + +#: src/FLTK/fl_callbacks.cpp:2696 src/FLTK/fl_callbacks.cpp:2749 +msgid "" +"Primary and secondary audio device are both ASIO devices.\n" +"You can not use two ASIO devices at the same time.\n" +"Please select a different device.\n" +msgstr "" +"جهاز الصوت الأساسي والثانوي كلاهما من أجهزة ASIO.\n" +"لا يمكنك استخدام جهازي ASIO ÙÙŠ Ù†ÙØ³ الوقت.\n" +"يرجى تحديد جهاز مختلÙ.\n" + +#: src/FLTK/fl_callbacks.cpp:2717 src/FLTK/fl_callbacks.cpp:4155 +msgid "" +"butt could not open selected audio device.\n" +"Please try another device.\n" +msgstr "" +"butt تعذر Ø¨ÙØªØ­ جهاز الصوت المحدد.\n" +"الرجاء تجربة جهاز آخر.\n" + +#: src/FLTK/fl_callbacks.cpp:2732 +#, c-format +msgid "" +"Primary device:\n" +"%s\n" +msgstr "" +"الجهاز الاساسي:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:2769 +msgid "" +"butt could not open secondary audio device.\n" +"Please try another device.\n" +msgstr "" +"butt تعذر Ø¨ÙØªØ­ جهاز الصوت الثانوي المحدد.\n" +"الرجاء تجربة جهاز آخر.\n" + +#: src/FLTK/fl_callbacks.cpp:2783 +#, c-format +msgid "" +"Secondary device:\n" +"%s\n" +msgstr "" +"الجهاز الثانوي:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:2894 src/FLTK/fl_callbacks.cpp:3072 +msgid "" +"MP3 encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"غير مدعوم تشÙير MP3 الحالي\n" +"تركيبة العينة-/معدل البت" + +#: src/FLTK/fl_callbacks.cpp:2915 +msgid "Stream codec set to mp3" +msgstr "ضبط ترميز البث على mp3" + +#: src/FLTK/fl_callbacks.cpp:2927 src/FLTK/fl_callbacks.cpp:3112 +msgid "" +"OGG Vorbis encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"غير مدعوم تشÙير OGG Vorbis الحالي\n" +"تركيبة العينة-/معدل البت" + +#: src/FLTK/fl_callbacks.cpp:2948 +msgid "Stream codec set to ogg/vorbis" +msgstr "ضبط ترميز البث على ogg/vorbis" + +#: src/FLTK/fl_callbacks.cpp:2959 src/FLTK/fl_callbacks.cpp:3151 +msgid "" +"Opus encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"غير مدعوم تشÙير Opus الحالي\n" +"تركيبة العينة-/معدل البت" + +#: src/FLTK/fl_callbacks.cpp:2979 +msgid "Stream codec set to opus" +msgstr "ضبط ترميز البث على opus" + +#: src/FLTK/fl_callbacks.cpp:3011 src/FLTK/fl_callbacks.cpp:3213 +msgid "" +"AAC encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"غير مدعوم تشÙير AAC الحالي\n" +"تركيبة العينة-/معدل البت" + +#: src/FLTK/fl_callbacks.cpp:3032 +msgid "Stream codec set to aac" +msgstr "ضبط ترميز البث على aac" + +#: src/FLTK/fl_callbacks.cpp:3042 src/FLTK/fl_callbacks.cpp:3252 +msgid "ERROR: While initializing flac settings" +msgstr "خطأ: أثناء تهيئة إعدادات FLAC" + +#: src/FLTK/fl_callbacks.cpp:3060 +msgid "Stream codec set to flac" +msgstr "ضبط ترميز البث على flac" + +#: src/FLTK/fl_callbacks.cpp:3101 +msgid "Record codec set to mp3" +msgstr "ضبط ترميز التسجيل على mp3" + +#: src/FLTK/fl_callbacks.cpp:3140 +msgid "Record codec set to ogg/vorbis" +msgstr "ضبط ترميز التسجيل على ogg/vorbis" + +#: src/FLTK/fl_callbacks.cpp:3179 +msgid "Record codec set to opus" +msgstr "ضبط ترميز التسجيل على opus" + +#: src/FLTK/fl_callbacks.cpp:3242 +msgid "Record codec set to aac" +msgstr "ضبط ترميز التسجيل على aac" + +#: src/FLTK/fl_callbacks.cpp:3278 +msgid "Record codec set to flac" +msgstr "ضبط ترميز التسجيل على flac" + +#: src/FLTK/fl_callbacks.cpp:3294 +msgid "Record codec set to wav" +msgstr "ضبط ترميز التسجيل على wav" + +#: src/FLTK/fl_callbacks.cpp:3329 +msgid "Select certificate file..." +msgstr "حدد مل٠الشهادة..." + +#: src/FLTK/fl_callbacks.cpp:3334 src/FLTK/fl_callbacks.cpp:3355 +#: src/FLTK/fl_callbacks.cpp:3466 src/FLTK/fl_callbacks.cpp:3556 +#: src/FLTK/fl_callbacks.cpp:4109 src/FLTK/fl_callbacks.cpp:4133 +#: src/FLTK/fl_callbacks.cpp:4257 +#, c-format +msgid "ERROR: %s" +msgstr "خطأ: %s" + +#: src/FLTK/fl_callbacks.cpp:3347 +msgid "Select certificate directory..." +msgstr "حدد مجلد الشهادة..." + +#: src/FLTK/fl_callbacks.cpp:3458 +msgid "Record to..." +msgstr "تسجيل الى..." + +#: src/FLTK/fl_callbacks.cpp:3483 +msgid "File splitting only works if recording is active." +msgstr "لا يعمل تقسيم Ø§Ù„Ù…Ù„ÙØ§Øª إلا إذا كان التسجيل نشطاً." + +#: src/FLTK/fl_callbacks.cpp:3552 +msgid "Select Songfile" +msgstr "حدد مل٠الاغنية" + +#: src/FLTK/fl_callbacks.cpp:3657 +msgid "Gain control is disabled. Enable in Settings->GUI" +msgstr "تم تعطيل التحكم ÙÙŠ المستوى. تمكين من الإعدادات->GUI" + +#: src/FLTK/fl_callbacks.cpp:3718 +msgid "select background color" +msgstr "حدد لون الخلÙية" + +#: src/FLTK/fl_callbacks.cpp:3728 +msgid "select text color" +msgstr "حدد لون النص" + +#: src/FLTK/fl_callbacks.cpp:3761 src/FLTK/fl_callbacks.cpp:3765 +#: src/FLTK/fl_callbacks.cpp:3774 src/FLTK/fl_callbacks.cpp:3778 +msgid "Value must be a number between -54 and 0" +msgstr "يجب أن تكون القيمة رقمًا يتراوح بين -54.0 Ùˆ 0" + +#: src/FLTK/fl_callbacks.cpp:3788 +msgid "Please restart butt to apply new language." +msgstr "الرجاء إعادة تشغيل butt لضبط اللغة الجديدة." + +#: src/FLTK/fl_callbacks.cpp:3867 src/FLTK/fl_callbacks.cpp:3872 +#: src/FLTK/fl_callbacks.cpp:3882 src/FLTK/fl_callbacks.cpp:3887 +msgid "Value must be a number between -90.0 and 0" +msgstr "يجب أن تكون القيمة رقمًا يتراوح بين -90.0 Ùˆ 0" + +#: src/FLTK/fl_callbacks.cpp:4082 +msgid "Recording volume" +msgstr "مستوى التسجيل" + +#: src/FLTK/fl_callbacks.cpp:4103 +msgid "Export to..." +msgstr "تصدير الى..." + +#: src/FLTK/fl_callbacks.cpp:4146 +#, c-format +msgid "Could not import config %s" +msgstr "تعذر استيراد التكوين %s" + +#: src/FLTK/fl_callbacks.cpp:4160 +#, c-format +msgid "Config imported %s" +msgstr "التكوين المستورد %s" + +#: src/FLTK/fl_callbacks.cpp:4234 +msgid "" +"Could not get update information.\n" +"Reason: Network error" +msgstr "" +"تعذر الحصول على معلومات التحديث.\n" +"السبب: خطأ ÙÙŠ الشبكة" + +#: src/FLTK/fl_callbacks.cpp:4237 +msgid "" +"Could not get update information.\n" +"Reason: Unknown answer from server" +msgstr "" +"تعذر الحصول على معلومات التحديث.\n" +"السبب: إجابة غير Ù…Ø¹Ø±ÙˆÙØ© من الخادم" + +#: src/FLTK/fl_callbacks.cpp:4240 +msgid "You have the latest version!" +msgstr "لديك أحدث إصدار!" + +#: src/FLTK/fl_callbacks.cpp:4243 +msgid "" +"Could not get update information.\n" +"Reason: Unknown" +msgstr "" +"تعذر الحصول على معلومات التحديث.\n" +"السبب: غير معروÙ" + +#: src/FLTK/fl_callbacks.cpp:4251 +msgid "Select logfile..." +msgstr "حدد مل٠السجل..." + +#: src/FLTK/fl_callbacks.cpp:4273 +msgid "" +"butt is currently streaming.\n" +"Do you really want to close butt now?" +msgstr "" +"butt يبث حالياً.\n" +"هل تريد حقاً إغلاق butt الآن؟" + +#: src/FLTK/fl_callbacks.cpp:4279 +msgid "" +"butt is currently recording.\n" +"Do you really want to close butt now?" +msgstr "" +"butt يسجل حالياً.\n" +"هل تريد حقاً إغلاق butt الآن؟" + +#: src/FLTK/fl_callbacks.cpp:4354 +msgid "The URL must start with either http:// or https://" +msgstr "يجب أن يبدأ عنوان URL إما ب http:// أو https://" + +#: src/FLTK/fl_callbacks.cpp:4366 +msgid "Value must be a number between 1 and 1000" +msgstr "يجب أن تكون القيمة رقمًا يتراوح بين 1 Ùˆ 1000" + +#: src/FLTK/fl_callbacks.cpp:5228 src/FLTK/fl_callbacks.cpp:5263 +#: src/FLTK/fl_callbacks.cpp:5298 src/FLTK/fl_callbacks.cpp:5333 +#: src/FLTK/fl_callbacks.cpp:5368 src/FLTK/fl_callbacks.cpp:5859 +#: src/FLTK/fl_callbacks.cpp:5894 src/FLTK/fl_callbacks.cpp:5929 +#: src/FLTK/fl_callbacks.cpp:5964 src/FLTK/fl_callbacks.cpp:5999 +msgid "The encoder could not be initialized with the provided parameters." +msgstr "تعذرت تهيئة Ø§Ù„Ù…Ø´ÙØ± باستخدام المعلمات Ø§Ù„Ù…ØªÙˆÙØ±Ø©." + +#: src/FLTK/fl_callbacks.cpp:5246 src/FLTK/fl_callbacks.cpp:5877 +msgid "The value must be between 0.001 kHz and 50 kHz" +msgstr "يجب أن تتراوح القيمة بين 0.001 كيلوهرتز Ùˆ50 كيلوهرتز" + +#: src/FLTK/fl_callbacks.cpp:5281 src/FLTK/fl_callbacks.cpp:5316 +#: src/FLTK/fl_callbacks.cpp:5351 src/FLTK/fl_callbacks.cpp:5912 +#: src/FLTK/fl_callbacks.cpp:5947 src/FLTK/fl_callbacks.cpp:5982 +msgid "The value must be between 0.001 kHz and 16 kHz" +msgstr "يجب أن تكون القيمة بين 0.001 كيلوهرتز Ùˆ16 كيلوهرتز" + +#: src/FLTK/fl_callbacks.cpp:6328 +msgid "MIDI device could not be opened." +msgstr "تعذر ÙØªØ­ جهاز MIDI." + +#: src/FLTK/fl_callbacks.cpp:6334 +#, c-format +msgid "" +"MIDI device:\n" +"%s\n" +msgstr "" +"جهاز MIDI:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:6339 +msgid "MIDI device could not be started." +msgstr "تعذر بدء تشغيل جهاز MIDI." + +#: src/FLTK/fl_callbacks.cpp:6344 +msgid "MIDI support disabled\n" +msgstr "تم تعطيل دعم MIDI\n" + +#: src/FLTK/fl_callbacks.cpp:6406 +msgid "The CC value must be between 0 and 127" +msgstr "يجب أن تكون قيمة CC بين 0 Ùˆ127" + +#: src/FLTK/fl_callbacks.cpp:6429 +msgid "Waiting..." +msgstr "ÙÙŠ الانتظار..." + +#: src/FLTK/fl_funcs.cpp:193 +msgid "Disabled" +msgstr "تعطيل" + +#: src/FLTK/fl_funcs.cpp:335 +#, c-format +msgid "%d seconds" +msgstr "%d ثانية" + +#: src/FLTK/fl_funcs.cpp:386 +msgid "Not supported on Windows" +msgstr "غير مدعوم على نظام Windows" + +#: src/FLTK/fl_funcs.cpp:808 +msgid "Start/Stop broadcasting" +msgstr "بدء/إيقا٠البث" + +#: src/FLTK/fl_funcs.cpp:809 +msgid "Start/Stop recording" +msgstr "بدء/إيقا٠التسجيل" + +#: src/FLTK/fl_funcs.cpp:811 +msgid "Streaming Gain" +msgstr "مستوى البث" + +#: src/FLTK/fl_funcs.cpp:812 +msgid "Recording Gain" +msgstr "مستوى التسجيل" + +#: src/FLTK/fl_funcs.cpp:813 +msgid "Primary Device Gain" +msgstr "الجهاز الاساسي" + +#: src/FLTK/fl_funcs.cpp:814 +msgid "Secondary Device Gain" +msgstr "الجهاز الثانوي" + +#: src/FLTK/fl_funcs.cpp:815 +msgid "Cross fader" +msgstr "Ø§Ù„Ø®Ø§ÙØ¶ المتقاطع" + +#: src/FLTK/fl_funcs.cpp:816 +msgid "Mute/Unmute Primary Device" +msgstr "كتم/إلغاء كتم صوت الجهاز الأساسي" + +#: src/FLTK/fl_funcs.cpp:817 +msgid "Mute/Unmute Secondary Device" +msgstr "كتم/إلغاء كتم صوت الجهاز الثانوي" + +#: src/FLTK/fl_funcs.cpp:818 +msgid "Start broadcasting" +msgstr "بدء البث" + +#: src/FLTK/fl_funcs.cpp:819 +msgid "Stop broadcasting" +msgstr "إيقا٠البث" + +#: src/FLTK/fl_funcs.cpp:820 +msgid "Start recording" +msgstr "بدء التسجيل" + +#: src/FLTK/fl_funcs.cpp:821 +msgid "Stop recording" +msgstr "إيقا٠التسجيل" + +#: src/FLTK/fl_funcs.cpp:870 +msgid "dev. not supported" +msgstr "التطوير. غير مدعوم" + +#: src/FLTK/fl_funcs.cpp:1087 +#, c-format +msgid "" +"Could not create recording folder:\n" +"%s\n" +"Please make sure the folder contains only valid format specifiers." +msgstr "" +"تعذر إنشاء مجلد التسجيل:\n" +"%s\n" +"الرجاء التأكد من احتواء المجلد على Ù…ÙˆØ§ØµÙØ§Øª تنسيق صالحة Ùقط." + +#: src/FLTK/fl_funcs.cpp:1102 +#, c-format +msgid "Could not create recording folder %s\n" +msgstr "تعذر إنشاء مجلد التسجيل %s\n" + +#: src/FLTK/fl_funcs.cpp:1111 +#, c-format +msgid "" +"Could not create recording file:\n" +"%s\n" +"Please make sure the filename contains only valid format specifiers." +msgstr "" +"تعذر إنشاء مل٠التسجيل:\n" +"%s\n" +"الرجاء التأكد من احتواء اسم المل٠على Ù…ÙˆØ§ØµÙØ§Øª تنسيق صالحة Ùقط." + +#: src/FLTK/fl_funcs.cpp:1157 +msgid "Could not find a valid filename" +msgstr "تعذر العثور على اسم مل٠صحيح" + +#: src/FLTK/fl_funcs.cpp:1462 +msgid "TRUST" +msgstr "توثيق" + +#: src/icecast.cpp:90 +msgid "" +"\n" +"connect: Could not create network socket" +msgstr "" +"\n" +"اتصال: تعذر إنشاء مقبس الشبكة" + +#: src/icecast.cpp:102 +msgid "" +"\n" +"connect: Error resolving server address" +msgstr "" +"\n" +"اتصال: خطأ ÙÙŠ حل عنوان الخادم" + +#: src/icecast.cpp:142 +msgid "" +"\n" +"connect: SSL connection timed out. Trying again..." +msgstr "" +"\n" +"اتصال: انتهت مهلة اتصال SSL. جاري المحاولة مرة أخرى..." + +#: src/icecast.cpp:149 +#, c-format +msgid "" +"SSL/TLS certificate verification failed\n" +"Reason: %s\n" +"\n" +"Do you still want to trust this certificate?\n" +"Trusting will be permanent and can be revoked\n" +"in the server settings." +msgstr "" +"ÙØ´Ù„ التحقق من شهادة SSL/TLS\n" +"السبب: %s\n" +"\n" +"هل ما زلت تريد الوثوق بهذه الشهادة؟\n" +"ستكون الثقة دائمة ويمكن إبطالها\n" +"ÙÙŠ إعدادات الخادم." + +#: src/icecast.cpp:164 +#, c-format +msgid "" +"\n" +"connect: SSL connection failed\n" +"Reason: %s" +msgstr "" +"\n" +"اتصال: ÙØ´Ù„ اتصال SSL\n" +"السبب: %s" + +#: src/icecast.cpp:320 +msgid "" +"\n" +"connect: connection timed out. Trying again..." +msgstr "" +"\n" +"الاتصال: انتهت مهلة الاتصال. المحاولة مرة أخرى..." + +#: src/icecast.cpp:373 +msgid "" +"\n" +"connect: server answered with 400!\n" +msgstr "" +"\n" +"الاتصال: تم الرد على الخادم بـ 400!\n" + +#: src/icecast.cpp:379 +msgid "" +"\n" +"connect: invalid user/password!\n" +msgstr "" +"\n" +"اتصال: مستخدم/كلمة مرور غير صالحة!\n" + +#: src/icecast.cpp:402 +msgid "" +"\n" +"connect: server answered with 404!\n" +msgstr "" +"\n" +"الاتصال: تم الرد على الخادم بـ 404!\n" + +#: src/icecast.cpp:409 +#, c-format +msgid "" +"\n" +"connect: server answered with %d!\n" +msgstr "" +"\n" +"الاتصال: تم الرد على الخادم بـ %d!\n" + +#: src/icecast.cpp:434 +msgid "" +"\n" +"ERROR: Opus is not supported by your\n" +"Icecast server (>=1.4.0 required)!\n" +msgstr "" +"\n" +"خطأ: Opus غير مدعوم من قبل\n" +"خادم Icecast (>=1.4.0 مطلوب)!\n" + +#: src/icecast.cpp:507 +msgid "" +"\n" +"update_song: could not create network socket" +msgstr "" +"\n" +"تحديث_الأغنية: تعذر إنشاء مقبس الشبكة" + +#: src/icecast.cpp:511 +msgid "" +"\n" +"update_song: error resolving server address" +msgstr "" +"\n" +"تحديث_الأغنية: خطأ ÙÙŠ حل عنوان الخادم" + +#: src/lame_encode.cpp:74 +#, c-format +msgid "unable to init lame params %d" +msgstr "تعذر تهيئة معلمات lame %d" + +#: src/port_audio.cpp:131 +#, c-format +msgid "" +"PortAudio init failed:\n" +"%s\n" +msgstr "" +"ÙØ´Ù„ت عملية بدء تشغيل PortAudio:\n" +"%s\n" + +#: src/port_audio.cpp:180 +msgid "ERROR: no sound device with input channels found" +msgstr "خطأ: لم يتم العثور على جهاز صوت به قنوات إدخال" + +#: src/port_audio.cpp:198 src/port_audio.cpp:289 src/port_audio.cpp:1331 +#: src/port_midi.cpp:177 +#, c-format +msgid "Error getting device Info (%d)" +msgstr "خطأ ÙÙŠ الحصول على معلومات الجهاز (%d)" + +#: src/port_audio.cpp:241 +#, c-format +msgid "" +"Samplerate not supported: %dHz\n" +"Using default samplerate: %dHz" +msgstr "" +"معدل أخذ العينات غير معتمد: %dHz\n" +"استخدام معدل أخذ العينات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ: %dHz" + +#: src/port_audio.cpp:258 src/port_audio.cpp:360 +#, c-format +msgid "PA: Format not supported: %s\n" +msgstr "PA: التنسيق غير معتمد: %s\n" + +#: src/port_audio.cpp:268 +#, c-format +msgid "error opening sound device: %s" +msgstr "خطأ ÙÙŠ ÙØªØ­ جهاز الصوت: %s" + +#: src/port_audio.cpp:326 +msgid "The selected secondary audio device can not be used" +msgstr "لا يمكن استخدام جهاز الصوت الثانوي المحدد" + +#: src/port_audio.cpp:343 src/port_audio.cpp:1452 src/port_audio.cpp:1469 +msgid "ERROR: Could not initialize samplerate converter" +msgstr "خطأ: تعذر تهيئة محول العينات" + +#: src/port_audio.cpp:354 +#, c-format +msgid "Samplerate of secondary device is resampled from %dHz to %dHz\n" +msgstr "تمت إعادة معايرة معدل العينات للجهاز الثانوي من %dHz إلى %dHz\n" + +#: src/port_audio.cpp:381 +#, c-format +msgid "error opening secondary sound device: %s" +msgstr "خطأ ÙÙŠ ÙØªØ­ جهاز الصوت الثانوي: %s" + +#: src/port_audio.cpp:921 +msgid "disconnected\n" +msgstr "غير متصل\n" + +#: src/port_audio.cpp:949 +msgid "recording stopped" +msgstr "توق٠التسجيل" + +#: src/port_midi.cpp:152 src/port_midi.cpp:211 src/port_midi.cpp:233 +#: src/port_midi.cpp:255 src/port_midi.cpp:282 src/port_midi.cpp:301 +#: src/port_midi.cpp:316 src/port_midi.cpp:341 src/port_midi.cpp:352 +msgid "Error: PortMidi was not initialized." +msgstr "خطأ: لم تتم تهيئة PortMidi." + +#: src/port_midi.cpp:262 +#, c-format +msgid "" +"Error: MIDI device %s could not be opened because no MIDI devices were found." +msgstr "خطأ: تعذر ÙØªØ­ جهاز MIDI %s لأنه لم يتم العثور على أجهزة MIDI." + +#: src/port_midi.cpp:269 +#, c-format +msgid "Error: MIDI device %s could not be found." +msgstr "خطأ: تعذر العثور على جهاز MIDI %s." + +#: src/port_midi.cpp:286 +msgid "Error: MIDI thread already active." +msgstr "خطأ: مؤشر ترابط MIDI نشط Ø¨Ø§Ù„ÙØ¹Ù„." + +#: src/port_midi.cpp:291 +msgid "Error: Could not start MIDI thread." +msgstr "خطأ: تعذر بدء مؤشر ترابط MIDI." + +#: src/shoutcast.cpp:80 +msgid "" +"\n" +"Connect: Could not create network socket" +msgstr "" +"\n" +"اتصال: تعذر إنشاء مقبس الشبكة" + +#: src/shoutcast.cpp:92 +msgid "" +"\n" +"Connect: Error resolving server address" +msgstr "" +"\n" +"اتصال: خطأ ÙÙŠ حل عنوان الخادم" + +#: src/shoutcast.cpp:172 +msgid "" +"\n" +"connect: connection timed out. Trying again...\n" +msgstr "" +"\n" +"الاتصال: انتهت مهلة الاتصال. المحاولة مرة أخرى...\n" + +#: src/shoutcast.cpp:189 +msgid "" +"\n" +"Connect: Invalid password!\n" +msgstr "" +"\n" +"اتصال: كلمة المرور غير صالحة!\n" + +#: src/shoutcast.cpp:238 +msgid "" +"\n" +"Update song: Could not create network socket" +msgstr "" +"\n" +"تحديث الأغنية: تعذر إنشاء مقبس الشبكة" + +#: src/shoutcast.cpp:242 +msgid "" +"\n" +"Update song: Error resolving server address" +msgstr "" +"\n" +"تحديث الأغنية: خطأ ÙÙŠ حل عنوان الخادم" + +#: src/tls.cpp:159 +msgid "check_host: could not read host name from cert" +msgstr "check_host: تعذر قراءة اسم المضي٠من الشهادة" + +#: src/tls.cpp:194 +msgid "check_cert: No peer certificate available" +msgstr "check_cert: لا توجد شهادة نظير Ù…ØªÙˆÙØ±Ø©" + +#: src/tls.cpp:207 +msgid "check_cert: X509_check_host failed" +msgstr "check_cert: ÙØ´Ù„ X509_تحقق_مضي٠X509" + +#: src/tls.cpp:213 +msgid "check_cert: check_host failed" +msgstr "check_cert: ÙØ´Ù„ التحقق_من_المضيÙ" + +#: src/tls.cpp:229 +msgid "calc_cert_hash: No peer certificate available" +msgstr "calc_cert_hash: لا توجد شهادة نظير Ù…ØªÙˆÙØ±Ø©" + +#: src/tls.cpp:236 +msgid "calc_cert_hash: Hash calculation failed" +msgstr "calc_cert_hash: ÙØ´Ù„ حساب التجزئة" + +#: src/tls.cpp:305 +msgid "tls_setup: Could not set cipher list" +msgstr "tls_setup: تعذر تعيين قائمة Ø§Ù„Ø´ÙØ±Ø§Øª" + +#: src/tls.cpp:318 +msgid "tls_setup: SSL_new failed" +msgstr "tls_setup: ÙØ´Ù„ SSL_new" + +#: src/tls.cpp:324 +msgid "tls_setup: Could not bind socket to SSL" +msgstr "tls_setup: تعذر ربط المقبس ب SSL" + +#: src/tls.cpp:338 +msgid "tls_setup: SSL_connect read timeout" +msgstr "tls_setup: مهلة قراءة SSL_connect انتهت" + +#: src/tls.cpp:344 +msgid "tls_setup: SSL_connect write timeout" +msgstr "tls_setup: مهلة كتابة SSL_connect انتهت" + +#: src/tls.cpp:361 +msgid "tls_setup: Cert hash could not be calculated" +msgstr "tls_setup: تعذر حساب تجزئة الشهادة" + +#: src/tls.cpp:385 +msgid "tls_send: read timeout" +msgstr "tls_send: مهلة القراءة انتهت" + +#: src/tls.cpp:392 +msgid "tls_send: write timeout" +msgstr "tls_send: مهلة الكتابة انتهت" + +#: src/tls.cpp:418 +msgid "tls_recv: read timeout" +msgstr "tls_recv: مهلة القراءة انتهت" + +#: src/tls.cpp:425 +msgid "tls_recv: write timeout" +msgstr "tls_recv: مهلة الكتابة انتهت" + +#~ msgid "Listeners: 99999" +#~ msgstr "المستمعين: 99999" + +#~ msgid "Resample output" +#~ msgstr "جودة إعادة العينة" + +#~ msgid "Resample output to selected sample rate" +#~ msgstr "حدد معدل عينة الإدخال" + +#, c-format +#~ msgid "" +#~ "error while parsing config. Missing WebRTC WHIP URL entry for server " +#~ "\"%s\".\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "خطأ أثناء تحليل التكوين. إدخال عنوان WebRTC WHIP Ù…Ùقود للخادم \"%s\".\n" +#~ "سيبدأ butt بالإعدادات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©" + +#, c-format +#~ msgid "" +#~ "error while parsing config. Missing WebRTC ICE server entry for server " +#~ "\"%s\".\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "خطأ أثناء تحليل التكوين. إدخال Ø§Ù„Ù…Ù†ÙØ° Ù…Ùقود للخادم \"%s\".\n" +#~ "سيبدأ butt بالإعدادات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©" + +#~ msgid "No ICE server specified" +#~ msgstr "لم يتم تحديد اسم" + +#~ msgid "Preset " +#~ msgstr "مضبوط مسبقاً " + +#~ msgid "Text color" +#~ msgstr "لون الكتابة" + +#~ msgid "Volume of Primary Device" +#~ msgstr "حجم صوت الجهاز الاساسي" + +#~ msgid "Volume of Secondary Device" +#~ msgstr "حجم صوت الجهاز الثانوي" diff --git a/po/boldquot.sed b/po/boldquot.sed new file mode 100644 index 0000000..4b937aa --- /dev/null +++ b/po/boldquot.sed @@ -0,0 +1,10 @@ +s/"\([^"]*\)"/“\1â€/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“â€/""/g +s/“/“/g +s/â€/â€/g +s/‘/‘/g +s/’/’/g diff --git a/po/butt.pot b/po/butt.pot new file mode 100644 index 0000000..33b2765 --- /dev/null +++ b/po/butt.pot @@ -0,0 +1,2867 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Daniel Nöthen +# This file is distributed under the same license as the butt package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: butt 1.45.0\n" +"Report-Msgid-Bugs-To: butt@danielnoethen.de\n" +"POT-Creation-Date: 2025-04-19 14:55+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/AskForMicPermission.m:20 +msgid "Microphone access" +msgstr "" + +#: src/AskForMicPermission.m:21 +msgid "" +"butt needs access to your microphone.\n" +"\n" +"Please go to\n" +"System Preferences->Privacy & Security->Microphone\n" +"and activate the check mark next to the butt entry." +msgstr "" + +#: src/butt.cpp:219 +msgid "No home-directory found" +msgstr "" + +#: src/butt.cpp:230 +#, c-format +msgid "" +"The shift key was held down during startup.\n" +"Do you want to start butt with a new configuration file?\n" +"This will overwrite your existing configuration file at\n" +"%s" +msgstr "" + +#: src/butt.cpp:233 +msgid "Start with old" +msgstr "" + +#: src/butt.cpp:233 +msgid "Start with new" +msgstr "" + +#: src/butt.cpp:236 src/butt.cpp:253 +#, c-format +msgid "" +"Could not create config %s\n" +"butt is going to close now" +msgstr "" + +#: src/butt.cpp:242 +#, c-format +msgid "Reading config %s\n" +msgstr "" + +#: src/butt.cpp:250 +#, c-format +msgid "Could not find config %s\n" +msgstr "" + +#: src/butt.cpp:257 +#, c-format +msgid "" +"butt created a default config at\n" +"%s\n" +msgstr "" + +#: src/butt.cpp:265 +msgid "" +"Could not find any audio device with input channels.\n" +"butt requires at least one audio device with input channels in order to " +"work.\n" +"This can either be a built-in audio device, an external audio device or a " +"virtual audio device.\n" +"\n" +"butt is going to close now." +msgstr "" + +#: src/butt.cpp:358 +#, c-format +msgid "Illegal argument: Threshold must be a non-negative number\n" +msgstr "" + +#: src/butt.cpp:382 +#, c-format +msgid "%c threshold set to %0.1f\n" +msgstr "" + +#: src/butt.cpp:464 +#, c-format +msgid "Illegal argument: Port must be a number between 1023 and 65535\n" +msgstr "" + +#: src/butt.cpp:472 src/butt.cpp:482 src/butt.cpp:489 src/butt.cpp:496 +#: src/butt.cpp:503 src/butt.cpp:510 src/butt.cpp:521 src/butt.cpp:540 +#: src/butt.cpp:550 src/butt.cpp:597 +#, c-format +msgid "" +"Warning: You may only pass one control option. Option -%c has been ignored.\n" +msgstr "" + +#: src/butt.cpp:559 +#, c-format +msgid "" +"\n" +"Options:\n" +"-h\tPrint this help text\n" +"-v\tPrint version information\n" +msgstr "" + +#: src/butt.cpp:563 +#, c-format +msgid "" +"\n" +"Options for operating mode:\n" +"-c\tPath to configuration file\n" +"-L\tPrint available audio devices\n" +"-A\tCommand server will be accessible from your network/internet (default: " +"localhost only)\n" +"-U\tCommand server will use UDP instead of TCP\n" +"-x\tDo not start a command server\n" +"-p\tPort where the command server shall listen to (default: 1256)\n" +msgstr "" + +#: src/butt.cpp:572 +#, c-format +msgid "" +"\n" +"Options for control mode:\n" +"-s\tConnect to streaming server\n" +"-d\tDisconnect from streaming server\n" +"-r\tStart recording\n" +"-t\tStop recording\n" +"-n\tSplit recording\n" +"-q\tQuit butt\n" +"-u\tupdate song name\n" +"-S\tRequest status\n" +"-M\tSet streaming signal threshold (seconds)\n" +"-m\tSet streaming silence threshold (seconds)\n" +"-O\tSet recording signal threshold (seconds)\n" +"-o\tSet recording silence threshold (seconds)\n" +"-U\tConnect via UDP instead of TCP\n" +"-a\tAddress of the butt instance to be controlled (default: 127.0.0.1)\n" +"-p\tPort of the butt instance to be controlled (default: 1256)\n" +msgstr "" + +#: src/butt.cpp:591 +#, c-format +msgid "" +"Illegal option -%c.\n" +"Type butt -h to get a list of supported options.\n" +msgstr "" + +#: src/butt.cpp:603 +#, c-format +msgid "Option -%c requires an argument\n" +msgstr "" + +#: src/butt.cpp:607 +#, c-format +msgid "Command line parsing failed\n" +msgstr "" + +#: src/butt.cpp:630 +#, c-format +msgid "No butt instance running on %s at port %d\n" +msgstr "" + +#: src/butt.cpp:635 +#, c-format +msgid "Error while sending command\n" +msgstr "" + +#: src/butt.cpp:640 +#, c-format +msgid "Error: Did not receive response packet\n" +msgstr "" + +#: src/butt.cpp:653 +#, c-format +msgid "Error: You may only request one status packet per second\n" +msgstr "" + +#: src/butt.cpp:657 +#, c-format +msgid "Error: Did not receive status packet (UDP server not running?)\n" +msgstr "" + +#: src/butt.cpp:661 +#, c-format +msgid "Network error while receiving status packet: %d\n" +msgstr "" + +#: src/butt.cpp:665 +#, c-format +msgid "Error: Client and server versions do not match\n" +msgstr "" + +#: src/butt.cpp:676 +#, c-format +msgid "" +"connected: %d\n" +"connecting: %d\n" +"recording: %d\n" +"signal present: %d\n" +"signal absent: %d\n" +msgstr "" + +#: src/butt.cpp:681 +#, c-format +msgid "stream seconds: %lu\n" +msgstr "" + +#: src/butt.cpp:682 +#, c-format +msgid "stream kBytes: %lu\n" +msgstr "" + +#: src/butt.cpp:683 +#, c-format +msgid "record seconds: %lu\n" +msgstr "" + +#: src/butt.cpp:684 +#, c-format +msgid "record kBytes: %lu\n" +msgstr "" + +#: src/butt.cpp:685 +#, c-format +msgid "volume left: %0.1f\n" +msgstr "" + +#: src/butt.cpp:686 +#, c-format +msgid "volume right: %0.1f\n" +msgstr "" + +#: src/butt.cpp:687 +#, c-format +msgid "song: %s\n" +msgstr "" + +#: src/butt.cpp:688 +#, c-format +msgid "record path: %s\n" +msgstr "" + +#: src/butt.cpp:689 +#, c-format +msgid "listeners: %d\n" +msgstr "" + +#: src/butt.cpp:703 +msgid "" +"The control key was held down during startup.\n" +"butt will start without opening an audio device.\n" +"Please select your preferred audio device in settings->audio" +msgstr "" + +#: src/butt.cpp:712 +msgid "" +"PortAudio init failed\n" +"butt is going to close now" +msgstr "" + +#: src/butt.cpp:747 src/FLTK/fl_timer_funcs.cpp:476 +#: src/FLTK/fl_callbacks.cpp:123 src/FLTK/fl_callbacks.cpp:899 +#: src/FLTK/fl_callbacks.cpp:977 src/FLTK/fl_funcs.cpp:1047 +msgid "idle" +msgstr "" + +#: src/butt.cpp:780 +#, c-format +msgid "" +"Starting %s\n" +"Written by Daniel Nöthen\n" +"iPhone/iPad client: https://izicast.de\n" +"Donate: paypal@danielnoethen.de\n" +msgstr "" + +#: src/butt.cpp:792 src/butt.cpp:793 src/cfg.cpp:577 src/port_audio.cpp:1314 +#: src/port_audio.cpp:1315 +msgid "Default PCM device (default)" +msgstr "" + +#: src/butt.cpp:796 src/butt.cpp:797 src/cfg.cpp:578 +#: src/FLTK/fl_callbacks.cpp:2820 src/FLTK/fl_funcs.cpp:227 +msgid "None" +msgstr "" + +#: src/butt.cpp:800 +msgid "" +"Could not open audio device.\n" +"Please select your preferred audio device in settings->audio" +msgstr "" + +#: src/butt.cpp:803 +msgid "" +"butt could not open previously used audio device.\n" +"The system default audio device will be used.\n" +msgstr "" + +#: src/butt.cpp:830 +#, c-format +msgid "Command server listening on port %d\n" +msgstr "" + +#: src/butt.cpp:837 +#, c-format +msgid "Warning: could not start command server on port %d\n" +msgstr "" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:4225 +#, c-format +msgid "" +"New version available: %s\n" +"You have version %s" +msgstr "" + +#: src/butt.cpp:853 +msgid "Don't ask again" +msgstr "" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:1594 +#: src/FLTK/fl_callbacks.cpp:4225 +msgid "Cancel" +msgstr "" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:4225 +msgid "Get new version" +msgstr "" + +#: src/butt.cpp:874 +#, c-format +msgid "Could not initialize PortMidi: %s" +msgstr "" + +#: src/butt.cpp:902 +msgid "butt was built without WebRTC support" +msgstr "" + +#: src/cfg.cpp:55 +#, c-format +msgid "Could not write to file: %s" +msgstr "" + +#: src/cfg.cpp:550 +#, c-format +msgid "Config written to %s" +msgstr "" + +#: src/cfg.cpp:674 +msgid "" +"error while parsing config. Missing main/server entry.\n" +"butt will start with default settings" +msgstr "" + +#: src/cfg.cpp:680 +msgid "" +"error while parsing config. Missing main/srv_ent entry.\n" +"butt will start with default settings" +msgstr "" + +#: src/cfg.cpp:699 +#, c-format +msgid "" +"error while parsing config. Missing type entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" + +#: src/cfg.cpp:707 +#, c-format +msgid "" +"error while parsing config. Missing address entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" + +#: src/cfg.cpp:716 +#, c-format +msgid "" +"error while parsing config. Missing port entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" + +#: src/cfg.cpp:725 +#, c-format +msgid "" +"error while parsing config. Missing password entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" + +#: src/cfg.cpp:734 +#, c-format +msgid "" +"error while parsing config. Missing mount entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" + +#: src/cfg.cpp:790 +msgid "" +"error while parsing config. Missing main/icy entry.\n" +"butt will start with default settings" +msgstr "" + +#: src/cfg.cpp:795 +msgid "" +"error while parsing config. Missing main/icy_ent entry.\n" +"butt will start with default settings" +msgstr "" + +#: src/cfg.cpp:821 +#, c-format +msgid "" +"error while parsing config. Missing pub entry for icy \"%s\".\n" +"butt will start with default settings" +msgstr "" + +#: src/FLTK/flgui.cpp:3088 +msgid "Bitcoin address has been copied to clipboard." +msgstr "" + +#: src/FLTK/flgui.cpp:3099 +msgid "Litecoin address has been copied to clipboard." +msgstr "" + +#: src/FLTK/flgui.cpp:3110 +msgid "Monero address has been copied to clipboard." +msgstr "" + +#: src/FLTK/flgui.cpp:4041 +msgid "press left mouse to toggle lcd info" +msgstr "" + +#: src/FLTK/flgui.cpp:4053 src/FLTK/fl_callbacks.cpp:4078 +msgid "Streaming volume" +msgstr "" + +#: src/FLTK/flgui.cpp:4057 +msgid "Mixer" +msgstr "" + +#: src/FLTK/flgui.cpp:4058 +msgid "show/hide mixer window" +msgstr "" + +#: src/FLTK/flgui.cpp:4065 +msgid "@circle" +msgstr "" + +#: src/FLTK/flgui.cpp:4066 +msgid "start/stop recording" +msgstr "" + +#: src/FLTK/flgui.cpp:4077 +msgid "@square" +msgstr "" + +#: src/FLTK/flgui.cpp:4078 +msgid "disconnect from server" +msgstr "" + +#: src/FLTK/flgui.cpp:4089 +msgid "@>" +msgstr "" + +#: src/FLTK/flgui.cpp:4090 +msgid "connect to server" +msgstr "" + +#: src/FLTK/flgui.cpp:4106 src/FLTK/flgui.cpp:4438 src/FLTK/flgui.cpp:4657 +#: src/FLTK/fl_callbacks.cpp:4077 +msgid "Streaming" +msgstr "" + +#: src/FLTK/flgui.cpp:4110 src/FLTK/flgui.cpp:4469 src/FLTK/flgui.cpp:4771 +msgid "Recording" +msgstr "" + +#: src/FLTK/flgui.cpp:4140 +msgid "Settings" +msgstr "" + +#: src/FLTK/flgui.cpp:4141 +msgid "show/hide config window" +msgstr "" + +#: src/FLTK/flgui.cpp:4148 src/FLTK/fl_callbacks.cpp:1098 +msgid "Show log" +msgstr "" + +#: src/FLTK/flgui.cpp:4149 +msgid "show/hide info window" +msgstr "" + +#: src/FLTK/flgui.cpp:4156 +msgid "-24 dB" +msgstr "" + +#: src/FLTK/flgui.cpp:4159 +msgid "Gain" +msgstr "" + +#: src/FLTK/flgui.cpp:4160 src/FLTK/fl_callbacks.cpp:3663 +#: src/FLTK/fl_funcs.cpp:810 +msgid "Master Gain" +msgstr "" + +#: src/FLTK/flgui.cpp:4178 +msgid "+24 dB" +msgstr "" + +#: src/FLTK/flgui.cpp:4185 +msgid "Listeners: 0" +msgstr "" + +#: src/FLTK/flgui.cpp:4200 +msgid "butt settings" +msgstr "" + +#: src/FLTK/flgui.cpp:4213 +msgid "Main" +msgstr "" + +#: src/FLTK/flgui.cpp:4215 +msgid "Server Settings" +msgstr "" + +#: src/FLTK/flgui.cpp:4218 +msgid "Server" +msgstr "" + +#: src/FLTK/flgui.cpp:4219 +msgid "Server to connect to" +msgstr "" + +#: src/FLTK/flgui.cpp:4224 src/FLTK/flgui.cpp:4245 +msgid "ADD" +msgstr "" + +#: src/FLTK/flgui.cpp:4225 src/FLTK/flgui.cpp:5550 +msgid "Add server" +msgstr "" + +#: src/FLTK/flgui.cpp:4229 src/FLTK/flgui.cpp:4250 +msgid "EDIT" +msgstr "" + +#: src/FLTK/flgui.cpp:4230 +msgid "Edit selected server" +msgstr "" + +#: src/FLTK/flgui.cpp:4234 src/FLTK/flgui.cpp:4255 +msgid "DEL" +msgstr "" + +#: src/FLTK/flgui.cpp:4235 +msgid "Delete selected server" +msgstr "" + +#: src/FLTK/flgui.cpp:4239 +msgid "Stream Infos" +msgstr "" + +#: src/FLTK/flgui.cpp:4240 +msgid "Stream info that shall be used" +msgstr "" + +#: src/FLTK/flgui.cpp:4246 src/FLTK/flgui.cpp:5671 +msgid "Add stream info" +msgstr "" + +#: src/FLTK/flgui.cpp:4251 +msgid "Edit stream info" +msgstr "" + +#: src/FLTK/flgui.cpp:4256 +msgid "Delete stream info" +msgstr "" + +#: src/FLTK/flgui.cpp:4262 +msgid "Log File" +msgstr "" + +#: src/FLTK/flgui.cpp:4266 +msgid "Log file path" +msgstr "" + +#: src/FLTK/flgui.cpp:4271 +msgid "Select log file" +msgstr "" + +#: src/FLTK/flgui.cpp:4278 +msgid "Configuration" +msgstr "" + +#: src/FLTK/flgui.cpp:4281 src/FLTK/fl_callbacks.cpp:4128 +msgid "Import..." +msgstr "" + +#: src/FLTK/flgui.cpp:4282 +msgid "Import settings from config file" +msgstr "" + +#: src/FLTK/flgui.cpp:4286 src/FLTK/flgui.cpp:5615 src/FLTK/flgui.cpp:5717 +msgid "&Save" +msgstr "" + +#: src/FLTK/flgui.cpp:4287 +msgid "Save settings" +msgstr "" + +#: src/FLTK/flgui.cpp:4291 +msgid "Export..." +msgstr "" + +#: src/FLTK/flgui.cpp:4292 +msgid "export settings" +msgstr "" + +#: src/FLTK/flgui.cpp:4298 +msgid "Butt Agent" +msgstr "" + +#: src/FLTK/flgui.cpp:4301 +msgid "Start agent at startup" +msgstr "" + +#: src/FLTK/flgui.cpp:4302 +msgid "Start the butt agent when butt starts" +msgstr "" + +#: src/FLTK/flgui.cpp:4306 src/FLTK/flgui.cpp:4307 +msgid "Minimize butt to tray" +msgstr "" + +#: src/FLTK/flgui.cpp:4311 +msgid "Start Agent" +msgstr "" + +#: src/FLTK/flgui.cpp:4312 +msgid "Start the butt agent now" +msgstr "" + +#: src/FLTK/flgui.cpp:4316 +msgid "Stop Agent" +msgstr "" + +#: src/FLTK/flgui.cpp:4317 +msgid "Stop the butt agent" +msgstr "" + +#: src/FLTK/flgui.cpp:4323 +msgid "Updates" +msgstr "" + +#: src/FLTK/flgui.cpp:4326 +msgid "Check at startup" +msgstr "" + +#: src/FLTK/flgui.cpp:4327 +msgid "Check for updates at start" +msgstr "" + +#: src/FLTK/flgui.cpp:4331 +msgid "Check now" +msgstr "" + +#: src/FLTK/flgui.cpp:4332 +msgid "Check if a new version is available" +msgstr "" + +#: src/FLTK/flgui.cpp:4338 +msgid "Help" +msgstr "" + +#: src/FLTK/flgui.cpp:4341 +msgid "Manual" +msgstr "" + +#: src/FLTK/flgui.cpp:4345 +msgid " YouTube" +msgstr "" + +#: src/FLTK/flgui.cpp:4355 +msgid "Audio" +msgstr "" + +#: src/FLTK/flgui.cpp:4357 +msgid "Main Audio Settings" +msgstr "" + +#: src/FLTK/flgui.cpp:4360 +msgid "Channel mode" +msgstr "" + +#: src/FLTK/flgui.cpp:4361 +msgid "Select input channel" +msgstr "" + +#: src/FLTK/flgui.cpp:4374 +msgid "Samplerate" +msgstr "" + +#: src/FLTK/flgui.cpp:4375 +msgid "Select input sample rate" +msgstr "" + +#: src/FLTK/flgui.cpp:4380 +msgid "Remember Device by" +msgstr "" + +#: src/FLTK/flgui.cpp:4383 +msgid "ID" +msgstr "" + +#: src/FLTK/flgui.cpp:4388 +msgid "Name" +msgstr "" + +#: src/FLTK/flgui.cpp:4395 +msgid "Update devices" +msgstr "" + +#: src/FLTK/flgui.cpp:4396 +msgid "Rescan audio devices" +msgstr "" + +#: src/FLTK/flgui.cpp:4400 +msgid "Primary Audio Device" +msgstr "" + +#: src/FLTK/flgui.cpp:4401 +msgid "Select your primary sound card device" +msgstr "" + +#: src/FLTK/flgui.cpp:4406 src/FLTK/flgui.cpp:4424 +msgid "Left" +msgstr "" + +#: src/FLTK/flgui.cpp:4407 src/FLTK/flgui.cpp:4425 +msgid "Select left audio channel" +msgstr "" + +#: src/FLTK/flgui.cpp:4412 src/FLTK/flgui.cpp:4430 +msgid "Right" +msgstr "" + +#: src/FLTK/flgui.cpp:4413 src/FLTK/flgui.cpp:4431 +msgid "Select right audio channel" +msgstr "" + +#: src/FLTK/flgui.cpp:4418 +msgid "Secondary Audio Device" +msgstr "" + +#: src/FLTK/flgui.cpp:4419 +msgid "Select your secondary sound card device" +msgstr "" + +#: src/FLTK/flgui.cpp:4441 src/FLTK/flgui.cpp:4472 +msgid "Codec" +msgstr "" + +#: src/FLTK/flgui.cpp:4442 +msgid "Select streaming codec" +msgstr "" + +#: src/FLTK/flgui.cpp:4455 src/FLTK/flgui.cpp:4486 +msgid "Bitrate" +msgstr "" + +#: src/FLTK/flgui.cpp:4456 +msgid "Select streaming bitrate" +msgstr "" + +#: src/FLTK/flgui.cpp:4473 +msgid "Select recording codec" +msgstr "" + +#: src/FLTK/flgui.cpp:4487 +msgid "Select recording bitrate" +msgstr "" + +#: src/FLTK/flgui.cpp:4499 +msgid "Advanced..." +msgstr "" + +#: src/FLTK/flgui.cpp:4505 +msgid "Buffer (ms)" +msgstr "" + +#: src/FLTK/flgui.cpp:4514 +msgid "Resample Quality" +msgstr "" + +#: src/FLTK/flgui.cpp:4529 +msgid "Signal detection levels" +msgstr "" + +#: src/FLTK/flgui.cpp:4532 +msgid "Signal present" +msgstr "" + +#: src/FLTK/flgui.cpp:4539 src/FLTK/flgui.cpp:4549 +msgid "dB" +msgstr "" + +#: src/FLTK/flgui.cpp:4542 +msgid "Signal absent" +msgstr "" + +#: src/FLTK/flgui.cpp:4556 src/FLTK/flgui.cpp:4833 src/FLTK/flgui.cpp:5084 +msgid "Stream" +msgstr "" + +#: src/FLTK/flgui.cpp:4558 +msgid "Update song name from file" +msgstr "" + +#: src/FLTK/flgui.cpp:4562 +msgid "Filename that holds the current song name" +msgstr "" + +#: src/FLTK/flgui.cpp:4568 +msgid "Select file that holds the current song name" +msgstr "" + +#: src/FLTK/flgui.cpp:4573 src/FLTK/flgui.cpp:4606 src/FLTK/flgui.cpp:4724 +msgid "Activate" +msgstr "" + +#: src/FLTK/flgui.cpp:4574 src/FLTK/flgui.cpp:4579 +msgid "Activate auto update song name from file" +msgstr "" + +#: src/FLTK/flgui.cpp:4578 +msgid "Read last line instead of first" +msgstr "" + +#: src/FLTK/flgui.cpp:4585 +msgid "Update song name from application" +msgstr "" + +#: src/FLTK/flgui.cpp:4589 +msgid "Changes the song through an running application" +msgstr "" + +#: src/FLTK/flgui.cpp:4594 +msgid "Title - Artist" +msgstr "" + +#: src/FLTK/flgui.cpp:4599 +msgid "Artist - Title" +msgstr "" + +#: src/FLTK/flgui.cpp:4612 +msgid "Update song name manually" +msgstr "" + +#: src/FLTK/flgui.cpp:4616 +msgid "Current song name" +msgstr "" + +#: src/FLTK/flgui.cpp:4622 src/FLTK/fl_callbacks.cpp:1594 +msgid "OK" +msgstr "" + +#: src/FLTK/flgui.cpp:4623 +msgid "Send current song name to the server" +msgstr "" + +#: src/FLTK/flgui.cpp:4631 +msgid "Update song name delay" +msgstr "" + +#: src/FLTK/flgui.cpp:4635 +msgid "Introduces a delay until the song name is actually updated" +msgstr "" + +#: src/FLTK/flgui.cpp:4642 +msgid "Extend song name" +msgstr "" + +#: src/FLTK/flgui.cpp:4645 +msgid "Prefix:" +msgstr "" + +#: src/FLTK/flgui.cpp:4650 +msgid "Suffix:" +msgstr "" + +#: src/FLTK/flgui.cpp:4660 src/FLTK/flgui.cpp:4789 +msgid "Start if signal is present for" +msgstr "" + +#: src/FLTK/flgui.cpp:4661 +msgid "" +"Start streaming if the audio level exceeds the \"Signal present\" level set " +"in the \"Audio\" tab" +msgstr "" + +#: src/FLTK/flgui.cpp:4670 src/FLTK/flgui.cpp:4683 src/FLTK/flgui.cpp:4702 +#: src/FLTK/flgui.cpp:4799 src/FLTK/flgui.cpp:4812 src/FLTK/flgui.cpp:5499 +msgid "seconds" +msgstr "" + +#: src/FLTK/flgui.cpp:4673 src/FLTK/flgui.cpp:4802 +msgid "Stop if signal is absent for" +msgstr "" + +#: src/FLTK/flgui.cpp:4674 +msgid "" +"Stop streaming if the audio level falls below the \"Signal absent level set " +"in the \"Audio\" tab" +msgstr "" + +#: src/FLTK/flgui.cpp:4686 +msgid "Start streaming after launch" +msgstr "" + +#: src/FLTK/flgui.cpp:4687 +msgid "Connect automatically to a server after launch" +msgstr "" + +#: src/FLTK/flgui.cpp:4691 +msgid "Force reconnecting" +msgstr "" + +#: src/FLTK/flgui.cpp:4692 +msgid "If enabled butt keeps reconnecting regardless of the error message" +msgstr "" + +#: src/FLTK/flgui.cpp:4696 +msgid "Reconnect delay:" +msgstr "" + +#: src/FLTK/flgui.cpp:4707 +msgid "Update song name from URL" +msgstr "" + +#: src/FLTK/flgui.cpp:4711 +msgid "URL to get song name from" +msgstr "" + +#: src/FLTK/flgui.cpp:4716 +msgid "Update interval" +msgstr "" + +#: src/FLTK/flgui.cpp:4717 +msgid "Update interval in seconds" +msgstr "" + +#: src/FLTK/flgui.cpp:4732 +msgid "Record" +msgstr "" + +#: src/FLTK/flgui.cpp:4734 +msgid "Record File Name:" +msgstr "" + +#: src/FLTK/flgui.cpp:4735 +msgid "Record file name" +msgstr "" + +#: src/FLTK/flgui.cpp:4740 +msgid "Record Directory:" +msgstr "" + +#: src/FLTK/flgui.cpp:4741 +msgid "Directory of recordings" +msgstr "" + +#: src/FLTK/flgui.cpp:4747 +msgid "Select recording directory" +msgstr "" + +#: src/FLTK/flgui.cpp:4752 +msgid "Split file" +msgstr "" + +#: src/FLTK/flgui.cpp:4755 +msgid "every" +msgstr "" + +#: src/FLTK/flgui.cpp:4758 +msgid "minutes" +msgstr "" + +#: src/FLTK/flgui.cpp:4760 src/FLTK/flgui.cpp:4761 +msgid "Sync to full hour" +msgstr "" + +#: src/FLTK/flgui.cpp:4765 +msgid "Split now" +msgstr "" + +#: src/FLTK/flgui.cpp:4774 src/FLTK/flgui.cpp:4775 +msgid "Start recording when connected" +msgstr "" + +#: src/FLTK/flgui.cpp:4779 +msgid "Stop recording when disconnected" +msgstr "" + +#: src/FLTK/flgui.cpp:4780 +msgid "Start recording when disconnected" +msgstr "" + +#: src/FLTK/flgui.cpp:4784 src/FLTK/flgui.cpp:4785 +msgid "Start recording after launch" +msgstr "" + +#: src/FLTK/flgui.cpp:4790 +msgid "" +"Start recording if the audio level exceeds the \"Signal present\" level set " +"in the \"Audio\" tab" +msgstr "" + +#: src/FLTK/flgui.cpp:4803 +msgid "" +"Stop recording if the audio level falls below the \"Signal absent level set " +"in the \"Audio\" tab" +msgstr "" + +#: src/FLTK/flgui.cpp:4815 +msgid "Overwrite existing files" +msgstr "" + +#: src/FLTK/flgui.cpp:4823 +msgid "DSP" +msgstr "" + +#: src/FLTK/flgui.cpp:4825 src/FLTK/flgui.cpp:5076 src/FLTK/flgui.cpp:6478 +msgid "Reset" +msgstr "" + +#: src/FLTK/flgui.cpp:4830 +msgid "Equalizer" +msgstr "" + +#: src/FLTK/flgui.cpp:4837 src/FLTK/flgui.cpp:5088 +msgid "Rec" +msgstr "" + +#: src/FLTK/flgui.cpp:4842 +msgid "Equalizer Preset" +msgstr "" + +#: src/FLTK/flgui.cpp:4854 src/FLTK/flgui.cpp:4876 src/FLTK/flgui.cpp:4898 +#: src/FLTK/flgui.cpp:4920 src/FLTK/flgui.cpp:4942 src/FLTK/flgui.cpp:4964 +#: src/FLTK/flgui.cpp:4986 src/FLTK/flgui.cpp:5008 src/FLTK/flgui.cpp:5030 +#: src/FLTK/flgui.cpp:5052 src/FLTK/flgui.cpp:5096 src/FLTK/flgui.cpp:5118 +#: src/FLTK/flgui.cpp:5186 +msgid "+0.0" +msgstr "" + +#: src/FLTK/flgui.cpp:4858 +msgid "32Hz" +msgstr "" + +#: src/FLTK/flgui.cpp:4880 +msgid "64Hz" +msgstr "" + +#: src/FLTK/flgui.cpp:4902 +msgid "125Hz" +msgstr "" + +#: src/FLTK/flgui.cpp:4924 +msgid "250Hz" +msgstr "" + +#: src/FLTK/flgui.cpp:4946 +msgid "500Hz" +msgstr "" + +#: src/FLTK/flgui.cpp:4968 +msgid "1kHz" +msgstr "" + +#: src/FLTK/flgui.cpp:4990 +msgid "2kHz" +msgstr "" + +#: src/FLTK/flgui.cpp:5012 +msgid "4kHz" +msgstr "" + +#: src/FLTK/flgui.cpp:5034 +msgid "8kHz" +msgstr "" + +#: src/FLTK/flgui.cpp:5056 +msgid "16kHz" +msgstr "" + +#: src/FLTK/flgui.cpp:5081 +msgid "Dynamic Range Compressor" +msgstr "" + +#: src/FLTK/flgui.cpp:5092 +msgid "Aggressive Mode" +msgstr "" + +#: src/FLTK/flgui.cpp:5100 +msgid "Threshold" +msgstr "" + +#: src/FLTK/flgui.cpp:5122 +msgid "Ratio" +msgstr "" + +#: src/FLTK/flgui.cpp:5140 src/FLTK/flgui.cpp:5163 +msgid "+0.00" +msgstr "" + +#: src/FLTK/flgui.cpp:5144 +msgid "Attack" +msgstr "" + +#: src/FLTK/flgui.cpp:5167 +msgid "Release" +msgstr "" + +#: src/FLTK/flgui.cpp:5190 +msgid "MakeupGain" +msgstr "" + +#: src/FLTK/flgui.cpp:5224 src/FLTK/flgui.cpp:5237 +msgid "MIDI" +msgstr "" + +#: src/FLTK/flgui.cpp:5226 +msgid "MIDI Device" +msgstr "" + +#: src/FLTK/flgui.cpp:5227 +msgid "Select your MIDI device" +msgstr "" + +#: src/FLTK/flgui.cpp:5232 +msgid "Rescan" +msgstr "" + +#: src/FLTK/flgui.cpp:5233 +msgid "Rescan MIDI devices" +msgstr "" + +#: src/FLTK/flgui.cpp:5238 +msgid "MIDI signal indicator" +msgstr "" + +#: src/FLTK/flgui.cpp:5250 +msgid "MIDI Commands" +msgstr "" + +#: src/FLTK/flgui.cpp:5255 +msgid "Enable" +msgstr "" + +#: src/FLTK/flgui.cpp:5256 +msgid "Enable/Disable the selected MIDI command" +msgstr "" + +#: src/FLTK/flgui.cpp:5262 +msgid "Channel" +msgstr "" + +#: src/FLTK/flgui.cpp:5263 +msgid "Select MIDI channel" +msgstr "" + +#: src/FLTK/flgui.cpp:5277 +msgid "CC" +msgstr "" + +#: src/FLTK/flgui.cpp:5278 +msgid "Select CC number" +msgstr "" + +#: src/FLTK/flgui.cpp:5283 src/FLTK/fl_callbacks.cpp:6425 +msgid "Learn" +msgstr "" + +#: src/FLTK/flgui.cpp:5284 +msgid "Activate to auto detect the channel and CC number" +msgstr "" + +#: src/FLTK/flgui.cpp:5289 +msgid "CC Mode" +msgstr "" + +#: src/FLTK/flgui.cpp:5290 +msgid "Select CC mode" +msgstr "" + +#: src/FLTK/flgui.cpp:5304 +msgid "Soft takeover" +msgstr "" + +#: src/FLTK/flgui.cpp:5305 +msgid "Prevents jumps when controlling a slider in absolute mode" +msgstr "" + +#: src/FLTK/flgui.cpp:5313 +msgid "TLS" +msgstr "" + +#: src/FLTK/flgui.cpp:5315 src/FLTK/flgui.cpp:5619 +msgid "SSL/TLS" +msgstr "" + +#: src/FLTK/flgui.cpp:5318 +msgid "" +"If your server uses a certificate from\n" +"Let's Encrypt or another well known\n" +"CA, you can leave these fields blank." +msgstr "" + +#: src/FLTK/flgui.cpp:5322 +msgid "CA Certificate File:" +msgstr "" + +#: src/FLTK/flgui.cpp:5323 +msgid "Certificate file" +msgstr "" + +#: src/FLTK/flgui.cpp:5329 +msgid "Select certificate file" +msgstr "" + +#: src/FLTK/flgui.cpp:5334 +msgid "CA Certificate Directory:" +msgstr "" + +#: src/FLTK/flgui.cpp:5335 +msgid "Certificate directory" +msgstr "" + +#: src/FLTK/flgui.cpp:5341 +msgid "Select certificate directory" +msgstr "" + +#: src/FLTK/flgui.cpp:5350 +msgid "GUI" +msgstr "" + +#: src/FLTK/flgui.cpp:5352 +msgid "Language" +msgstr "" + +#: src/FLTK/flgui.cpp:5369 +msgid "Display Color" +msgstr "" + +#: src/FLTK/flgui.cpp:5372 +msgid "Text" +msgstr "" + +#: src/FLTK/flgui.cpp:5373 +msgid "Select text color" +msgstr "" + +#: src/FLTK/flgui.cpp:5379 +msgid "Background" +msgstr "" + +#: src/FLTK/flgui.cpp:5380 +msgid "Select background color" +msgstr "" + +#: src/FLTK/flgui.cpp:5388 +msgid "VU meter" +msgstr "" + +#: src/FLTK/flgui.cpp:5391 +msgid "Gradient colors" +msgstr "" + +#: src/FLTK/flgui.cpp:5396 +msgid "Solid colors" +msgstr "" + +#: src/FLTK/flgui.cpp:5401 +msgid "Always show tabs" +msgstr "" + +#: src/FLTK/flgui.cpp:5406 +msgid "Select lower range color" +msgstr "" + +#: src/FLTK/flgui.cpp:5413 +msgid "Select mid range color" +msgstr "" + +#: src/FLTK/flgui.cpp:5420 +msgid "Select high range color" +msgstr "" + +#: src/FLTK/flgui.cpp:5427 +msgid "Low range start value (dB)" +msgstr "" + +#: src/FLTK/flgui.cpp:5431 +msgid "Mid range start value (dB)" +msgstr "" + +#: src/FLTK/flgui.cpp:5440 +msgid "High range start value (dB)" +msgstr "" + +#: src/FLTK/flgui.cpp:5450 +msgid "Misc" +msgstr "" + +#: src/FLTK/flgui.cpp:5453 +msgid "Attach settings window to main window" +msgstr "" + +#: src/FLTK/flgui.cpp:5454 +msgid "Attach this window to the butt window" +msgstr "" + +#: src/FLTK/flgui.cpp:5458 src/FLTK/flgui.cpp:5459 +msgid "Stay always on top" +msgstr "" + +#: src/FLTK/flgui.cpp:5463 src/FLTK/flgui.cpp:5464 +msgid "Remember main window position" +msgstr "" + +#: src/FLTK/flgui.cpp:5468 src/FLTK/flgui.cpp:5469 +msgid "Hide log window after start up" +msgstr "" + +#: src/FLTK/flgui.cpp:5473 src/FLTK/flgui.cpp:5474 +msgid "Change display mode every 5 seconds" +msgstr "" + +#: src/FLTK/flgui.cpp:5478 +msgid "Start minimized" +msgstr "" + +#: src/FLTK/flgui.cpp:5479 +msgid "Minimize butt at startup" +msgstr "" + +#: src/FLTK/flgui.cpp:5483 +msgid "Disable gain control" +msgstr "" + +#: src/FLTK/flgui.cpp:5489 +msgid "Show listeners" +msgstr "" + +#: src/FLTK/flgui.cpp:5490 +msgid "Show current listeners in the display (not always available)" +msgstr "" + +#: src/FLTK/flgui.cpp:5494 +msgid "Update rate:" +msgstr "" + +#: src/FLTK/flgui.cpp:5504 +msgid "Custom window title:" +msgstr "" + +#: src/FLTK/flgui.cpp:5505 +msgid "Define a custom window title" +msgstr "" + +#: src/FLTK/flgui.cpp:5515 +msgid "Donate" +msgstr "" + +#: src/FLTK/flgui.cpp:5517 +msgid "Donation" +msgstr "" + +#: src/FLTK/flgui.cpp:5520 +msgid "" +"Keeping this software up to date, adding\n" +"new features and answering support mails\n" +"takes a lot of time and effort. If you can\n" +"afford it, please consider supporting this\n" +"project.\n" +"\n" +"Thank you!" +msgstr "" + +#: src/FLTK/flgui.cpp:5525 +msgid "&Donate via PayPal" +msgstr "" + +#: src/FLTK/flgui.cpp:5529 +msgid "Become a &patron" +msgstr "" + +#: src/FLTK/flgui.cpp:5533 +msgid "&Apple Pay, Google Pay, CC and more" +msgstr "" + +#: src/FLTK/flgui.cpp:5537 +msgid "&Bitcoin && Co" +msgstr "" + +#: src/FLTK/flgui.cpp:5552 src/FLTK/flgui.cpp:5673 +msgid "Name:" +msgstr "" + +#: src/FLTK/flgui.cpp:5556 +msgid "Address:" +msgstr "" + +#: src/FLTK/flgui.cpp:5560 +msgid "Port:" +msgstr "" + +#: src/FLTK/flgui.cpp:5564 +msgid "Password:" +msgstr "" + +#: src/FLTK/flgui.cpp:5569 +msgid "Icecast mountpoint:" +msgstr "" + +#: src/FLTK/flgui.cpp:5573 +msgid "Icecast user:" +msgstr "" + +#: src/FLTK/flgui.cpp:5577 src/FLTK/fl_callbacks.cpp:1136 +#: src/FLTK/fl_callbacks.cpp:1215 src/FLTK/fl_callbacks.cpp:1623 +msgid "Show" +msgstr "" + +#: src/FLTK/flgui.cpp:5578 +msgid "show/hide password" +msgstr "" + +#: src/FLTK/flgui.cpp:5582 +msgid "Type" +msgstr "" + +#: src/FLTK/flgui.cpp:5585 +msgid "Shoutcast" +msgstr "" + +#: src/FLTK/flgui.cpp:5590 +msgid "Icecast" +msgstr "" + +#: src/FLTK/flgui.cpp:5595 +msgid "WebRTC" +msgstr "" + +#: src/FLTK/flgui.cpp:5600 +msgid "Radio.co" +msgstr "" + +#: src/FLTK/flgui.cpp:5607 src/FLTK/flgui.cpp:5709 +msgid "&Cancel" +msgstr "" + +#: src/FLTK/flgui.cpp:5611 src/FLTK/flgui.cpp:5713 +msgid "&ADD" +msgstr "" + +#: src/FLTK/flgui.cpp:5622 +msgid "Use SSL/TLS" +msgstr "" + +#: src/FLTK/flgui.cpp:5625 +msgid "Revoke certificate trust" +msgstr "" + +#: src/FLTK/flgui.cpp:5631 +msgid "Radio.co Stations" +msgstr "" + +#: src/FLTK/flgui.cpp:5634 +msgid "Get Stations" +msgstr "" + +#: src/FLTK/flgui.cpp:5638 +msgid "Select all" +msgstr "" + +#: src/FLTK/flgui.cpp:5642 +msgid "Deselect all" +msgstr "" + +#: src/FLTK/flgui.cpp:5646 +msgid "Use legacy Icecast protocol" +msgstr "" + +#: src/FLTK/flgui.cpp:5647 +msgid "" +"Activate this if you want to use the older SOURCE protocol instead of the " +"newer PUT protocol" +msgstr "" + +#: src/FLTK/flgui.cpp:5651 +msgid "ICE server (optional):" +msgstr "" + +#: src/FLTK/flgui.cpp:5654 +msgid "WebRTC (WHIP) URL:" +msgstr "" + +#: src/FLTK/flgui.cpp:5657 +msgid "Bearer token (optional):" +msgstr "" + +#: src/FLTK/flgui.cpp:5660 +msgid "Custom listener URL (optional):" +msgstr "" + +#: src/FLTK/flgui.cpp:5664 +msgid "Custom listener mountpoint (optional):" +msgstr "" + +#: src/FLTK/flgui.cpp:5674 +msgid "The name of your new ICY-entrie" +msgstr "" + +#: src/FLTK/flgui.cpp:5678 +msgid "Description:" +msgstr "" + +#: src/FLTK/flgui.cpp:5682 +msgid "Genre:" +msgstr "" + +#: src/FLTK/flgui.cpp:5686 +msgid "URL:" +msgstr "" + +#: src/FLTK/flgui.cpp:5690 +msgid "ICQ:" +msgstr "" + +#: src/FLTK/flgui.cpp:5694 +msgid "IRC:" +msgstr "" + +#: src/FLTK/flgui.cpp:5698 +msgid "AIM:" +msgstr "" + +#: src/FLTK/flgui.cpp:5702 +msgid "Make server public" +msgstr "" + +#: src/FLTK/flgui.cpp:5705 +msgid "Expand variables" +msgstr "" + +#: src/FLTK/flgui.cpp:5706 +msgid "Activate to expand date variables in name and description" +msgstr "" + +#: src/FLTK/flgui.cpp:5736 +msgid "Donate Cryptocurrency" +msgstr "" + +#: src/FLTK/flgui.cpp:5747 +msgid "Bitcoin" +msgstr "" + +#: src/FLTK/flgui.cpp:5752 src/FLTK/flgui.cpp:5761 src/FLTK/flgui.cpp:5770 +msgid "Copy" +msgstr "" + +#: src/FLTK/flgui.cpp:5756 +msgid "Litecoin" +msgstr "" + +#: src/FLTK/flgui.cpp:5765 +msgid "Monero" +msgstr "" + +#: src/FLTK/flgui.cpp:5774 src/FLTK/flgui.cpp:6106 src/FLTK/flgui.cpp:6461 +#: src/FLTK/flgui.cpp:6669 +msgid "&Close" +msgstr "" + +#: src/FLTK/flgui.cpp:5780 +msgid "Streaming Codec Settings" +msgstr "" + +#: src/FLTK/flgui.cpp:5792 src/FLTK/flgui.cpp:6124 +msgid "MP3" +msgstr "" + +#: src/FLTK/flgui.cpp:5793 src/FLTK/flgui.cpp:6125 +msgid "Encoding Quality" +msgstr "" + +#: src/FLTK/flgui.cpp:5806 src/FLTK/flgui.cpp:6138 +msgid "Stereo Mode" +msgstr "" + +#: src/FLTK/flgui.cpp:5819 src/FLTK/flgui.cpp:5949 src/FLTK/flgui.cpp:6015 +#: src/FLTK/flgui.cpp:6071 src/FLTK/flgui.cpp:6151 src/FLTK/flgui.cpp:6281 +#: src/FLTK/flgui.cpp:6334 src/FLTK/flgui.cpp:6403 +msgid "Bitrate Mode" +msgstr "" + +#: src/FLTK/flgui.cpp:5832 src/FLTK/flgui.cpp:6164 +msgid "VBR" +msgstr "" + +#: src/FLTK/flgui.cpp:5835 src/FLTK/flgui.cpp:5989 src/FLTK/flgui.cpp:6167 +#: src/FLTK/flgui.cpp:6347 +msgid "Quality" +msgstr "" + +#: src/FLTK/flgui.cpp:5848 src/FLTK/flgui.cpp:6180 +msgid "Min. Bitrate" +msgstr "" + +#: src/FLTK/flgui.cpp:5861 src/FLTK/flgui.cpp:6193 +msgid "Max. Bitrate" +msgstr "" + +#: src/FLTK/flgui.cpp:5874 src/FLTK/flgui.cpp:6206 +msgid "Force" +msgstr "" + +#: src/FLTK/flgui.cpp:5875 src/FLTK/flgui.cpp:6207 +msgid "Strictly enforce mininum Bitrate (-F option of the lame encoder)" +msgstr "" + +#: src/FLTK/flgui.cpp:5881 src/FLTK/flgui.cpp:6227 +msgid "Lowpass (kHz)" +msgstr "" + +#: src/FLTK/flgui.cpp:5884 src/FLTK/flgui.cpp:5909 src/FLTK/flgui.cpp:6230 +#: src/FLTK/flgui.cpp:6255 +msgid "Frequency" +msgstr "" + +#: src/FLTK/flgui.cpp:5890 src/FLTK/flgui.cpp:5915 src/FLTK/flgui.cpp:6236 +#: src/FLTK/flgui.cpp:6261 +msgid "Width" +msgstr "" + +#: src/FLTK/flgui.cpp:5906 src/FLTK/flgui.cpp:6252 +msgid "Highpass (kHz)" +msgstr "" + +#: src/FLTK/flgui.cpp:5931 src/FLTK/flgui.cpp:6213 +msgid "Resampling" +msgstr "" + +#: src/FLTK/flgui.cpp:5932 src/FLTK/flgui.cpp:6214 +msgid "Resample to the selected sample rate" +msgstr "" + +#: src/FLTK/flgui.cpp:5947 src/FLTK/flgui.cpp:6279 +msgid "OGG" +msgstr "" + +#: src/FLTK/flgui.cpp:5962 src/FLTK/flgui.cpp:6294 +msgid "VBR Quality" +msgstr "" + +#: src/FLTK/flgui.cpp:5975 src/FLTK/flgui.cpp:6307 +msgid "VBR min. Bitrate" +msgstr "" + +#: src/FLTK/flgui.cpp:5980 src/FLTK/flgui.cpp:6312 +msgid "VBR max. Bitrate" +msgstr "" + +#: src/FLTK/flgui.cpp:5987 src/FLTK/flgui.cpp:6319 +msgid "OPUS" +msgstr "" + +#: src/FLTK/flgui.cpp:6002 src/FLTK/flgui.cpp:6321 +msgid "Optimize for" +msgstr "" + +#: src/FLTK/flgui.cpp:6028 src/FLTK/flgui.cpp:6360 +msgid "Max. Bandwidth" +msgstr "" + +#: src/FLTK/flgui.cpp:6043 src/FLTK/flgui.cpp:6375 +msgid "AAC" +msgstr "" + +#: src/FLTK/flgui.cpp:6045 src/FLTK/flgui.cpp:6377 +msgid "Profile" +msgstr "" + +#: src/FLTK/flgui.cpp:6058 src/FLTK/flgui.cpp:6390 +msgid "Afterburner" +msgstr "" + +#: src/FLTK/flgui.cpp:6086 src/FLTK/flgui.cpp:6418 +msgid "FLAC" +msgstr "" + +#: src/FLTK/flgui.cpp:6088 src/FLTK/flgui.cpp:6420 src/FLTK/flgui.cpp:6438 +msgid "Bit depth" +msgstr "" + +#: src/FLTK/flgui.cpp:6090 src/FLTK/flgui.cpp:6422 src/FLTK/flgui.cpp:6440 +msgid "16 bit" +msgstr "" + +#: src/FLTK/flgui.cpp:6095 src/FLTK/flgui.cpp:6427 src/FLTK/flgui.cpp:6450 +msgid "24 bit" +msgstr "" + +#: src/FLTK/flgui.cpp:6112 +msgid "Recording Codec Settings" +msgstr "" + +#: src/FLTK/flgui.cpp:6436 +msgid "WAV" +msgstr "" + +#: src/FLTK/flgui.cpp:6445 +msgid "32 bit" +msgstr "" + +#: src/FLTK/flgui.cpp:6467 +msgid "butt audio mixer" +msgstr "" + +#: src/FLTK/flgui.cpp:6483 +msgid "Audio Mixer" +msgstr "" + +#: src/FLTK/flgui.cpp:6486 src/FLTK/flgui.cpp:6516 src/FLTK/flgui.cpp:6546 +#: src/FLTK/flgui.cpp:6569 src/FLTK/flgui.cpp:6592 +msgid "+0.0 dB" +msgstr "" + +#: src/FLTK/flgui.cpp:6491 src/FLTK/flgui.cpp:6634 +msgid "" +"Primary\n" +"Device" +msgstr "" + +#: src/FLTK/flgui.cpp:6509 src/FLTK/flgui.cpp:6510 src/FLTK/flgui.cpp:6539 +#: src/FLTK/flgui.cpp:6540 +msgid "Mute" +msgstr "" + +#: src/FLTK/flgui.cpp:6521 src/FLTK/flgui.cpp:6642 +msgid "" +"Secondary\n" +"Device" +msgstr "" + +#: src/FLTK/flgui.cpp:6551 +msgid "" +"Streaming\n" +"Gain" +msgstr "" + +#: src/FLTK/flgui.cpp:6574 +msgid "" +"Recording\n" +"Gain" +msgstr "" + +#: src/FLTK/flgui.cpp:6597 +msgid "" +"Master\n" +"Gain" +msgstr "" + +#: src/FLTK/flgui.cpp:6615 +msgid "" +"\n" +"Cross Fader" +msgstr "" + +#: src/FLTK/flgui.cpp:6638 +msgid "|" +msgstr "" + +#: src/FLTK/flgui.cpp:6650 +msgid "Alert" +msgstr "" + +#: src/FLTK/flgui.cpp:6661 +msgid "&Open the manual" +msgstr "" + +#: src/FLTK/flgui.cpp:6665 +msgid "" +"Could not find aac library.\n" +"\n" +"Please follow the instructions in the manual\n" +"for adding aac support." +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:318 +#, c-format +msgid "" +"stream sent\n" +"%0.2lfMB" +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:323 +#, c-format +msgid "" +"stream time\n" +"%s" +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:330 +#, c-format +msgid "" +"On Air\n" +"Listeners %5d" +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:333 +#, c-format +msgid "" +"On Air\n" +"Listeners>%5d" +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:337 +#, c-format +msgid "On Air" +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:343 +#, c-format +msgid "" +"record time\n" +"%s" +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:348 +#, c-format +msgid "" +"record size\n" +"%0.2lfMB" +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:479 +#, c-format +msgid "" +"ERROR: Connection lost\n" +"reconnecting in %d seconds..." +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:483 +msgid "" +"ERROR: Connection lost\n" +"reconnecting..." +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:608 +msgid "Listeners" +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:674 +msgid "" +"Could not find a file extension in current filename\n" +"Automatic file splitting is deactivated" +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:704 +msgid "" +"Could not find a valid filename for next file\n" +"butt keeps recording to current file" +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:717 src/FLTK/fl_callbacks.cpp:1033 +#, c-format +msgid "" +"Could not open:\n" +"%s" +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:721 src/port_audio.cpp:938 +msgid "Recording to:" +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:964 +#, c-format +msgid "" +"Warning\n" +"Could not open: %s.\n" +"Will retry in 5 seconds" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:145 +msgid "connecting" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:187 +msgid "" +"Error: No server entry found.\n" +"Please add a server in the settings-window." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:192 +msgid "" +"Error: ogg vorbis encoder doesn't support bitrates\n" +"lower than 48kbit" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:200 +#, c-format +msgid "Warning: %s is not supported by every Shoutcast version" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:204 +msgid "Error: FLAC is not supported by ShoutCast" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:211 +#, c-format +msgid "Error: Radio.co supports only mp3 and aac" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:219 +#, c-format +msgid "Error: WebRTC only supports opus" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:226 +#, c-format +msgid "Connecting to %s via %s ..." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:229 +#, c-format +msgid "Connecting to %s:%u ..." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:232 +#, c-format +msgid "Connecting to %s:%u (%u) ..." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:328 +msgid "Connection established" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:342 src/FLTK/fl_callbacks.cpp:4275 +#: src/FLTK/fl_callbacks.cpp:4281 +msgid "no" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:342 src/FLTK/fl_callbacks.cpp:4275 +#: src/FLTK/fl_callbacks.cpp:4281 +msgid "yes" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:344 +#, c-format +msgid "Device 1:\t%s\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:345 +#, c-format +msgid "Device 2:\t%s\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:396 +#, c-format +msgid "Connected to: %s" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:567 src/FLTK/fl_callbacks.cpp:1669 +msgid "The custom listener URL must start with http:// or https://" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:574 src/FLTK/fl_callbacks.cpp:1676 +msgid "" +"No mountpoint specified\n" +"Setting mountpoint to \"stream\"" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:578 src/FLTK/fl_callbacks.cpp:1680 +msgid "" +"No user specified\n" +"Setting user to \"source\"" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:586 src/FLTK/fl_callbacks.cpp:1688 +msgid "" +"Unsupported listener URL.\n" +"The listener URL must end with status-json.xsl, 7.xsl, 7.html or contain " +"stats?sid" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:592 src/FLTK/fl_callbacks.cpp:1694 +#: src/FLTK/fl_callbacks.cpp:1857 src/FLTK/fl_callbacks.cpp:2545 +msgid "No name specified" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:597 src/FLTK/fl_callbacks.cpp:1699 +msgid "" +"The number of characters of all your server names exeeds 1000\n" +"Please reduce the number of characters of each server name" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:603 src/FLTK/fl_callbacks.cpp:1705 +msgid "Newline characters and [];/\\ are not allowed within the server name" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:609 src/FLTK/fl_callbacks.cpp:1710 +msgid "No address specified" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:613 src/FLTK/fl_callbacks.cpp:1714 +msgid "No password specified" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:617 src/FLTK/fl_callbacks.cpp:1718 +msgid "No port specified" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:621 src/FLTK/fl_callbacks.cpp:1722 +msgid "" +"Invalid port number\n" +"The port number must be between 1 and 65535" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:628 src/FLTK/fl_callbacks.cpp:1729 +msgid "No WHIP URL specified" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:637 src/FLTK/fl_callbacks.cpp:1740 +#: src/FLTK/fl_callbacks.cpp:2564 +msgid "Server name already exist!" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:966 +msgid "stop recording?" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:966 src/FLTK/fl_funcs.cpp:1462 +msgid "No" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:966 +msgid "Yes" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1005 +msgid "No recording filename specified" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1015 +#, c-format +msgid "%s already exists!" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "overwrite" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "cancel" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "append" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1021 +msgid "Recording canceled" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1090 src/FLTK/fl_funcs.cpp:1308 +msgid "Hide log" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1123 +msgid "Add Server" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1176 +msgid "Edit Server" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1181 +msgid "Radio.co stations cannot be edited." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1267 +msgid "Add Server Infos" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1302 +msgid "Song update failed: WebRTC does not support song names" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1345 +#, c-format +msgid "" +"Updated songname to:\n" +"%s\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1354 +msgid "Updating songname failed" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1428 +#, c-format +msgid "Audio buffer has been set to %d ms" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1592 +msgid "" +"butt will open Radio.co in a new browser window.\n" +"\n" +"Login to Radio.co and allow butt access to your account." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1618 +msgid "Hide" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1638 +msgid "Could not revoke trust for certificate" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1862 +msgid "" +"The number of characters of all your icy names exeeds 1000\n" +"Please reduce the count of characters of each icy name" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1868 src/FLTK/fl_callbacks.cpp:2557 +msgid "Newline characters and [];/\\ are not allowed within the icy name" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1877 +msgid "Icy name already exist!" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2002 src/FLTK/fl_callbacks.cpp:2015 +#: src/FLTK/fl_callbacks.cpp:2029 src/FLTK/fl_callbacks.cpp:2044 +#: src/FLTK/fl_callbacks.cpp:2233 src/FLTK/fl_callbacks.cpp:2246 +#: src/FLTK/fl_callbacks.cpp:2260 src/FLTK/fl_callbacks.cpp:2275 +#: src/FLTK/fl_callbacks.cpp:2290 +msgid "" +"Warning:\n" +"The stream Sample-/Bitrate combination is invalid" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2008 src/FLTK/fl_callbacks.cpp:2021 +#: src/FLTK/fl_callbacks.cpp:2035 src/FLTK/fl_callbacks.cpp:2050 +msgid "The previous values have been set\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2056 +#, c-format +msgid "Stream bitrate set to: %dk" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2142 src/FLTK/fl_callbacks.cpp:2155 +#: src/FLTK/fl_callbacks.cpp:2169 src/FLTK/fl_callbacks.cpp:2184 +#: src/FLTK/fl_callbacks.cpp:2313 src/FLTK/fl_callbacks.cpp:2326 +#: src/FLTK/fl_callbacks.cpp:2340 src/FLTK/fl_callbacks.cpp:2355 +#: src/FLTK/fl_callbacks.cpp:2369 +msgid "" +"Warning:\n" +"The record Sample-/Bitrate combination is invalid" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2148 src/FLTK/fl_callbacks.cpp:2161 +#: src/FLTK/fl_callbacks.cpp:2175 src/FLTK/fl_callbacks.cpp:2190 +#: src/FLTK/fl_callbacks.cpp:2239 src/FLTK/fl_callbacks.cpp:2252 +#: src/FLTK/fl_callbacks.cpp:2266 src/FLTK/fl_callbacks.cpp:2281 +#: src/FLTK/fl_callbacks.cpp:2296 src/FLTK/fl_callbacks.cpp:2319 +#: src/FLTK/fl_callbacks.cpp:2332 src/FLTK/fl_callbacks.cpp:2346 +#: src/FLTK/fl_callbacks.cpp:2361 src/FLTK/fl_callbacks.cpp:2375 +msgid "The previous values have been set" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2196 +#, c-format +msgid "Record bitrate set to: %dk" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2383 +#, c-format +msgid "Samplerate set to: %dHz" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2449 +msgid "Channels set to: stereo" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2512 +msgid "Channels set to: mono" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2551 +msgid "" +"The number of characters of all your icy names exeeds 1000\n" +"Please reduce the number of characters of each icy name" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2659 +msgid "Edit Server Infos" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2696 src/FLTK/fl_callbacks.cpp:2749 +msgid "" +"Primary and secondary audio device are both ASIO devices.\n" +"You can not use two ASIO devices at the same time.\n" +"Please select a different device.\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2717 src/FLTK/fl_callbacks.cpp:4155 +msgid "" +"butt could not open selected audio device.\n" +"Please try another device.\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2732 +#, c-format +msgid "" +"Primary device:\n" +"%s\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2769 +msgid "" +"butt could not open secondary audio device.\n" +"Please try another device.\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2783 +#, c-format +msgid "" +"Secondary device:\n" +"%s\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2894 src/FLTK/fl_callbacks.cpp:3072 +msgid "" +"MP3 encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2915 +msgid "Stream codec set to mp3" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2927 src/FLTK/fl_callbacks.cpp:3112 +msgid "" +"OGG Vorbis encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2948 +msgid "Stream codec set to ogg/vorbis" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2959 src/FLTK/fl_callbacks.cpp:3151 +msgid "" +"Opus encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2979 +msgid "Stream codec set to opus" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3011 src/FLTK/fl_callbacks.cpp:3213 +msgid "" +"AAC encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3032 +msgid "Stream codec set to aac" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3042 src/FLTK/fl_callbacks.cpp:3252 +msgid "ERROR: While initializing flac settings" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3060 +msgid "Stream codec set to flac" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3101 +msgid "Record codec set to mp3" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3140 +msgid "Record codec set to ogg/vorbis" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3179 +msgid "Record codec set to opus" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3242 +msgid "Record codec set to aac" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3278 +msgid "Record codec set to flac" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3294 +msgid "Record codec set to wav" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3329 +msgid "Select certificate file..." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3334 src/FLTK/fl_callbacks.cpp:3355 +#: src/FLTK/fl_callbacks.cpp:3466 src/FLTK/fl_callbacks.cpp:3556 +#: src/FLTK/fl_callbacks.cpp:4109 src/FLTK/fl_callbacks.cpp:4133 +#: src/FLTK/fl_callbacks.cpp:4257 +#, c-format +msgid "ERROR: %s" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3347 +msgid "Select certificate directory..." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3458 +msgid "Record to..." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3483 +msgid "File splitting only works if recording is active." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3552 +msgid "Select Songfile" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3657 +msgid "Gain control is disabled. Enable in Settings->GUI" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3718 +msgid "select background color" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3728 +msgid "select text color" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3761 src/FLTK/fl_callbacks.cpp:3765 +#: src/FLTK/fl_callbacks.cpp:3774 src/FLTK/fl_callbacks.cpp:3778 +msgid "Value must be a number between -54 and 0" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3788 +msgid "Please restart butt to apply new language." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:3867 src/FLTK/fl_callbacks.cpp:3872 +#: src/FLTK/fl_callbacks.cpp:3882 src/FLTK/fl_callbacks.cpp:3887 +msgid "Value must be a number between -90.0 and 0" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:4082 +msgid "Recording volume" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:4103 +msgid "Export to..." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:4146 +#, c-format +msgid "Could not import config %s" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:4160 +#, c-format +msgid "Config imported %s" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:4234 +msgid "" +"Could not get update information.\n" +"Reason: Network error" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:4237 +msgid "" +"Could not get update information.\n" +"Reason: Unknown answer from server" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:4240 +msgid "You have the latest version!" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:4243 +msgid "" +"Could not get update information.\n" +"Reason: Unknown" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:4251 +msgid "Select logfile..." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:4273 +msgid "" +"butt is currently streaming.\n" +"Do you really want to close butt now?" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:4279 +msgid "" +"butt is currently recording.\n" +"Do you really want to close butt now?" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:4354 +msgid "The URL must start with either http:// or https://" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:4366 +msgid "Value must be a number between 1 and 1000" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:5228 src/FLTK/fl_callbacks.cpp:5263 +#: src/FLTK/fl_callbacks.cpp:5298 src/FLTK/fl_callbacks.cpp:5333 +#: src/FLTK/fl_callbacks.cpp:5368 src/FLTK/fl_callbacks.cpp:5859 +#: src/FLTK/fl_callbacks.cpp:5894 src/FLTK/fl_callbacks.cpp:5929 +#: src/FLTK/fl_callbacks.cpp:5964 src/FLTK/fl_callbacks.cpp:5999 +msgid "The encoder could not be initialized with the provided parameters." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:5246 src/FLTK/fl_callbacks.cpp:5877 +msgid "The value must be between 0.001 kHz and 50 kHz" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:5281 src/FLTK/fl_callbacks.cpp:5316 +#: src/FLTK/fl_callbacks.cpp:5351 src/FLTK/fl_callbacks.cpp:5912 +#: src/FLTK/fl_callbacks.cpp:5947 src/FLTK/fl_callbacks.cpp:5982 +msgid "The value must be between 0.001 kHz and 16 kHz" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:6328 +msgid "MIDI device could not be opened." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:6334 +#, c-format +msgid "" +"MIDI device:\n" +"%s\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:6339 +msgid "MIDI device could not be started." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:6344 +msgid "MIDI support disabled\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:6406 +msgid "The CC value must be between 0 and 127" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:6429 +msgid "Waiting..." +msgstr "" + +#: src/FLTK/fl_funcs.cpp:193 +msgid "Disabled" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:335 +#, c-format +msgid "%d seconds" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:386 +msgid "Not supported on Windows" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:808 +msgid "Start/Stop broadcasting" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:809 +msgid "Start/Stop recording" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:811 +msgid "Streaming Gain" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:812 +msgid "Recording Gain" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:813 +msgid "Primary Device Gain" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:814 +msgid "Secondary Device Gain" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:815 +msgid "Cross fader" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:816 +msgid "Mute/Unmute Primary Device" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:817 +msgid "Mute/Unmute Secondary Device" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:818 +msgid "Start broadcasting" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:819 +msgid "Stop broadcasting" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:820 +msgid "Start recording" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:821 +msgid "Stop recording" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:870 +msgid "dev. not supported" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:1087 +#, c-format +msgid "" +"Could not create recording folder:\n" +"%s\n" +"Please make sure the folder contains only valid format specifiers." +msgstr "" + +#: src/FLTK/fl_funcs.cpp:1102 +#, c-format +msgid "Could not create recording folder %s\n" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:1111 +#, c-format +msgid "" +"Could not create recording file:\n" +"%s\n" +"Please make sure the filename contains only valid format specifiers." +msgstr "" + +#: src/FLTK/fl_funcs.cpp:1157 +msgid "Could not find a valid filename" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:1462 +msgid "TRUST" +msgstr "" + +#: src/icecast.cpp:90 +msgid "" +"\n" +"connect: Could not create network socket" +msgstr "" + +#: src/icecast.cpp:102 +msgid "" +"\n" +"connect: Error resolving server address" +msgstr "" + +#: src/icecast.cpp:142 +msgid "" +"\n" +"connect: SSL connection timed out. Trying again..." +msgstr "" + +#: src/icecast.cpp:149 +#, c-format +msgid "" +"SSL/TLS certificate verification failed\n" +"Reason: %s\n" +"\n" +"Do you still want to trust this certificate?\n" +"Trusting will be permanent and can be revoked\n" +"in the server settings." +msgstr "" + +#: src/icecast.cpp:164 +#, c-format +msgid "" +"\n" +"connect: SSL connection failed\n" +"Reason: %s" +msgstr "" + +#: src/icecast.cpp:320 +msgid "" +"\n" +"connect: connection timed out. Trying again..." +msgstr "" + +#: src/icecast.cpp:373 +msgid "" +"\n" +"connect: server answered with 400!\n" +msgstr "" + +#: src/icecast.cpp:379 +msgid "" +"\n" +"connect: invalid user/password!\n" +msgstr "" + +#: src/icecast.cpp:402 +msgid "" +"\n" +"connect: server answered with 404!\n" +msgstr "" + +#: src/icecast.cpp:409 +#, c-format +msgid "" +"\n" +"connect: server answered with %d!\n" +msgstr "" + +#: src/icecast.cpp:434 +msgid "" +"\n" +"ERROR: Opus is not supported by your\n" +"Icecast server (>=1.4.0 required)!\n" +msgstr "" + +#: src/icecast.cpp:507 +msgid "" +"\n" +"update_song: could not create network socket" +msgstr "" + +#: src/icecast.cpp:511 +msgid "" +"\n" +"update_song: error resolving server address" +msgstr "" + +#: src/lame_encode.cpp:74 +#, c-format +msgid "unable to init lame params %d" +msgstr "" + +#: src/port_audio.cpp:131 +#, c-format +msgid "" +"PortAudio init failed:\n" +"%s\n" +msgstr "" + +#: src/port_audio.cpp:180 +msgid "ERROR: no sound device with input channels found" +msgstr "" + +#: src/port_audio.cpp:198 src/port_audio.cpp:289 src/port_audio.cpp:1331 +#: src/port_midi.cpp:177 +#, c-format +msgid "Error getting device Info (%d)" +msgstr "" + +#: src/port_audio.cpp:241 +#, c-format +msgid "" +"Samplerate not supported: %dHz\n" +"Using default samplerate: %dHz" +msgstr "" + +#: src/port_audio.cpp:258 src/port_audio.cpp:360 +#, c-format +msgid "PA: Format not supported: %s\n" +msgstr "" + +#: src/port_audio.cpp:268 +#, c-format +msgid "error opening sound device: %s" +msgstr "" + +#: src/port_audio.cpp:326 +msgid "The selected secondary audio device can not be used" +msgstr "" + +#: src/port_audio.cpp:343 src/port_audio.cpp:1452 src/port_audio.cpp:1469 +msgid "ERROR: Could not initialize samplerate converter" +msgstr "" + +#: src/port_audio.cpp:354 +#, c-format +msgid "Samplerate of secondary device is resampled from %dHz to %dHz\n" +msgstr "" + +#: src/port_audio.cpp:381 +#, c-format +msgid "error opening secondary sound device: %s" +msgstr "" + +#: src/port_audio.cpp:921 +msgid "disconnected\n" +msgstr "" + +#: src/port_audio.cpp:949 +msgid "recording stopped" +msgstr "" + +#: src/port_midi.cpp:152 src/port_midi.cpp:211 src/port_midi.cpp:233 +#: src/port_midi.cpp:255 src/port_midi.cpp:282 src/port_midi.cpp:301 +#: src/port_midi.cpp:316 src/port_midi.cpp:341 src/port_midi.cpp:352 +msgid "Error: PortMidi was not initialized." +msgstr "" + +#: src/port_midi.cpp:262 +#, c-format +msgid "" +"Error: MIDI device %s could not be opened because no MIDI devices were found." +msgstr "" + +#: src/port_midi.cpp:269 +#, c-format +msgid "Error: MIDI device %s could not be found." +msgstr "" + +#: src/port_midi.cpp:286 +msgid "Error: MIDI thread already active." +msgstr "" + +#: src/port_midi.cpp:291 +msgid "Error: Could not start MIDI thread." +msgstr "" + +#: src/shoutcast.cpp:80 +msgid "" +"\n" +"Connect: Could not create network socket" +msgstr "" + +#: src/shoutcast.cpp:92 +msgid "" +"\n" +"Connect: Error resolving server address" +msgstr "" + +#: src/shoutcast.cpp:172 +msgid "" +"\n" +"connect: connection timed out. Trying again...\n" +msgstr "" + +#: src/shoutcast.cpp:189 +msgid "" +"\n" +"Connect: Invalid password!\n" +msgstr "" + +#: src/shoutcast.cpp:238 +msgid "" +"\n" +"Update song: Could not create network socket" +msgstr "" + +#: src/shoutcast.cpp:242 +msgid "" +"\n" +"Update song: Error resolving server address" +msgstr "" + +#: src/tls.cpp:159 +msgid "check_host: could not read host name from cert" +msgstr "" + +#: src/tls.cpp:194 +msgid "check_cert: No peer certificate available" +msgstr "" + +#: src/tls.cpp:207 +msgid "check_cert: X509_check_host failed" +msgstr "" + +#: src/tls.cpp:213 +msgid "check_cert: check_host failed" +msgstr "" + +#: src/tls.cpp:229 +msgid "calc_cert_hash: No peer certificate available" +msgstr "" + +#: src/tls.cpp:236 +msgid "calc_cert_hash: Hash calculation failed" +msgstr "" + +#: src/tls.cpp:305 +msgid "tls_setup: Could not set cipher list" +msgstr "" + +#: src/tls.cpp:318 +msgid "tls_setup: SSL_new failed" +msgstr "" + +#: src/tls.cpp:324 +msgid "tls_setup: Could not bind socket to SSL" +msgstr "" + +#: src/tls.cpp:338 +msgid "tls_setup: SSL_connect read timeout" +msgstr "" + +#: src/tls.cpp:344 +msgid "tls_setup: SSL_connect write timeout" +msgstr "" + +#: src/tls.cpp:361 +msgid "tls_setup: Cert hash could not be calculated" +msgstr "" + +#: src/tls.cpp:385 +msgid "tls_send: read timeout" +msgstr "" + +#: src/tls.cpp:392 +msgid "tls_send: write timeout" +msgstr "" + +#: src/tls.cpp:418 +msgid "tls_recv: read timeout" +msgstr "" + +#: src/tls.cpp:425 +msgid "tls_recv: write timeout" +msgstr "" diff --git a/po/de.gmo b/po/de.gmo new file mode 100644 index 0000000..ff44de3 Binary files /dev/null and b/po/de.gmo differ diff --git a/po/de.po b/po/de.po new file mode 100644 index 0000000..e7095e4 --- /dev/null +++ b/po/de.po @@ -0,0 +1,3253 @@ +# German translations for butt-0.1.41 package. +# Copyright (C) Daniel Nöthen +# This file is distributed under the same license as the butt package. +# Daniel Nöthen , 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: butt 1.45.0\n" +"Report-Msgid-Bugs-To: butt@danielnoethen.de\n" +"POT-Creation-Date: 2025-04-19 14:55+0200\n" +"PO-Revision-Date: 2025-04-19 15:19+0200\n" +"Last-Translator: Daniel Nöthen \n" +"Language-Team: German\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.0.1\n" + +#: src/AskForMicPermission.m:20 +msgid "Microphone access" +msgstr "Zugriff auf Mikrofon" + +#: src/AskForMicPermission.m:21 +msgid "" +"butt needs access to your microphone.\n" +"\n" +"Please go to\n" +"System Preferences->Privacy & Security->Microphone\n" +"and activate the check mark next to the butt entry." +msgstr "" +"butt benötigt Zugriff auf Dein Microfon\n" +"Bitte gehe zu\n" +"Systemeinstellungen->Sicherheit->Datenschutz->Mikrofon\n" +"Und aktiviere die Checkbox neben dem butt Eintrag." + +#: src/butt.cpp:219 +msgid "No home-directory found" +msgstr "Keine Heimatverzeichnis gefunden" + +#: src/butt.cpp:230 +#, c-format +msgid "" +"The shift key was held down during startup.\n" +"Do you want to start butt with a new configuration file?\n" +"This will overwrite your existing configuration file at\n" +"%s" +msgstr "" +"Die Shift Taste wurde während des Starts gedrückt.\n" +"Möchtest du butt mit einer neuen Konfiguration starten?\n" +"Dabei wird die existierende Konfigurationsdatei\n" +"%s\n" +"überschrieben" + +#: src/butt.cpp:233 +msgid "Start with old" +msgstr "Mit alter starten" + +#: src/butt.cpp:233 +msgid "Start with new" +msgstr "Mit neuer start" + +#: src/butt.cpp:236 src/butt.cpp:253 +#, c-format +msgid "" +"Could not create config %s\n" +"butt is going to close now" +msgstr "" +"Konfigurationsdatei %s konnte nicht erstellt werden\n" +"butt wird automatisch geschlossen" + +#: src/butt.cpp:242 +#, c-format +msgid "Reading config %s\n" +msgstr "Lese Konfiguration %s\n" + +#: src/butt.cpp:250 +#, c-format +msgid "Could not find config %s\n" +msgstr "Konnte Konfigurationsdatei %s nicht finden\n" + +#: src/butt.cpp:257 +#, c-format +msgid "" +"butt created a default config at\n" +"%s\n" +msgstr "" +"Konfigurationsdatei wurde erstellt\n" +"%s\n" + +#: src/butt.cpp:265 +msgid "" +"Could not find any audio device with input channels.\n" +"butt requires at least one audio device with input channels in order to " +"work.\n" +"This can either be a built-in audio device, an external audio device or a " +"virtual audio device.\n" +"\n" +"butt is going to close now." +msgstr "" +"Es konnte kein Aufnahmegerät gefunden werden.\n" +"butt benötigt ein Aufnahmegerät mit mindestens einem Eingangskanal, um " +"korrekt zu funktionieren.\n" +"Dabei kann es sich entweder um ein internes, externes oder virtuelles " +"Audiogerät handeln.\n" +"\n" +"butt wird jetzt beendet." + +#: src/butt.cpp:358 +#, c-format +msgid "Illegal argument: Threshold must be a non-negative number\n" +msgstr "Ungültiges Argument: Detektionsschwelle darf nicht negativ sein\n" + +#: src/butt.cpp:382 +#, c-format +msgid "%c threshold set to %0.1f\n" +msgstr "%c Detektionsschwelle auf %0.1f gesetzt\n" + +#: src/butt.cpp:464 +#, c-format +msgid "Illegal argument: Port must be a number between 1023 and 65535\n" +msgstr "" +"Ungültiges Argument: Port muss eine Nummer zwischen 1023 and 65535 sein\n" + +#: src/butt.cpp:472 src/butt.cpp:482 src/butt.cpp:489 src/butt.cpp:496 +#: src/butt.cpp:503 src/butt.cpp:510 src/butt.cpp:521 src/butt.cpp:540 +#: src/butt.cpp:550 src/butt.cpp:597 +#, c-format +msgid "" +"Warning: You may only pass one control option. Option -%c has been ignored.\n" +msgstr "" +"Warnung: Es darf nur ein Kommando angegeben werden. Kommando -%c wurde " +"ignoriert.\n" + +#: src/butt.cpp:559 +#, c-format +msgid "" +"\n" +"Options:\n" +"-h\tPrint this help text\n" +"-v\tPrint version information\n" +msgstr "" +"\n" +"Optionen:\n" +"-h\tHilfe ausgeben\n" +"-v\tVersion ausgeben\n" + +#: src/butt.cpp:563 +#, c-format +msgid "" +"\n" +"Options for operating mode:\n" +"-c\tPath to configuration file\n" +"-L\tPrint available audio devices\n" +"-A\tCommand server will be accessible from your network/internet (default: " +"localhost only)\n" +"-U\tCommand server will use UDP instead of TCP\n" +"-x\tDo not start a command server\n" +"-p\tPort where the command server shall listen to (default: 1256)\n" +msgstr "" +"\n" +"Optionen für den operativen Modus\n" +"-c\tPfad zur Konfigurationsdatei\n" +"-L\tVerfügbare Audiogeräte anzeigen\n" +"-A\tKommandos können über das Netzwerk/Internet empfangen werden (default: " +"nur von localhost)\n" +"-U\tKommando Server nutzt UDP anstatt TCP\n" +"-x\tKeinen Kommando Server starten\n" +"-p\tPort des Kommando Servers (default: 1256)\n" + +#: src/butt.cpp:572 +#, c-format +msgid "" +"\n" +"Options for control mode:\n" +"-s\tConnect to streaming server\n" +"-d\tDisconnect from streaming server\n" +"-r\tStart recording\n" +"-t\tStop recording\n" +"-n\tSplit recording\n" +"-q\tQuit butt\n" +"-u\tupdate song name\n" +"-S\tRequest status\n" +"-M\tSet streaming signal threshold (seconds)\n" +"-m\tSet streaming silence threshold (seconds)\n" +"-O\tSet recording signal threshold (seconds)\n" +"-o\tSet recording silence threshold (seconds)\n" +"-U\tConnect via UDP instead of TCP\n" +"-a\tAddress of the butt instance to be controlled (default: 127.0.0.1)\n" +"-p\tPort of the butt instance to be controlled (default: 1256)\n" +msgstr "" +"\n" +"Optionen für den Steuerungsmodus:\n" +"-s\tMit streaming server verbinden\n" +"-d\tVon streaming server trennen\n" +"-r\tAufnahme starten\n" +"-t\tAufnahme beenden\n" +"-n\tAufnahme aufteilen\n" +"-q\tbutt beenden\n" +"-u\tSongnamen updaten\n" +"-S\tStatus abrufen\n" +"-M\tStreaming Detektionsschwelle für vorhandenes Signal setzen (Sekunden)\n" +"-m\tStreaming Detektionsschwelle für abswesendes Signal setzen (Sekunden)\n" +"-O\tAufnahme Detektionsschwelle für vorhandenes Signal setzen (Sekunden)\n" +"-o\tAufnahme Detektionsschwelle für abwesendes Signal setzen(Sekunden)\n" +"-U\tNutze UDP anstatt TCP\n" +"-a\tAdresse des Kommando Servers (default: 127.0.0.1)\n" +"-p\tPort des Kommando Servers (default: 1256)\n" + +#: src/butt.cpp:591 +#, c-format +msgid "" +"Illegal option -%c.\n" +"Type butt -h to get a list of supported options.\n" +msgstr "" +"Ungültige Option -%c.\n" +"Gebe butt -h ein, um eine Liste aller gültigen Optionen zu erhalten.\n" + +#: src/butt.cpp:603 +#, c-format +msgid "Option -%c requires an argument\n" +msgstr "Option -%c benötigt ein Argument\n" + +#: src/butt.cpp:607 +#, c-format +msgid "Command line parsing failed\n" +msgstr "Ungültige Optionen angegeben\n" + +#: src/butt.cpp:630 +#, c-format +msgid "No butt instance running on %s at port %d\n" +msgstr "Keine butt Instanz an Adresse %s mit Port %d vorhanden\n" + +#: src/butt.cpp:635 +#, c-format +msgid "Error while sending command\n" +msgstr "Fehler beim Senden des Kommandos\n" + +#: src/butt.cpp:640 +#, c-format +msgid "Error: Did not receive response packet\n" +msgstr "Fehler: Keine Antwort vom Server erhalten\n" + +#: src/butt.cpp:653 +#, c-format +msgid "Error: You may only request one status packet per second\n" +msgstr "Fehler: Der Status darf nur einmal pro Sekunde abgefragt werden\n" + +#: src/butt.cpp:657 +#, c-format +msgid "Error: Did not receive status packet (UDP server not running?)\n" +msgstr "Error: Keine Antwort vom Server erhalten (UDP server nicht aktiv?)\n" + +#: src/butt.cpp:661 +#, c-format +msgid "Network error while receiving status packet: %d\n" +msgstr "Netzwerkfehler beim Empfangen des Status Pakets: %d\n" + +#: src/butt.cpp:665 +#, c-format +msgid "Error: Client and server versions do not match\n" +msgstr "Fehler: Client and Server Versionen sind unterschiedlich\n" + +#: src/butt.cpp:676 +#, c-format +msgid "" +"connected: %d\n" +"connecting: %d\n" +"recording: %d\n" +"signal present: %d\n" +"signal absent: %d\n" +msgstr "" +"Verbunden: %d\n" +"Verbinde: %d\n" +"Nehme auf: %d\n" +"Signal vorhanden: %d\n" +"Signal abwesend: %d\n" + +#: src/butt.cpp:681 +#, c-format +msgid "stream seconds: %lu\n" +msgstr "Stream Sekunden: %lu\n" + +#: src/butt.cpp:682 +#, c-format +msgid "stream kBytes: %lu\n" +msgstr "Stream kBytes: %lu\n" + +#: src/butt.cpp:683 +#, c-format +msgid "record seconds: %lu\n" +msgstr "Aufnahme Sekunden: %lu\n" + +#: src/butt.cpp:684 +#, c-format +msgid "record kBytes: %lu\n" +msgstr "Aufnahme kBytes: %lu\n" + +#: src/butt.cpp:685 +#, c-format +msgid "volume left: %0.1f\n" +msgstr "Lautstärke links: %0.1f\n" + +#: src/butt.cpp:686 +#, c-format +msgid "volume right: %0.1f\n" +msgstr "Lautstärke rechts: %0.1f\n" + +#: src/butt.cpp:687 +#, c-format +msgid "song: %s\n" +msgstr "song: %s\n" + +#: src/butt.cpp:688 +#, c-format +msgid "record path: %s\n" +msgstr "Aufnahmepfad: %s\n" + +#: src/butt.cpp:689 +#, c-format +msgid "listeners: %d\n" +msgstr "Zuhörer: %d\n" + +#: src/butt.cpp:703 +msgid "" +"The control key was held down during startup.\n" +"butt will start without opening an audio device.\n" +"Please select your preferred audio device in settings->audio" +msgstr "" +"Die STRG-Taste würde während des startens gedrückt.\n" +"butt wird daher kein Audiogerät öffnen.\n" +"Bitte wählen sie ihr bevorzugtes Audiogerät in Einstellungen->Audio aus" + +#: src/butt.cpp:712 +msgid "" +"PortAudio init failed\n" +"butt is going to close now" +msgstr "" +"PortAudio Initzialisierung fehlgeschlagen\n" +"butt wird automatisch geschlossen" + +#: src/butt.cpp:747 src/FLTK/fl_timer_funcs.cpp:476 +#: src/FLTK/fl_callbacks.cpp:123 src/FLTK/fl_callbacks.cpp:899 +#: src/FLTK/fl_callbacks.cpp:977 src/FLTK/fl_funcs.cpp:1047 +msgid "idle" +msgstr "Warte" + +#: src/butt.cpp:780 +#, c-format +msgid "" +"Starting %s\n" +"Written by Daniel Nöthen\n" +"iPhone/iPad client: https://izicast.de\n" +"Donate: paypal@danielnoethen.de\n" +msgstr "" +"Starte %s\n" +"Entwickelt von Daniel Nöthen\n" +"iPhone/iPad client: https://izicast.de\n" +"Spende: paypal@danielnoethen.de\n" + +#: src/butt.cpp:792 src/butt.cpp:793 src/cfg.cpp:577 src/port_audio.cpp:1314 +#: src/port_audio.cpp:1315 +msgid "Default PCM device (default)" +msgstr "Default PCM device (default)" + +#: src/butt.cpp:796 src/butt.cpp:797 src/cfg.cpp:578 +#: src/FLTK/fl_callbacks.cpp:2820 src/FLTK/fl_funcs.cpp:227 +msgid "None" +msgstr "Keins" + +#: src/butt.cpp:800 +msgid "" +"Could not open audio device.\n" +"Please select your preferred audio device in settings->audio" +msgstr "" +"Audiogerät konnte nicht geöffnet werden.\n" +"Bitte wählen sie ihr bevorzugtes Audiogerät in Einstellungen->Audio aus" + +#: src/butt.cpp:803 +msgid "" +"butt could not open previously used audio device.\n" +"The system default audio device will be used.\n" +msgstr "" +"Das zuvor genutzte Audiogerät konnte nicht geöffnet werden.\n" +"butt wird das standard Audiogerät verwenden. \n" + +#: src/butt.cpp:830 +#, c-format +msgid "Command server listening on port %d\n" +msgstr "Command server listening on port %d\n" + +#: src/butt.cpp:837 +#, c-format +msgid "Warning: could not start command server on port %d\n" +msgstr "Warnung: Konnte Kommandoserver nicht an port %d starten\n" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:4225 +#, c-format +msgid "" +"New version available: %s\n" +"You have version %s" +msgstr "" +"Neue Version verfügbar: %s\n" +"Du hast Version Version %s" + +#: src/butt.cpp:853 +msgid "Don't ask again" +msgstr "Nicht erneut fragen" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:1594 +#: src/FLTK/fl_callbacks.cpp:4225 +msgid "Cancel" +msgstr "Abbrechen" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:4225 +msgid "Get new version" +msgstr "Neue version holen" + +#: src/butt.cpp:874 +#, c-format +msgid "Could not initialize PortMidi: %s" +msgstr "PortMidi konnte nicht initialisiert werden: %s" + +#: src/butt.cpp:902 +msgid "butt was built without WebRTC support" +msgstr "BUTT wurde ohne WebRTC Unterstützung kompiliert" + +#: src/cfg.cpp:55 +#, c-format +msgid "Could not write to file: %s" +msgstr "Konnte Datei nicht schreiben: %s" + +#: src/cfg.cpp:550 +#, c-format +msgid "Config written to %s" +msgstr "Konfiguration gespeichert nach %s" + +#: src/cfg.cpp:674 +msgid "" +"error while parsing config. Missing main/server entry.\n" +"butt will start with default settings" +msgstr "" +"Fehler beim Lesen der Konfigurationsdatei. Ein main/server Eintrag fehlt.\n" +"butt wird mit den Standardeinstellungen gestartet" + +#: src/cfg.cpp:680 +msgid "" +"error while parsing config. Missing main/srv_ent entry.\n" +"butt will start with default settings" +msgstr "" +"Fehler beim Lesen der Konfigurationsdatei. Ein main/srv_ent Eintrag fehlt.\n" +"butt wird mit den Standardeinstellungen gestartet" + +#: src/cfg.cpp:699 +#, c-format +msgid "" +"error while parsing config. Missing type entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"Fehler beim Lesen der Konfigurationsdatei. Der Type für server \"%s\" " +"fehlt.\n" +"butt wird mit den Standardeinstellungen gestartet" + +#: src/cfg.cpp:707 +#, c-format +msgid "" +"error while parsing config. Missing address entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"Fehler beim Lesen der Konfigurationsdatei. Für den server \"%s\" existiert " +"keine Adresse.\n" +"butt wird mit den Standardeinstellungen gestartet" + +#: src/cfg.cpp:716 +#, c-format +msgid "" +"error while parsing config. Missing port entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"Fehler beim Lesen der Konfigurationsdatei. Der Port für server \"%s\" " +"fehlt.\n" +"butt wird mit den Standardeinstellungen gestartet" + +#: src/cfg.cpp:725 +#, c-format +msgid "" +"error while parsing config. Missing password entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"Fehler beim Lesen der Konfigurationsdatei. Das Password für server \"%s\" " +"fehlt.\n" +"butt wird mit den Standardeinstellungen gestartet" + +#: src/cfg.cpp:734 +#, c-format +msgid "" +"error while parsing config. Missing mount entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"Fehler beim Lesen der Konfigurationsdatei. Der Mountpoint für server \"%s\" " +"fehlt.\n" +"butt wird mit den Standardeinstellungen gestartet" + +#: src/cfg.cpp:790 +msgid "" +"error while parsing config. Missing main/icy entry.\n" +"butt will start with default settings" +msgstr "" +"Fehler beim Lesen der Konfigurationsdatei. Es fehlt ein main/icy Eintrag.\n" +"butt wird mit den Standardeinstellungen gestartet" + +#: src/cfg.cpp:795 +msgid "" +"error while parsing config. Missing main/icy_ent entry.\n" +"butt will start with default settings" +msgstr "" +"Fehler beim Lesen der Konfigurationsdatei. Es fehlt ein main/icy_ent " +"Eintrag.\n" +"butt wird mit den Standardeinstellungen gestartet" + +#: src/cfg.cpp:821 +#, c-format +msgid "" +"error while parsing config. Missing pub entry for icy \"%s\".\n" +"butt will start with default settings" +msgstr "" +"Fehler beim Lesen der Konfigurationsdatei. Es fehlt der pub Eintrag für icy " +"\"%s\".\n" +"butt wird mit den Standardeinstellungen gestartet" + +#: src/FLTK/flgui.cpp:3088 +msgid "Bitcoin address has been copied to clipboard." +msgstr "Bitcoin Adresse wurde in die Zwischenablage kopiert." + +#: src/FLTK/flgui.cpp:3099 +msgid "Litecoin address has been copied to clipboard." +msgstr "Litecoin Adresse wurde in die Zwischenablage kopiert." + +#: src/FLTK/flgui.cpp:3110 +msgid "Monero address has been copied to clipboard." +msgstr "Monero Adresse wurde in die Zwischenablage kopiert." + +#: src/FLTK/flgui.cpp:4041 +msgid "press left mouse to toggle lcd info" +msgstr "Linke Maustaste betätigen, um Anzeige zu ändern" + +#: src/FLTK/flgui.cpp:4053 src/FLTK/fl_callbacks.cpp:4078 +msgid "Streaming volume" +msgstr "Stream Lautstärke" + +#: src/FLTK/flgui.cpp:4057 +msgid "Mixer" +msgstr "Mischpult" + +#: src/FLTK/flgui.cpp:4058 +msgid "show/hide mixer window" +msgstr "Mischer anzeigen/verbergen" + +#: src/FLTK/flgui.cpp:4065 +msgid "@circle" +msgstr "@circle" + +#: src/FLTK/flgui.cpp:4066 +msgid "start/stop recording" +msgstr "Aufnahme starten/stoppen" + +#: src/FLTK/flgui.cpp:4077 +msgid "@square" +msgstr "@square" + +#: src/FLTK/flgui.cpp:4078 +msgid "disconnect from server" +msgstr "Von Server trennen" + +#: src/FLTK/flgui.cpp:4089 +msgid "@>" +msgstr "@>" + +#: src/FLTK/flgui.cpp:4090 +msgid "connect to server" +msgstr "Mit Server verbinden" + +#: src/FLTK/flgui.cpp:4106 src/FLTK/flgui.cpp:4438 src/FLTK/flgui.cpp:4657 +#: src/FLTK/fl_callbacks.cpp:4077 +msgid "Streaming" +msgstr "Streaming" + +#: src/FLTK/flgui.cpp:4110 src/FLTK/flgui.cpp:4469 src/FLTK/flgui.cpp:4771 +msgid "Recording" +msgstr "Aufnahme" + +#: src/FLTK/flgui.cpp:4140 +msgid "Settings" +msgstr "Einstellungen" + +#: src/FLTK/flgui.cpp:4141 +msgid "show/hide config window" +msgstr "Einstellungen anzeigen/verbergen" + +#: src/FLTK/flgui.cpp:4148 src/FLTK/fl_callbacks.cpp:1098 +msgid "Show log" +msgstr "Log anzeigen" + +#: src/FLTK/flgui.cpp:4149 +msgid "show/hide info window" +msgstr "Informationsfenster anzeigen/verbergen" + +#: src/FLTK/flgui.cpp:4156 +msgid "-24 dB" +msgstr "-24 dB" + +#: src/FLTK/flgui.cpp:4159 +msgid "Gain" +msgstr "Verstärkung" + +#: src/FLTK/flgui.cpp:4160 src/FLTK/fl_callbacks.cpp:3663 +#: src/FLTK/fl_funcs.cpp:810 +msgid "Master Gain" +msgstr "Haupt Verstärkung" + +#: src/FLTK/flgui.cpp:4178 +msgid "+24 dB" +msgstr "+24 dB" + +#: src/FLTK/flgui.cpp:4185 +msgid "Listeners: 0" +msgstr "Zuhörer: 0" + +#: src/FLTK/flgui.cpp:4200 +msgid "butt settings" +msgstr "butt Einstellungen" + +#: src/FLTK/flgui.cpp:4213 +msgid "Main" +msgstr "Main" + +#: src/FLTK/flgui.cpp:4215 +msgid "Server Settings" +msgstr "Server Einstellungen" + +#: src/FLTK/flgui.cpp:4218 +msgid "Server" +msgstr "Server" + +#: src/FLTK/flgui.cpp:4219 +msgid "Server to connect to" +msgstr "Mit diesem Server verbinden" + +#: src/FLTK/flgui.cpp:4224 src/FLTK/flgui.cpp:4245 +msgid "ADD" +msgstr "NEU" + +#: src/FLTK/flgui.cpp:4225 src/FLTK/flgui.cpp:5550 +msgid "Add server" +msgstr "Neuer Server" + +#: src/FLTK/flgui.cpp:4229 src/FLTK/flgui.cpp:4250 +msgid "EDIT" +msgstr "EDIT" + +#: src/FLTK/flgui.cpp:4230 +msgid "Edit selected server" +msgstr "Server editieren" + +#: src/FLTK/flgui.cpp:4234 src/FLTK/flgui.cpp:4255 +msgid "DEL" +msgstr "ENTF" + +#: src/FLTK/flgui.cpp:4235 +msgid "Delete selected server" +msgstr "Server löschen" + +#: src/FLTK/flgui.cpp:4239 +msgid "Stream Infos" +msgstr "Stream Infos" + +#: src/FLTK/flgui.cpp:4240 +msgid "Stream info that shall be used" +msgstr "Zu verwendende Stream Info" + +#: src/FLTK/flgui.cpp:4246 src/FLTK/flgui.cpp:5671 +msgid "Add stream info" +msgstr "Neue Stream Infos" + +#: src/FLTK/flgui.cpp:4251 +msgid "Edit stream info" +msgstr "Stream info editieren" + +#: src/FLTK/flgui.cpp:4256 +msgid "Delete stream info" +msgstr "Stream info löschen" + +#: src/FLTK/flgui.cpp:4262 +msgid "Log File" +msgstr "Logdatei" + +#: src/FLTK/flgui.cpp:4266 +msgid "Log file path" +msgstr "Logdatei Pfad" + +#: src/FLTK/flgui.cpp:4271 +msgid "Select log file" +msgstr "Logdatei wählen" + +#: src/FLTK/flgui.cpp:4278 +msgid "Configuration" +msgstr "Konfiguration" + +#: src/FLTK/flgui.cpp:4281 src/FLTK/fl_callbacks.cpp:4128 +msgid "Import..." +msgstr "Import..." + +#: src/FLTK/flgui.cpp:4282 +msgid "Import settings from config file" +msgstr "Einstellungen importieren" + +#: src/FLTK/flgui.cpp:4286 src/FLTK/flgui.cpp:5615 src/FLTK/flgui.cpp:5717 +msgid "&Save" +msgstr "Speichern" + +#: src/FLTK/flgui.cpp:4287 +msgid "Save settings" +msgstr "Einst. speichern" + +#: src/FLTK/flgui.cpp:4291 +msgid "Export..." +msgstr "Export..." + +#: src/FLTK/flgui.cpp:4292 +msgid "export settings" +msgstr "Einstellungen exportieren" + +#: src/FLTK/flgui.cpp:4298 +msgid "Butt Agent" +msgstr "Butt Agent" + +#: src/FLTK/flgui.cpp:4301 +msgid "Start agent at startup" +msgstr "Agent beim Start starten" + +#: src/FLTK/flgui.cpp:4302 +msgid "Start the butt agent when butt starts" +msgstr "Agent beim Starten von butt starten" + +#: src/FLTK/flgui.cpp:4306 src/FLTK/flgui.cpp:4307 +msgid "Minimize butt to tray" +msgstr "In Tray minimieren" + +#: src/FLTK/flgui.cpp:4311 +msgid "Start Agent" +msgstr "Agent starten" + +#: src/FLTK/flgui.cpp:4312 +msgid "Start the butt agent now" +msgstr "Agent jetzt starten" + +#: src/FLTK/flgui.cpp:4316 +msgid "Stop Agent" +msgstr "Agent beenden" + +#: src/FLTK/flgui.cpp:4317 +msgid "Stop the butt agent" +msgstr "Agent jetzt beenden" + +#: src/FLTK/flgui.cpp:4323 +msgid "Updates" +msgstr "Aktualisierung" + +#: src/FLTK/flgui.cpp:4326 +msgid "Check at startup" +msgstr "Beim Starten prüfen" + +#: src/FLTK/flgui.cpp:4327 +msgid "Check for updates at start" +msgstr "Beim Starten prüfen" + +#: src/FLTK/flgui.cpp:4331 +msgid "Check now" +msgstr "Prüfen" + +#: src/FLTK/flgui.cpp:4332 +msgid "Check if a new version is available" +msgstr "Prüft ob eine neue Version verfügbar ist" + +#: src/FLTK/flgui.cpp:4338 +msgid "Help" +msgstr "Hilfe" + +#: src/FLTK/flgui.cpp:4341 +msgid "Manual" +msgstr "Manuell" + +#: src/FLTK/flgui.cpp:4345 +msgid " YouTube" +msgstr " YouTube" + +#: src/FLTK/flgui.cpp:4355 +msgid "Audio" +msgstr "Audio" + +#: src/FLTK/flgui.cpp:4357 +msgid "Main Audio Settings" +msgstr "Audio Einstellungen" + +#: src/FLTK/flgui.cpp:4360 +msgid "Channel mode" +msgstr "Kanalmodus" + +#: src/FLTK/flgui.cpp:4361 +msgid "Select input channel" +msgstr "Eingangskanal wählen" + +#: src/FLTK/flgui.cpp:4374 +msgid "Samplerate" +msgstr "Samplerate" + +#: src/FLTK/flgui.cpp:4375 +msgid "Select input sample rate" +msgstr "Samplerate wählen" + +#: src/FLTK/flgui.cpp:4380 +msgid "Remember Device by" +msgstr "Audiogerät speichern als" + +#: src/FLTK/flgui.cpp:4383 +msgid "ID" +msgstr "ID" + +#: src/FLTK/flgui.cpp:4388 +msgid "Name" +msgstr "Name" + +#: src/FLTK/flgui.cpp:4395 +msgid "Update devices" +msgstr "Geräte aktualisieren" + +#: src/FLTK/flgui.cpp:4396 +msgid "Rescan audio devices" +msgstr "Nach neuen Audiogeräten suchen" + +#: src/FLTK/flgui.cpp:4400 +msgid "Primary Audio Device" +msgstr "Primäres Audiogerät" + +#: src/FLTK/flgui.cpp:4401 +msgid "Select your primary sound card device" +msgstr "Wähle dein primäres Audiogerät" + +#: src/FLTK/flgui.cpp:4406 src/FLTK/flgui.cpp:4424 +msgid "Left" +msgstr "Links" + +#: src/FLTK/flgui.cpp:4407 src/FLTK/flgui.cpp:4425 +msgid "Select left audio channel" +msgstr "Wähle den linken Audio Kanal" + +#: src/FLTK/flgui.cpp:4412 src/FLTK/flgui.cpp:4430 +msgid "Right" +msgstr "Rechts" + +#: src/FLTK/flgui.cpp:4413 src/FLTK/flgui.cpp:4431 +msgid "Select right audio channel" +msgstr "Wähle den rechten Audio Kanal" + +#: src/FLTK/flgui.cpp:4418 +msgid "Secondary Audio Device" +msgstr "Sekundäres Audiogerät" + +#: src/FLTK/flgui.cpp:4419 +msgid "Select your secondary sound card device" +msgstr "Wähle dein sekundäres Audiogerät" + +#: src/FLTK/flgui.cpp:4441 src/FLTK/flgui.cpp:4472 +msgid "Codec" +msgstr "Codec" + +#: src/FLTK/flgui.cpp:4442 +msgid "Select streaming codec" +msgstr "Stream Codec wählen" + +#: src/FLTK/flgui.cpp:4455 src/FLTK/flgui.cpp:4486 +msgid "Bitrate" +msgstr "Bitrate" + +#: src/FLTK/flgui.cpp:4456 +msgid "Select streaming bitrate" +msgstr "Stream Bitrate wählen" + +#: src/FLTK/flgui.cpp:4473 +msgid "Select recording codec" +msgstr "Aufnahme Codec wählen" + +#: src/FLTK/flgui.cpp:4487 +msgid "Select recording bitrate" +msgstr "Aufnahme Bitrate wählen" + +#: src/FLTK/flgui.cpp:4499 +msgid "Advanced..." +msgstr "Erweitert..." + +#: src/FLTK/flgui.cpp:4505 +msgid "Buffer (ms)" +msgstr "Puffer (ms)" + +#: src/FLTK/flgui.cpp:4514 +msgid "Resample Quality" +msgstr "Resample Qualtät" + +#: src/FLTK/flgui.cpp:4529 +msgid "Signal detection levels" +msgstr "Detektions Pegel" + +#: src/FLTK/flgui.cpp:4532 +msgid "Signal present" +msgstr "Signal vorhanden" + +#: src/FLTK/flgui.cpp:4539 src/FLTK/flgui.cpp:4549 +msgid "dB" +msgstr "dB" + +#: src/FLTK/flgui.cpp:4542 +msgid "Signal absent" +msgstr "Signal abwesend" + +#: src/FLTK/flgui.cpp:4556 src/FLTK/flgui.cpp:4833 src/FLTK/flgui.cpp:5084 +msgid "Stream" +msgstr "Stream" + +#: src/FLTK/flgui.cpp:4558 +msgid "Update song name from file" +msgstr "Song von Datei aktualisieren" + +#: src/FLTK/flgui.cpp:4562 +msgid "Filename that holds the current song name" +msgstr "Datei mit aktuellem Songnamen" + +#: src/FLTK/flgui.cpp:4568 +msgid "Select file that holds the current song name" +msgstr "Datei mit Songnamen auswählen" + +#: src/FLTK/flgui.cpp:4573 src/FLTK/flgui.cpp:4606 src/FLTK/flgui.cpp:4724 +msgid "Activate" +msgstr "Aktivieren" + +#: src/FLTK/flgui.cpp:4574 src/FLTK/flgui.cpp:4579 +msgid "Activate auto update song name from file" +msgstr "Aktualisierung des Songnamens von Datei aktivieren" + +#: src/FLTK/flgui.cpp:4578 +msgid "Read last line instead of first" +msgstr "Lese letzte Zeile der Datei" + +#: src/FLTK/flgui.cpp:4585 +msgid "Update song name from application" +msgstr "Song von Applikation aktualisieren" + +#: src/FLTK/flgui.cpp:4589 +msgid "Changes the song through an running application" +msgstr "Song wird durch ein Musikprogramm geändert" + +#: src/FLTK/flgui.cpp:4594 +msgid "Title - Artist" +msgstr "Titel - Artist" + +#: src/FLTK/flgui.cpp:4599 +msgid "Artist - Title" +msgstr "Artist - Titel" + +#: src/FLTK/flgui.cpp:4612 +msgid "Update song name manually" +msgstr "Song manuell einstellen" + +#: src/FLTK/flgui.cpp:4616 +msgid "Current song name" +msgstr "Aktueller Song" + +#: src/FLTK/flgui.cpp:4622 src/FLTK/fl_callbacks.cpp:1594 +msgid "OK" +msgstr "OK" + +#: src/FLTK/flgui.cpp:4623 +msgid "Send current song name to the server" +msgstr "Aktuellen Song dem Server mitteilen" + +#: src/FLTK/flgui.cpp:4631 +msgid "Update song name delay" +msgstr "Song update Verzögerung" + +#: src/FLTK/flgui.cpp:4635 +msgid "Introduces a delay until the song name is actually updated" +msgstr "Verzögert die Aktualisierung des song namens" + +#: src/FLTK/flgui.cpp:4642 +msgid "Extend song name" +msgstr "Song erweitern" + +#: src/FLTK/flgui.cpp:4645 +msgid "Prefix:" +msgstr "Präfix:" + +#: src/FLTK/flgui.cpp:4650 +msgid "Suffix:" +msgstr "Suffix:" + +#: src/FLTK/flgui.cpp:4660 src/FLTK/flgui.cpp:4789 +msgid "Start if signal is present for" +msgstr "Starten wenn Signal da für" + +#: src/FLTK/flgui.cpp:4661 +msgid "" +"Start streaming if the audio level exceeds the \"Signal present\" level set " +"in the \"Audio\" tab" +msgstr "" +"Starte den Stream wenn der Audiopegel den eingestellten Pegel im \"Audio\" " +"Tab überschreitet" + +#: src/FLTK/flgui.cpp:4670 src/FLTK/flgui.cpp:4683 src/FLTK/flgui.cpp:4702 +#: src/FLTK/flgui.cpp:4799 src/FLTK/flgui.cpp:4812 src/FLTK/flgui.cpp:5499 +msgid "seconds" +msgstr "Sekunden" + +#: src/FLTK/flgui.cpp:4673 src/FLTK/flgui.cpp:4802 +msgid "Stop if signal is absent for" +msgstr "Stoppen wenn Signal weg für" + +#: src/FLTK/flgui.cpp:4674 +msgid "" +"Stop streaming if the audio level falls below the \"Signal absent level set " +"in the \"Audio\" tab" +msgstr "" +"Beende den Stream wenn der Audiopegel den eingestellten Pegel im \"Audio\" " +"Tab unterschreitet" + +#: src/FLTK/flgui.cpp:4686 +msgid "Start streaming after launch" +msgstr "Nach Start mit server verbinden" + +#: src/FLTK/flgui.cpp:4687 +msgid "Connect automatically to a server after launch" +msgstr "Nach dem starten mit Server verbinden" + +#: src/FLTK/flgui.cpp:4691 +msgid "Force reconnecting" +msgstr "Erzwinge Neuverbindung" + +#: src/FLTK/flgui.cpp:4692 +msgid "If enabled butt keeps reconnecting regardless of the error message" +msgstr "" +"Bei Aktivierung versucht butt sich unabhängig von einer Fehlermeldung mit " +"dem Server neu zu verbinden" + +#: src/FLTK/flgui.cpp:4696 +msgid "Reconnect delay:" +msgstr "Neuverbindungsverzögerung:" + +#: src/FLTK/flgui.cpp:4707 +msgid "Update song name from URL" +msgstr "Song von URL aktualisieren" + +#: src/FLTK/flgui.cpp:4711 +msgid "URL to get song name from" +msgstr "Die URL, von welcher der Songname geholt werden soll" + +#: src/FLTK/flgui.cpp:4716 +msgid "Update interval" +msgstr "Aktualisierungsintervall" + +#: src/FLTK/flgui.cpp:4717 +msgid "Update interval in seconds" +msgstr "Aktualisierungsintervall in Sekunden" + +#: src/FLTK/flgui.cpp:4732 +msgid "Record" +msgstr "Aufnahme" + +#: src/FLTK/flgui.cpp:4734 +msgid "Record File Name:" +msgstr "Aufnahmedatei:" + +#: src/FLTK/flgui.cpp:4735 +msgid "Record file name" +msgstr "Aufnahmedatei" + +#: src/FLTK/flgui.cpp:4740 +msgid "Record Directory:" +msgstr "Aufnahmen Ordner:" + +#: src/FLTK/flgui.cpp:4741 +msgid "Directory of recordings" +msgstr "Order für Aufnahmen" + +#: src/FLTK/flgui.cpp:4747 +msgid "Select recording directory" +msgstr "Aufnahme Ordner wählen" + +#: src/FLTK/flgui.cpp:4752 +msgid "Split file" +msgstr "Datei aufteilen" + +#: src/FLTK/flgui.cpp:4755 +msgid "every" +msgstr "jede" + +#: src/FLTK/flgui.cpp:4758 +msgid "minutes" +msgstr "minuten" + +#: src/FLTK/flgui.cpp:4760 src/FLTK/flgui.cpp:4761 +msgid "Sync to full hour" +msgstr "Zur Stunde synchronisieren" + +#: src/FLTK/flgui.cpp:4765 +msgid "Split now" +msgstr "Aufteilen" + +#: src/FLTK/flgui.cpp:4774 src/FLTK/flgui.cpp:4775 +msgid "Start recording when connected" +msgstr "Aufnahme beginnen wenn verbunden" + +#: src/FLTK/flgui.cpp:4779 +msgid "Stop recording when disconnected" +msgstr "Aufnahme nach Trennung stoppen" + +#: src/FLTK/flgui.cpp:4780 +msgid "Start recording when disconnected" +msgstr "Aufnahme nach Trennung stoppen" + +#: src/FLTK/flgui.cpp:4784 src/FLTK/flgui.cpp:4785 +msgid "Start recording after launch" +msgstr "Aufnahme nach Start beginnen" + +#: src/FLTK/flgui.cpp:4790 +msgid "" +"Start recording if the audio level exceeds the \"Signal present\" level set " +"in the \"Audio\" tab" +msgstr "" +"Starte die Aufnahme wenn der Audiopegel den eingestellten Pegel im \"Audio\" " +"Tab überschreitet" + +#: src/FLTK/flgui.cpp:4803 +msgid "" +"Stop recording if the audio level falls below the \"Signal absent level set " +"in the \"Audio\" tab" +msgstr "" +"Beende die Aufnahme wenn der Audiopegel den eingestellten Pegel im \"Audio\" " +"Tab unterschreitet" + +#: src/FLTK/flgui.cpp:4815 +msgid "Overwrite existing files" +msgstr "Überschreibe existierende Dateien" + +#: src/FLTK/flgui.cpp:4823 +msgid "DSP" +msgstr "DSP" + +#: src/FLTK/flgui.cpp:4825 src/FLTK/flgui.cpp:5076 src/FLTK/flgui.cpp:6478 +msgid "Reset" +msgstr "Reset" + +#: src/FLTK/flgui.cpp:4830 +msgid "Equalizer" +msgstr "Equalizer" + +#: src/FLTK/flgui.cpp:4837 src/FLTK/flgui.cpp:5088 +msgid "Rec" +msgstr "Aufnahme" + +#: src/FLTK/flgui.cpp:4842 +msgid "Equalizer Preset" +msgstr "Equalizer Voreinstellung" + +#: src/FLTK/flgui.cpp:4854 src/FLTK/flgui.cpp:4876 src/FLTK/flgui.cpp:4898 +#: src/FLTK/flgui.cpp:4920 src/FLTK/flgui.cpp:4942 src/FLTK/flgui.cpp:4964 +#: src/FLTK/flgui.cpp:4986 src/FLTK/flgui.cpp:5008 src/FLTK/flgui.cpp:5030 +#: src/FLTK/flgui.cpp:5052 src/FLTK/flgui.cpp:5096 src/FLTK/flgui.cpp:5118 +#: src/FLTK/flgui.cpp:5186 +msgid "+0.0" +msgstr "+0.0" + +#: src/FLTK/flgui.cpp:4858 +msgid "32Hz" +msgstr "32Hz" + +#: src/FLTK/flgui.cpp:4880 +msgid "64Hz" +msgstr "64Hz" + +#: src/FLTK/flgui.cpp:4902 +msgid "125Hz" +msgstr "125Hz" + +#: src/FLTK/flgui.cpp:4924 +msgid "250Hz" +msgstr "250Hz" + +#: src/FLTK/flgui.cpp:4946 +msgid "500Hz" +msgstr "500Hz" + +#: src/FLTK/flgui.cpp:4968 +msgid "1kHz" +msgstr "1kHz" + +#: src/FLTK/flgui.cpp:4990 +msgid "2kHz" +msgstr "2kHz" + +#: src/FLTK/flgui.cpp:5012 +msgid "4kHz" +msgstr "4kHz" + +#: src/FLTK/flgui.cpp:5034 +msgid "8kHz" +msgstr "8kHz" + +#: src/FLTK/flgui.cpp:5056 +msgid "16kHz" +msgstr "16kHz" + +#: src/FLTK/flgui.cpp:5081 +msgid "Dynamic Range Compressor" +msgstr "Dynamic Range Compressor" + +#: src/FLTK/flgui.cpp:5092 +msgid "Aggressive Mode" +msgstr "Aggressive Mode" + +#: src/FLTK/flgui.cpp:5100 +msgid "Threshold" +msgstr "Threshold" + +#: src/FLTK/flgui.cpp:5122 +msgid "Ratio" +msgstr "Ratio" + +#: src/FLTK/flgui.cpp:5140 src/FLTK/flgui.cpp:5163 +msgid "+0.00" +msgstr "+0.00" + +#: src/FLTK/flgui.cpp:5144 +msgid "Attack" +msgstr "Attack" + +#: src/FLTK/flgui.cpp:5167 +msgid "Release" +msgstr "Release" + +#: src/FLTK/flgui.cpp:5190 +msgid "MakeupGain" +msgstr "MakeupGain" + +#: src/FLTK/flgui.cpp:5224 src/FLTK/flgui.cpp:5237 +msgid "MIDI" +msgstr "MIDI" + +#: src/FLTK/flgui.cpp:5226 +msgid "MIDI Device" +msgstr "MIDI Gerät" + +#: src/FLTK/flgui.cpp:5227 +msgid "Select your MIDI device" +msgstr "MIDI-Gerät selektieren" + +#: src/FLTK/flgui.cpp:5232 +msgid "Rescan" +msgstr "Suchen" + +#: src/FLTK/flgui.cpp:5233 +msgid "Rescan MIDI devices" +msgstr "Nach neuen MIDI-Geräten suchen" + +#: src/FLTK/flgui.cpp:5238 +msgid "MIDI signal indicator" +msgstr "MIDI-Signal indikator" + +#: src/FLTK/flgui.cpp:5250 +msgid "MIDI Commands" +msgstr "MIDI-Befehle" + +#: src/FLTK/flgui.cpp:5255 +msgid "Enable" +msgstr "Aktivieren" + +#: src/FLTK/flgui.cpp:5256 +msgid "Enable/Disable the selected MIDI command" +msgstr "Den selektieren MIDI-Befehl aktivieren/deaktivieren" + +#: src/FLTK/flgui.cpp:5262 +msgid "Channel" +msgstr "Kanal" + +#: src/FLTK/flgui.cpp:5263 +msgid "Select MIDI channel" +msgstr "MIDI-Kanal wählen" + +#: src/FLTK/flgui.cpp:5277 +msgid "CC" +msgstr "CC" + +#: src/FLTK/flgui.cpp:5278 +msgid "Select CC number" +msgstr "CC-Nummer wählen" + +#: src/FLTK/flgui.cpp:5283 src/FLTK/fl_callbacks.cpp:6425 +msgid "Learn" +msgstr "Lernen" + +#: src/FLTK/flgui.cpp:5284 +msgid "Activate to auto detect the channel and CC number" +msgstr "Den MIDI-Kanal und die CC-Nummer automatisch erkennen" + +#: src/FLTK/flgui.cpp:5289 +msgid "CC Mode" +msgstr "CC-Modus" + +#: src/FLTK/flgui.cpp:5290 +msgid "Select CC mode" +msgstr "CC-Modus wählen" + +#: src/FLTK/flgui.cpp:5304 +msgid "Soft takeover" +msgstr "Sanfte Übernahme" + +#: src/FLTK/flgui.cpp:5305 +msgid "Prevents jumps when controlling a slider in absolute mode" +msgstr "" +"Verhindert Sprünge wenn ein Schieberegler im Absolutmodus betrieben wird" + +#: src/FLTK/flgui.cpp:5313 +msgid "TLS" +msgstr "TLS" + +#: src/FLTK/flgui.cpp:5315 src/FLTK/flgui.cpp:5619 +msgid "SSL/TLS" +msgstr "SSL/TLS" + +#: src/FLTK/flgui.cpp:5318 +msgid "" +"If your server uses a certificate from\n" +"Let's Encrypt or another well known\n" +"CA, you can leave these fields blank." +msgstr "" +"Wenn dein Server ein Zertifikat von\n" +"Let's Encrypt oder einer anderen bekannten\n" +"CA verwenden, kann dieses Feld leer gelassen\n" +"werden." + +#: src/FLTK/flgui.cpp:5322 +msgid "CA Certificate File:" +msgstr "CA Zertifikate Datei:" + +#: src/FLTK/flgui.cpp:5323 +msgid "Certificate file" +msgstr "Zertifikate Datei" + +#: src/FLTK/flgui.cpp:5329 +msgid "Select certificate file" +msgstr "Zertifikatedatei" + +#: src/FLTK/flgui.cpp:5334 +msgid "CA Certificate Directory:" +msgstr "CA Zertifikate Ordner:" + +#: src/FLTK/flgui.cpp:5335 +msgid "Certificate directory" +msgstr "Zertifikate Ordner" + +#: src/FLTK/flgui.cpp:5341 +msgid "Select certificate directory" +msgstr "Zertifikate Ordner" + +#: src/FLTK/flgui.cpp:5350 +msgid "GUI" +msgstr "GUI" + +#: src/FLTK/flgui.cpp:5352 +msgid "Language" +msgstr "Sprache" + +#: src/FLTK/flgui.cpp:5369 +msgid "Display Color" +msgstr "Anzeige Farbe" + +#: src/FLTK/flgui.cpp:5372 +msgid "Text" +msgstr "Text" + +#: src/FLTK/flgui.cpp:5373 +msgid "Select text color" +msgstr "Textfarbe" + +#: src/FLTK/flgui.cpp:5379 +msgid "Background" +msgstr "Hintergrund" + +#: src/FLTK/flgui.cpp:5380 +msgid "Select background color" +msgstr "Hintergrundfarbe wählen" + +#: src/FLTK/flgui.cpp:5388 +msgid "VU meter" +msgstr "VU meter" + +#: src/FLTK/flgui.cpp:5391 +msgid "Gradient colors" +msgstr "Farbverlauf" + +#: src/FLTK/flgui.cpp:5396 +msgid "Solid colors" +msgstr "Harte Übergänge" + +#: src/FLTK/flgui.cpp:5401 +msgid "Always show tabs" +msgstr "Tabs immer anzeigen" + +#: src/FLTK/flgui.cpp:5406 +msgid "Select lower range color" +msgstr "Farbe für unter Grenze auswählen" + +#: src/FLTK/flgui.cpp:5413 +msgid "Select mid range color" +msgstr "Farbe für mittlere Grenze auswählen" + +#: src/FLTK/flgui.cpp:5420 +msgid "Select high range color" +msgstr "Farbe für obere Grenze auswählen" + +#: src/FLTK/flgui.cpp:5427 +msgid "Low range start value (dB)" +msgstr "Unterer Startwert (dB)" + +#: src/FLTK/flgui.cpp:5431 +msgid "Mid range start value (dB)" +msgstr "Mittlerer Startwert (dB)" + +#: src/FLTK/flgui.cpp:5440 +msgid "High range start value (dB)" +msgstr "Oberer Startwert (dB)" + +#: src/FLTK/flgui.cpp:5450 +msgid "Misc" +msgstr "Sonstiges" + +#: src/FLTK/flgui.cpp:5453 +msgid "Attach settings window to main window" +msgstr "Fenster an Hauptfenster anhaften" + +#: src/FLTK/flgui.cpp:5454 +msgid "Attach this window to the butt window" +msgstr "Fenster an Hauptfenster anhaften" + +#: src/FLTK/flgui.cpp:5458 src/FLTK/flgui.cpp:5459 +msgid "Stay always on top" +msgstr "Im Vordergrund bleiben" + +#: src/FLTK/flgui.cpp:5463 src/FLTK/flgui.cpp:5464 +msgid "Remember main window position" +msgstr "Fensterposition merken" + +#: src/FLTK/flgui.cpp:5468 src/FLTK/flgui.cpp:5469 +msgid "Hide log window after start up" +msgstr "Logfenster nach Start verbergen" + +#: src/FLTK/flgui.cpp:5473 src/FLTK/flgui.cpp:5474 +msgid "Change display mode every 5 seconds" +msgstr "Anzeige alle 5 Sekunden ändern" + +#: src/FLTK/flgui.cpp:5478 +msgid "Start minimized" +msgstr "Minimiert starten" + +#: src/FLTK/flgui.cpp:5479 +msgid "Minimize butt at startup" +msgstr "butt minimiert starten" + +#: src/FLTK/flgui.cpp:5483 +msgid "Disable gain control" +msgstr "Lautstärkeregler deaktivieren" + +#: src/FLTK/flgui.cpp:5489 +msgid "Show listeners" +msgstr "Zuhörer anzeigen" + +#: src/FLTK/flgui.cpp:5490 +msgid "Show current listeners in the display (not always available)" +msgstr "" +"Zeige die aktuelle Zuhörerzahl auf dem Display an (nicht immer möglich)" + +#: src/FLTK/flgui.cpp:5494 +msgid "Update rate:" +msgstr "Aktualisieren:" + +#: src/FLTK/flgui.cpp:5504 +msgid "Custom window title:" +msgstr "Benutzerdefinierter Fenstertitel:" + +#: src/FLTK/flgui.cpp:5505 +msgid "Define a custom window title" +msgstr "Bestimme einen Benutzerdefinierten Fenstertitel" + +#: src/FLTK/flgui.cpp:5515 +msgid "Donate" +msgstr "Spende" + +#: src/FLTK/flgui.cpp:5517 +msgid "Donation" +msgstr "Spenden" + +#: src/FLTK/flgui.cpp:5520 +msgid "" +"Keeping this software up to date, adding\n" +"new features and answering support mails\n" +"takes a lot of time and effort. If you can\n" +"afford it, please consider supporting this\n" +"project.\n" +"\n" +"Thank you!" +msgstr "" +"Es benötigt viel Zeit und Fleiß, diese\n" +"Software aktuell zu halten und mit\n" +"neuen Funktionen zu erweitern. Wenn Du\n" +"es Dir erlauben kannst, würde ich mich\n" +"sehr über eine Spende freuen.\n" +"\n" +"Danke!" + +#: src/FLTK/flgui.cpp:5525 +msgid "&Donate via PayPal" +msgstr "Mit PayPal spenden" + +#: src/FLTK/flgui.cpp:5529 +msgid "Become a &patron" +msgstr "Patron werden" + +#: src/FLTK/flgui.cpp:5533 +msgid "&Apple Pay, Google Pay, CC and more" +msgstr "&Apple Pay, Google Pay, Kreditkarte und mehr" + +#: src/FLTK/flgui.cpp:5537 +msgid "&Bitcoin && Co" +msgstr "&Bitcoin && Co" + +#: src/FLTK/flgui.cpp:5552 src/FLTK/flgui.cpp:5673 +msgid "Name:" +msgstr "Name:" + +#: src/FLTK/flgui.cpp:5556 +msgid "Address:" +msgstr "Adresse:" + +#: src/FLTK/flgui.cpp:5560 +msgid "Port:" +msgstr "Port:" + +#: src/FLTK/flgui.cpp:5564 +msgid "Password:" +msgstr "Passwort:" + +#: src/FLTK/flgui.cpp:5569 +msgid "Icecast mountpoint:" +msgstr "Icecast mountpoint:" + +#: src/FLTK/flgui.cpp:5573 +msgid "Icecast user:" +msgstr "Icecast Benutzer:" + +#: src/FLTK/flgui.cpp:5577 src/FLTK/fl_callbacks.cpp:1136 +#: src/FLTK/fl_callbacks.cpp:1215 src/FLTK/fl_callbacks.cpp:1623 +msgid "Show" +msgstr "Zeigen" + +#: src/FLTK/flgui.cpp:5578 +msgid "show/hide password" +msgstr "Password anzeigen/verbergen" + +#: src/FLTK/flgui.cpp:5582 +msgid "Type" +msgstr "Typ" + +#: src/FLTK/flgui.cpp:5585 +msgid "Shoutcast" +msgstr "Shoutcast" + +#: src/FLTK/flgui.cpp:5590 +msgid "Icecast" +msgstr "Icecast" + +#: src/FLTK/flgui.cpp:5595 +msgid "WebRTC" +msgstr "WebRTC" + +#: src/FLTK/flgui.cpp:5600 +msgid "Radio.co" +msgstr "Radio.co" + +#: src/FLTK/flgui.cpp:5607 src/FLTK/flgui.cpp:5709 +msgid "&Cancel" +msgstr "Abbrechen" + +#: src/FLTK/flgui.cpp:5611 src/FLTK/flgui.cpp:5713 +msgid "&ADD" +msgstr "OK" + +#: src/FLTK/flgui.cpp:5622 +msgid "Use SSL/TLS" +msgstr "SSL/TLS verwenden" + +#: src/FLTK/flgui.cpp:5625 +msgid "Revoke certificate trust" +msgstr "Vertrauen zurücksetzen" + +#: src/FLTK/flgui.cpp:5631 +msgid "Radio.co Stations" +msgstr "Radio.co Stationen" + +#: src/FLTK/flgui.cpp:5634 +msgid "Get Stations" +msgstr "Stationen holen" + +#: src/FLTK/flgui.cpp:5638 +msgid "Select all" +msgstr "Alle" + +#: src/FLTK/flgui.cpp:5642 +msgid "Deselect all" +msgstr "Keinen" + +#: src/FLTK/flgui.cpp:5646 +msgid "Use legacy Icecast protocol" +msgstr "Älteres Icecast Protokoll verwenden" + +#: src/FLTK/flgui.cpp:5647 +msgid "" +"Activate this if you want to use the older SOURCE protocol instead of the " +"newer PUT protocol" +msgstr "" +"Aktiviere dieses Feld, wenn du das ältere SOURCE Protokoll anstatt das " +"neuere PUT Protokoll verwenden möchtest" + +#: src/FLTK/flgui.cpp:5651 +msgid "ICE server (optional):" +msgstr "ICE Server (optional):" + +#: src/FLTK/flgui.cpp:5654 +msgid "WebRTC (WHIP) URL:" +msgstr "WebRTC (WHIP) URL:" + +#: src/FLTK/flgui.cpp:5657 +msgid "Bearer token (optional):" +msgstr "Bearer token (optional):" + +#: src/FLTK/flgui.cpp:5660 +msgid "Custom listener URL (optional):" +msgstr "Spezielle URL für die Höreranzahl (optional):" + +#: src/FLTK/flgui.cpp:5664 +msgid "Custom listener mountpoint (optional):" +msgstr "Spezieller Mountpoint für die Höreranzahl (optional):" + +#: src/FLTK/flgui.cpp:5674 +msgid "The name of your new ICY-entrie" +msgstr "Name des neue ICY-Eintrags" + +#: src/FLTK/flgui.cpp:5678 +msgid "Description:" +msgstr "Beschreibung:" + +#: src/FLTK/flgui.cpp:5682 +msgid "Genre:" +msgstr "Genre:" + +#: src/FLTK/flgui.cpp:5686 +msgid "URL:" +msgstr "URL:" + +#: src/FLTK/flgui.cpp:5690 +msgid "ICQ:" +msgstr "ICQ:" + +#: src/FLTK/flgui.cpp:5694 +msgid "IRC:" +msgstr "IRC:" + +#: src/FLTK/flgui.cpp:5698 +msgid "AIM:" +msgstr "AIM:" + +#: src/FLTK/flgui.cpp:5702 +msgid "Make server public" +msgstr "Server publizieren" + +#: src/FLTK/flgui.cpp:5705 +msgid "Expand variables" +msgstr "Variablen ersetzen" + +#: src/FLTK/flgui.cpp:5706 +msgid "Activate to expand date variables in name and description" +msgstr "Aktiviere, um Variablen im Namen und der Beschreibung zu ersetzen" + +#: src/FLTK/flgui.cpp:5736 +msgid "Donate Cryptocurrency" +msgstr "Kryptowährung spenden" + +#: src/FLTK/flgui.cpp:5747 +msgid "Bitcoin" +msgstr "Bitcoin" + +#: src/FLTK/flgui.cpp:5752 src/FLTK/flgui.cpp:5761 src/FLTK/flgui.cpp:5770 +msgid "Copy" +msgstr "Kopieren" + +#: src/FLTK/flgui.cpp:5756 +msgid "Litecoin" +msgstr "Litecoin" + +#: src/FLTK/flgui.cpp:5765 +msgid "Monero" +msgstr "Monero" + +#: src/FLTK/flgui.cpp:5774 src/FLTK/flgui.cpp:6106 src/FLTK/flgui.cpp:6461 +#: src/FLTK/flgui.cpp:6669 +msgid "&Close" +msgstr "&Schließen" + +#: src/FLTK/flgui.cpp:5780 +msgid "Streaming Codec Settings" +msgstr "Stream Codec Einstellungen" + +#: src/FLTK/flgui.cpp:5792 src/FLTK/flgui.cpp:6124 +msgid "MP3" +msgstr "MP3" + +#: src/FLTK/flgui.cpp:5793 src/FLTK/flgui.cpp:6125 +msgid "Encoding Quality" +msgstr "Qualität" + +#: src/FLTK/flgui.cpp:5806 src/FLTK/flgui.cpp:6138 +msgid "Stereo Mode" +msgstr "Stereo Modus" + +#: src/FLTK/flgui.cpp:5819 src/FLTK/flgui.cpp:5949 src/FLTK/flgui.cpp:6015 +#: src/FLTK/flgui.cpp:6071 src/FLTK/flgui.cpp:6151 src/FLTK/flgui.cpp:6281 +#: src/FLTK/flgui.cpp:6334 src/FLTK/flgui.cpp:6403 +msgid "Bitrate Mode" +msgstr "Bitrate Modus" + +#: src/FLTK/flgui.cpp:5832 src/FLTK/flgui.cpp:6164 +msgid "VBR" +msgstr "VBR" + +#: src/FLTK/flgui.cpp:5835 src/FLTK/flgui.cpp:5989 src/FLTK/flgui.cpp:6167 +#: src/FLTK/flgui.cpp:6347 +msgid "Quality" +msgstr "Qualität" + +#: src/FLTK/flgui.cpp:5848 src/FLTK/flgui.cpp:6180 +msgid "Min. Bitrate" +msgstr "Min. Bitrate" + +#: src/FLTK/flgui.cpp:5861 src/FLTK/flgui.cpp:6193 +msgid "Max. Bitrate" +msgstr "Max. Bitrate" + +#: src/FLTK/flgui.cpp:5874 src/FLTK/flgui.cpp:6206 +msgid "Force" +msgstr "Erzwingen" + +#: src/FLTK/flgui.cpp:5875 src/FLTK/flgui.cpp:6207 +msgid "Strictly enforce mininum Bitrate (-F option of the lame encoder)" +msgstr "" +"Minimale Bitrate erzwingen (entspricht der -F Option des lame encoders)" + +#: src/FLTK/flgui.cpp:5881 src/FLTK/flgui.cpp:6227 +msgid "Lowpass (kHz)" +msgstr "Tiefpass (kHz)" + +#: src/FLTK/flgui.cpp:5884 src/FLTK/flgui.cpp:5909 src/FLTK/flgui.cpp:6230 +#: src/FLTK/flgui.cpp:6255 +msgid "Frequency" +msgstr "Frequenz" + +#: src/FLTK/flgui.cpp:5890 src/FLTK/flgui.cpp:5915 src/FLTK/flgui.cpp:6236 +#: src/FLTK/flgui.cpp:6261 +msgid "Width" +msgstr "Breite" + +#: src/FLTK/flgui.cpp:5906 src/FLTK/flgui.cpp:6252 +msgid "Highpass (kHz)" +msgstr "Hochpass (kHz)" + +#: src/FLTK/flgui.cpp:5931 src/FLTK/flgui.cpp:6213 +msgid "Resampling" +msgstr "Resampling" + +#: src/FLTK/flgui.cpp:5932 src/FLTK/flgui.cpp:6214 +msgid "Resample to the selected sample rate" +msgstr "Ausgabe zur selektierten Samplerate resamplen" + +#: src/FLTK/flgui.cpp:5947 src/FLTK/flgui.cpp:6279 +msgid "OGG" +msgstr "OGG" + +#: src/FLTK/flgui.cpp:5962 src/FLTK/flgui.cpp:6294 +msgid "VBR Quality" +msgstr "VBR Qualität" + +#: src/FLTK/flgui.cpp:5975 src/FLTK/flgui.cpp:6307 +msgid "VBR min. Bitrate" +msgstr "VBR min. Bitrate" + +#: src/FLTK/flgui.cpp:5980 src/FLTK/flgui.cpp:6312 +msgid "VBR max. Bitrate" +msgstr "VBR max. Bitrate" + +#: src/FLTK/flgui.cpp:5987 src/FLTK/flgui.cpp:6319 +msgid "OPUS" +msgstr "OPUS" + +#: src/FLTK/flgui.cpp:6002 src/FLTK/flgui.cpp:6321 +msgid "Optimize for" +msgstr "Optimiere für" + +#: src/FLTK/flgui.cpp:6028 src/FLTK/flgui.cpp:6360 +msgid "Max. Bandwidth" +msgstr "Max. Bandbreite" + +#: src/FLTK/flgui.cpp:6043 src/FLTK/flgui.cpp:6375 +msgid "AAC" +msgstr "AAC" + +#: src/FLTK/flgui.cpp:6045 src/FLTK/flgui.cpp:6377 +msgid "Profile" +msgstr "Profil" + +#: src/FLTK/flgui.cpp:6058 src/FLTK/flgui.cpp:6390 +msgid "Afterburner" +msgstr "Nachbrenner" + +#: src/FLTK/flgui.cpp:6086 src/FLTK/flgui.cpp:6418 +msgid "FLAC" +msgstr "FLAC" + +#: src/FLTK/flgui.cpp:6088 src/FLTK/flgui.cpp:6420 src/FLTK/flgui.cpp:6438 +msgid "Bit depth" +msgstr "Bittiefe" + +#: src/FLTK/flgui.cpp:6090 src/FLTK/flgui.cpp:6422 src/FLTK/flgui.cpp:6440 +msgid "16 bit" +msgstr "16 bit" + +#: src/FLTK/flgui.cpp:6095 src/FLTK/flgui.cpp:6427 src/FLTK/flgui.cpp:6450 +msgid "24 bit" +msgstr "24 bit" + +#: src/FLTK/flgui.cpp:6112 +msgid "Recording Codec Settings" +msgstr "Aufnahme Codec Einstellungen" + +#: src/FLTK/flgui.cpp:6436 +msgid "WAV" +msgstr "WAV" + +#: src/FLTK/flgui.cpp:6445 +msgid "32 bit" +msgstr "32 bit" + +#: src/FLTK/flgui.cpp:6467 +msgid "butt audio mixer" +msgstr "butt Mischpult" + +#: src/FLTK/flgui.cpp:6483 +msgid "Audio Mixer" +msgstr "Mischpult" + +#: src/FLTK/flgui.cpp:6486 src/FLTK/flgui.cpp:6516 src/FLTK/flgui.cpp:6546 +#: src/FLTK/flgui.cpp:6569 src/FLTK/flgui.cpp:6592 +msgid "+0.0 dB" +msgstr "+0.0 dB" + +#: src/FLTK/flgui.cpp:6491 src/FLTK/flgui.cpp:6634 +msgid "" +"Primary\n" +"Device" +msgstr "" +"Primäres\n" +"Gerät" + +#: src/FLTK/flgui.cpp:6509 src/FLTK/flgui.cpp:6510 src/FLTK/flgui.cpp:6539 +#: src/FLTK/flgui.cpp:6540 +msgid "Mute" +msgstr "Aus" + +#: src/FLTK/flgui.cpp:6521 src/FLTK/flgui.cpp:6642 +msgid "" +"Secondary\n" +"Device" +msgstr "" +"Sekundäres\n" +"Gerät" + +#: src/FLTK/flgui.cpp:6551 +msgid "" +"Streaming\n" +"Gain" +msgstr "" +"Streaming\n" +"Verstärking" + +#: src/FLTK/flgui.cpp:6574 +msgid "" +"Recording\n" +"Gain" +msgstr "" +"Aufnahme\n" +"Verstärkung" + +#: src/FLTK/flgui.cpp:6597 +msgid "" +"Master\n" +"Gain" +msgstr "" +"Haupt\n" +"Verstärkung" + +#: src/FLTK/flgui.cpp:6615 +msgid "" +"\n" +"Cross Fader" +msgstr "" +"\n" +"Cross Fader" + +#: src/FLTK/flgui.cpp:6638 +msgid "|" +msgstr "|" + +#: src/FLTK/flgui.cpp:6650 +msgid "Alert" +msgstr "Warnung" + +#: src/FLTK/flgui.cpp:6661 +msgid "&Open the manual" +msgstr "&Handbuch öffnen" + +#: src/FLTK/flgui.cpp:6665 +msgid "" +"Could not find aac library.\n" +"\n" +"Please follow the instructions in the manual\n" +"for adding aac support." +msgstr "" +"Konnte die AAC Bibliothek nicht finden.\n" +"\n" +"Bitte folge den Schritten im Handbuch, um die AAC Unterstützung zu " +"aktivieren." + +#: src/FLTK/fl_timer_funcs.cpp:318 +#, c-format +msgid "" +"stream sent\n" +"%0.2lfMB" +msgstr "" +"Stream gesendet\n" +"%0.2lfMB" + +#: src/FLTK/fl_timer_funcs.cpp:323 +#, c-format +msgid "" +"stream time\n" +"%s" +msgstr "" +"Stream Zeit\n" +"%s" + +# Will be shown in the main display and thus +# may only contain ascii-characters. When +# in doubt just keep "Listeners". Also the string length should not exceed 10 characters. +#: src/FLTK/fl_timer_funcs.cpp:330 +#, c-format +msgid "" +"On Air\n" +"Listeners %5d" +msgstr "" +"On Air\n" +"Zuhoerer %5d" + +# Will be shown in the main display and thus +# may only contain ascii-characters. When +# in doubt just keep "Listeners>". Also the string length should not exceed 10 characters. +#: src/FLTK/fl_timer_funcs.cpp:333 +#, c-format +msgid "" +"On Air\n" +"Listeners>%5d" +msgstr "" +"On Air\n" +"Hoerer>%5d" + +# Will be shown in the main display and thus may only contain ascii-characters. When in doubt just keep "On Air" +#: src/FLTK/fl_timer_funcs.cpp:337 +#, c-format +msgid "On Air" +msgstr "On Air" + +#: src/FLTK/fl_timer_funcs.cpp:343 +#, c-format +msgid "" +"record time\n" +"%s" +msgstr "" +"Record Zeit\n" +"%s" + +#: src/FLTK/fl_timer_funcs.cpp:348 +#, c-format +msgid "" +"record size\n" +"%0.2lfMB" +msgstr "" +"Record groesse\n" +"%0.2lfMB" + +#: src/FLTK/fl_timer_funcs.cpp:479 +#, c-format +msgid "" +"ERROR: Connection lost\n" +"reconnecting in %d seconds..." +msgstr "" +"FEHLER: Verbindung verloren\n" +"Verbinde neu in %d Sekunden..." + +#: src/FLTK/fl_timer_funcs.cpp:483 +msgid "" +"ERROR: Connection lost\n" +"reconnecting..." +msgstr "" +"FEHLER: Verbindung verloren\n" +"Verbinde neu..." + +#: src/FLTK/fl_timer_funcs.cpp:608 +msgid "Listeners" +msgstr "Zuhörer" + +#: src/FLTK/fl_timer_funcs.cpp:674 +msgid "" +"Could not find a file extension in current filename\n" +"Automatic file splitting is deactivated" +msgstr "" +"Der Aufnahmedateiname hat keine Dateiendung\n" +"Automatische Dateiaufteilung wird deaktiviert" + +#: src/FLTK/fl_timer_funcs.cpp:704 +msgid "" +"Could not find a valid filename for next file\n" +"butt keeps recording to current file" +msgstr "" +"Konnte keinen gültigen Dateinahmen für die nächste Datei erstellen\n" +"butt wird die Aufnahme in der aktuellen Datei fortführen" + +#: src/FLTK/fl_timer_funcs.cpp:717 src/FLTK/fl_callbacks.cpp:1033 +#, c-format +msgid "" +"Could not open:\n" +"%s" +msgstr "" +"Konnte Datei nicht öffnen:\n" +"%s" + +#: src/FLTK/fl_timer_funcs.cpp:721 src/port_audio.cpp:938 +msgid "Recording to:" +msgstr "Aufnahmedatei:" + +#: src/FLTK/fl_timer_funcs.cpp:964 +#, c-format +msgid "" +"Warning\n" +"Could not open: %s.\n" +"Will retry in 5 seconds" +msgstr "" +"Warnung\n" +"Konnte Datei nicht öffnen: %s.\n" +"Versuche in 5 Sekunden erneut" + +#: src/FLTK/fl_callbacks.cpp:145 +msgid "connecting" +msgstr "Verbinde" + +#: src/FLTK/fl_callbacks.cpp:187 +msgid "" +"Error: No server entry found.\n" +"Please add a server in the settings-window." +msgstr "" +"Fehler: Kein Servereintrag gefunden.\n" +"Bitte füge einen Server in den Einstellungen hinzu." + +#: src/FLTK/fl_callbacks.cpp:192 +msgid "" +"Error: ogg vorbis encoder doesn't support bitrates\n" +"lower than 48kbit" +msgstr "" +"Fehler: Der ogg vorbis encoder erlaubt keine Bitraten\n" +"kleiner als 48kbit" + +#: src/FLTK/fl_callbacks.cpp:200 +#, c-format +msgid "Warning: %s is not supported by every Shoutcast version" +msgstr "Warnung: %s wird nicht von jeder Shoutcast version unterstützt" + +#: src/FLTK/fl_callbacks.cpp:204 +msgid "Error: FLAC is not supported by ShoutCast" +msgstr "Fehler: FLAC wird von Shoutcast nicht unterstützt" + +#: src/FLTK/fl_callbacks.cpp:211 +#, c-format +msgid "Error: Radio.co supports only mp3 and aac" +msgstr "Fehler: Radio.co unterstützt nur mp3 und aac" + +#: src/FLTK/fl_callbacks.cpp:219 +#, c-format +msgid "Error: WebRTC only supports opus" +msgstr "Fehler: WebRTC funktioniert nur mit dem opus codec" + +#: src/FLTK/fl_callbacks.cpp:226 +#, c-format +msgid "Connecting to %s via %s ..." +msgstr "Verbinde mit %s via %s ..." + +#: src/FLTK/fl_callbacks.cpp:229 +#, c-format +msgid "Connecting to %s:%u ..." +msgstr "Verbinde mit %s:%u ..." + +#: src/FLTK/fl_callbacks.cpp:232 +#, c-format +msgid "Connecting to %s:%u (%u) ..." +msgstr "Verbinde mit %s:%u (%u) ..." + +#: src/FLTK/fl_callbacks.cpp:328 +msgid "Connection established" +msgstr "Verbindung hergestellt" + +#: src/FLTK/fl_callbacks.cpp:342 src/FLTK/fl_callbacks.cpp:4275 +#: src/FLTK/fl_callbacks.cpp:4281 +msgid "no" +msgstr "nein" + +#: src/FLTK/fl_callbacks.cpp:342 src/FLTK/fl_callbacks.cpp:4275 +#: src/FLTK/fl_callbacks.cpp:4281 +msgid "yes" +msgstr "ja" + +#: src/FLTK/fl_callbacks.cpp:344 +#, c-format +msgid "Device 1:\t%s\n" +msgstr "Gerät 1:\t%s\n" + +#: src/FLTK/fl_callbacks.cpp:345 +#, c-format +msgid "Device 2:\t%s\n" +msgstr "Gerät 2:\t%s\n" + +#: src/FLTK/fl_callbacks.cpp:396 +#, c-format +msgid "Connected to: %s" +msgstr "Verbunden mit: %s" + +#: src/FLTK/fl_callbacks.cpp:567 src/FLTK/fl_callbacks.cpp:1669 +msgid "The custom listener URL must start with http:// or https://" +msgstr "Die URL muss entweder mit http:// oder https:// beginnen" + +#: src/FLTK/fl_callbacks.cpp:574 src/FLTK/fl_callbacks.cpp:1676 +msgid "" +"No mountpoint specified\n" +"Setting mountpoint to \"stream\"" +msgstr "" +"Kein Mountpoint angegeben\n" +"Nutze Mountpoint \"stream\"" + +#: src/FLTK/fl_callbacks.cpp:578 src/FLTK/fl_callbacks.cpp:1680 +msgid "" +"No user specified\n" +"Setting user to \"source\"" +msgstr "" +"Kein Benutzer angegeben\n" +"Nutze Benutzer \"source\"" + +#: src/FLTK/fl_callbacks.cpp:586 src/FLTK/fl_callbacks.cpp:1688 +msgid "" +"Unsupported listener URL.\n" +"The listener URL must end with status-json.xsl, 7.xsl, 7.html or contain " +"stats?sid" +msgstr "" +"Die eingegebene URL wird nicht unterstützt.\n" +"Sie muss mit status-json.xsl, 7.xsl, 7.html enden oder stats?sid beinhalten" + +#: src/FLTK/fl_callbacks.cpp:592 src/FLTK/fl_callbacks.cpp:1694 +#: src/FLTK/fl_callbacks.cpp:1857 src/FLTK/fl_callbacks.cpp:2545 +msgid "No name specified" +msgstr "Kein Name angegeben" + +#: src/FLTK/fl_callbacks.cpp:597 src/FLTK/fl_callbacks.cpp:1699 +msgid "" +"The number of characters of all your server names exeeds 1000\n" +"Please reduce the number of characters of each server name" +msgstr "" +"Der Name des Servers ist länger als 1000 Zeichen\n" +"Bitte wähle einen kürzeren Namen" + +#: src/FLTK/fl_callbacks.cpp:603 src/FLTK/fl_callbacks.cpp:1705 +msgid "Newline characters and [];/\\ are not allowed within the server name" +msgstr "Der Name darf weder neue Zeilen noch die Zeichen [];/\\ enthalten" + +#: src/FLTK/fl_callbacks.cpp:609 src/FLTK/fl_callbacks.cpp:1710 +msgid "No address specified" +msgstr "Keine Adresse angegeben" + +#: src/FLTK/fl_callbacks.cpp:613 src/FLTK/fl_callbacks.cpp:1714 +msgid "No password specified" +msgstr "Keine Password angegeben" + +#: src/FLTK/fl_callbacks.cpp:617 src/FLTK/fl_callbacks.cpp:1718 +msgid "No port specified" +msgstr "Kein Port angegeben" + +#: src/FLTK/fl_callbacks.cpp:621 src/FLTK/fl_callbacks.cpp:1722 +msgid "" +"Invalid port number\n" +"The port number must be between 1 and 65535" +msgstr "" +"Ungültiger Port\n" +"Der Port muss eine Zahl zwischen 1 und 65535 sein" + +#: src/FLTK/fl_callbacks.cpp:628 src/FLTK/fl_callbacks.cpp:1729 +msgid "No WHIP URL specified" +msgstr "Keine WHIP URL angegeben" + +#: src/FLTK/fl_callbacks.cpp:637 src/FLTK/fl_callbacks.cpp:1740 +#: src/FLTK/fl_callbacks.cpp:2564 +msgid "Server name already exist!" +msgstr "Der Servername existiert bereits!" + +#: src/FLTK/fl_callbacks.cpp:966 +msgid "stop recording?" +msgstr "Aufnahme beenden?" + +#: src/FLTK/fl_callbacks.cpp:966 src/FLTK/fl_funcs.cpp:1462 +msgid "No" +msgstr "Nein" + +#: src/FLTK/fl_callbacks.cpp:966 +msgid "Yes" +msgstr "Ja" + +#: src/FLTK/fl_callbacks.cpp:1005 +msgid "No recording filename specified" +msgstr "Keine Aufnahmedatei spezifiziert" + +#: src/FLTK/fl_callbacks.cpp:1015 +#, c-format +msgid "%s already exists!" +msgstr "%s existiert bereits!" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "overwrite" +msgstr "Überschreiben" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "cancel" +msgstr "Abbrechen" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "append" +msgstr "Anhängen" + +#: src/FLTK/fl_callbacks.cpp:1021 +msgid "Recording canceled" +msgstr "Aufnahme wurde nicht gestarted" + +#: src/FLTK/fl_callbacks.cpp:1090 src/FLTK/fl_funcs.cpp:1308 +msgid "Hide log" +msgstr "Log verbergen" + +#: src/FLTK/fl_callbacks.cpp:1123 +msgid "Add Server" +msgstr "Neuer Server" + +#: src/FLTK/fl_callbacks.cpp:1176 +msgid "Edit Server" +msgstr "Server editieren" + +#: src/FLTK/fl_callbacks.cpp:1181 +msgid "Radio.co stations cannot be edited." +msgstr "Radio.co server können nicht editiert werden." + +#: src/FLTK/fl_callbacks.cpp:1267 +msgid "Add Server Infos" +msgstr "Neue Server Infos" + +#: src/FLTK/fl_callbacks.cpp:1302 +msgid "Song update failed: WebRTC does not support song names" +msgstr "Song update fehlgeschlagen: Wird von WebRTC nicht unterstützt" + +#: src/FLTK/fl_callbacks.cpp:1345 +#, c-format +msgid "" +"Updated songname to:\n" +"%s\n" +msgstr "" +"Neuer Songname:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:1354 +msgid "Updating songname failed" +msgstr "Aktualisierung des Songnamens ist fehlgeschlagen" + +#: src/FLTK/fl_callbacks.cpp:1428 +#, c-format +msgid "Audio buffer has been set to %d ms" +msgstr "Audio Puffer wurde auf %d ms gesetzt" + +#: src/FLTK/fl_callbacks.cpp:1592 +msgid "" +"butt will open Radio.co in a new browser window.\n" +"\n" +"Login to Radio.co and allow butt access to your account." +msgstr "" +"butt wird jetzt Radio.co in einem neuen Browser Fenster öffnen.\n" +"\n" +"Bitte loggen Sie sich ein und erlauben Sie den Zugriff mit butt." + +#: src/FLTK/fl_callbacks.cpp:1618 +msgid "Hide" +msgstr "Ausbl." + +#: src/FLTK/fl_callbacks.cpp:1638 +msgid "Could not revoke trust for certificate" +msgstr "Konnte Vertrauen für Zertifikat nicht zurückziehen" + +#: src/FLTK/fl_callbacks.cpp:1862 +msgid "" +"The number of characters of all your icy names exeeds 1000\n" +"Please reduce the count of characters of each icy name" +msgstr "" +"Der ICY Namen ist länger als 1000 Zeichen\n" +"Bitte wähle einen kürzeren Namen" + +#: src/FLTK/fl_callbacks.cpp:1868 src/FLTK/fl_callbacks.cpp:2557 +msgid "Newline characters and [];/\\ are not allowed within the icy name" +msgstr "Der Name darf weder neue Zeilen noch die Zeichen [];/\\ enthalten" + +#: src/FLTK/fl_callbacks.cpp:1877 +msgid "Icy name already exist!" +msgstr "ICY Name existiert bereits!" + +#: src/FLTK/fl_callbacks.cpp:2002 src/FLTK/fl_callbacks.cpp:2015 +#: src/FLTK/fl_callbacks.cpp:2029 src/FLTK/fl_callbacks.cpp:2044 +#: src/FLTK/fl_callbacks.cpp:2233 src/FLTK/fl_callbacks.cpp:2246 +#: src/FLTK/fl_callbacks.cpp:2260 src/FLTK/fl_callbacks.cpp:2275 +#: src/FLTK/fl_callbacks.cpp:2290 +msgid "" +"Warning:\n" +"The stream Sample-/Bitrate combination is invalid" +msgstr "" +"Warnung:\n" +"Ungültige stream Sample-/Bitrate Kombination" + +#: src/FLTK/fl_callbacks.cpp:2008 src/FLTK/fl_callbacks.cpp:2021 +#: src/FLTK/fl_callbacks.cpp:2035 src/FLTK/fl_callbacks.cpp:2050 +msgid "The previous values have been set\n" +msgstr "Die vorherigen Werte werden verwenden\n" + +#: src/FLTK/fl_callbacks.cpp:2056 +#, c-format +msgid "Stream bitrate set to: %dk" +msgstr "Stream Bitrate geändert: %dk" + +#: src/FLTK/fl_callbacks.cpp:2142 src/FLTK/fl_callbacks.cpp:2155 +#: src/FLTK/fl_callbacks.cpp:2169 src/FLTK/fl_callbacks.cpp:2184 +#: src/FLTK/fl_callbacks.cpp:2313 src/FLTK/fl_callbacks.cpp:2326 +#: src/FLTK/fl_callbacks.cpp:2340 src/FLTK/fl_callbacks.cpp:2355 +#: src/FLTK/fl_callbacks.cpp:2369 +msgid "" +"Warning:\n" +"The record Sample-/Bitrate combination is invalid" +msgstr "" +"Warnung:\n" +"Ungültige Aufnahme Sample-/Bitrate Kombination" + +#: src/FLTK/fl_callbacks.cpp:2148 src/FLTK/fl_callbacks.cpp:2161 +#: src/FLTK/fl_callbacks.cpp:2175 src/FLTK/fl_callbacks.cpp:2190 +#: src/FLTK/fl_callbacks.cpp:2239 src/FLTK/fl_callbacks.cpp:2252 +#: src/FLTK/fl_callbacks.cpp:2266 src/FLTK/fl_callbacks.cpp:2281 +#: src/FLTK/fl_callbacks.cpp:2296 src/FLTK/fl_callbacks.cpp:2319 +#: src/FLTK/fl_callbacks.cpp:2332 src/FLTK/fl_callbacks.cpp:2346 +#: src/FLTK/fl_callbacks.cpp:2361 src/FLTK/fl_callbacks.cpp:2375 +msgid "The previous values have been set" +msgstr "Die vorherigen Werte werden verwenden" + +#: src/FLTK/fl_callbacks.cpp:2196 +#, c-format +msgid "Record bitrate set to: %dk" +msgstr "Neue Aufnahme Bitrate: %dk" + +#: src/FLTK/fl_callbacks.cpp:2383 +#, c-format +msgid "Samplerate set to: %dHz" +msgstr "Neue Samplerate: %dHz" + +#: src/FLTK/fl_callbacks.cpp:2449 +msgid "Channels set to: stereo" +msgstr "Verwende stereo" + +#: src/FLTK/fl_callbacks.cpp:2512 +msgid "Channels set to: mono" +msgstr "Verwende mono" + +#: src/FLTK/fl_callbacks.cpp:2551 +msgid "" +"The number of characters of all your icy names exeeds 1000\n" +"Please reduce the number of characters of each icy name" +msgstr "" +"Der ICY Namen ist länger als 1000 Zeichen\n" +"Bitte wähle einen kürzeren Namen" + +#: src/FLTK/fl_callbacks.cpp:2659 +msgid "Edit Server Infos" +msgstr "Server Infos Editieren" + +#: src/FLTK/fl_callbacks.cpp:2696 src/FLTK/fl_callbacks.cpp:2749 +msgid "" +"Primary and secondary audio device are both ASIO devices.\n" +"You can not use two ASIO devices at the same time.\n" +"Please select a different device.\n" +msgstr "" +"Primäres und sekundäres Audiogerät sind beides ASIO-Geräte.\n" +"Es können nicht zwei ASIO-Geräte gleichzeitig verwendet werden.\n" +"Wähle bitte ein anderes Gerät.\n" + +#: src/FLTK/fl_callbacks.cpp:2717 src/FLTK/fl_callbacks.cpp:4155 +msgid "" +"butt could not open selected audio device.\n" +"Please try another device.\n" +msgstr "" +"butt konnte das ausgewählte Audiogerät öffnen.\n" +"Bitte wählen Sie ein alternatives Audiogerät aus.\n" + +#: src/FLTK/fl_callbacks.cpp:2732 +#, c-format +msgid "" +"Primary device:\n" +"%s\n" +msgstr "" +"Primäres Gerät:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:2769 +msgid "" +"butt could not open secondary audio device.\n" +"Please try another device.\n" +msgstr "" +"butt konnte das sekundäre Audiogerät nicht öffnen.\n" +"Bitte wählen Sie ein alternatives Audiogerät aus.\n" + +#: src/FLTK/fl_callbacks.cpp:2783 +#, c-format +msgid "" +"Secondary device:\n" +"%s\n" +msgstr "" +"Sekundäres Gerät: \n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:2894 src/FLTK/fl_callbacks.cpp:3072 +msgid "" +"MP3 encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"MP3 encoder unterstützt die aktuelle\n" +"Sample-/Bitrate Kombination nicht" + +#: src/FLTK/fl_callbacks.cpp:2915 +msgid "Stream codec set to mp3" +msgstr "Stream Codec nach mp3 geändert" + +#: src/FLTK/fl_callbacks.cpp:2927 src/FLTK/fl_callbacks.cpp:3112 +msgid "" +"OGG Vorbis encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"OGG Vorbis encoder unterstützt die aktuelle\n" +"Sample-/Bitrate Kombination nicht" + +#: src/FLTK/fl_callbacks.cpp:2948 +msgid "Stream codec set to ogg/vorbis" +msgstr "Stream Codec nach ogg/vorbis geändert" + +#: src/FLTK/fl_callbacks.cpp:2959 src/FLTK/fl_callbacks.cpp:3151 +msgid "" +"Opus encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"Opus encoder unterstützt die aktuelle\n" +"Sample-/Bitrate Kombination nicht" + +#: src/FLTK/fl_callbacks.cpp:2979 +msgid "Stream codec set to opus" +msgstr "Stream Codec nach opus geändert" + +#: src/FLTK/fl_callbacks.cpp:3011 src/FLTK/fl_callbacks.cpp:3213 +msgid "" +"AAC encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"AAC encoder unterstützt die aktuelle\n" +"Sample-/Bitrate Kombination nicht" + +#: src/FLTK/fl_callbacks.cpp:3032 +msgid "Stream codec set to aac" +msgstr "Stream Codec nach AAC geändert" + +#: src/FLTK/fl_callbacks.cpp:3042 src/FLTK/fl_callbacks.cpp:3252 +msgid "ERROR: While initializing flac settings" +msgstr "FEHLER: Beim Initialisieren der FLAC Einstellungen" + +#: src/FLTK/fl_callbacks.cpp:3060 +msgid "Stream codec set to flac" +msgstr "Stream Codec nach FLAC geändert" + +#: src/FLTK/fl_callbacks.cpp:3101 +msgid "Record codec set to mp3" +msgstr "Aufnahme Codec nach mp3 geändert" + +#: src/FLTK/fl_callbacks.cpp:3140 +msgid "Record codec set to ogg/vorbis" +msgstr "Aufnahme Codec nach ogg/vorbis geändert" + +#: src/FLTK/fl_callbacks.cpp:3179 +msgid "Record codec set to opus" +msgstr "Aufnahme Codec nach opus geändert" + +#: src/FLTK/fl_callbacks.cpp:3242 +msgid "Record codec set to aac" +msgstr "Aufnahme Codec nach ACC geändert" + +#: src/FLTK/fl_callbacks.cpp:3278 +msgid "Record codec set to flac" +msgstr "Aufnahme Codec nach FLAC geändert" + +#: src/FLTK/fl_callbacks.cpp:3294 +msgid "Record codec set to wav" +msgstr "Aufnahme Codec nach wav geändert" + +#: src/FLTK/fl_callbacks.cpp:3329 +msgid "Select certificate file..." +msgstr "Zertifikat auswählen..." + +#: src/FLTK/fl_callbacks.cpp:3334 src/FLTK/fl_callbacks.cpp:3355 +#: src/FLTK/fl_callbacks.cpp:3466 src/FLTK/fl_callbacks.cpp:3556 +#: src/FLTK/fl_callbacks.cpp:4109 src/FLTK/fl_callbacks.cpp:4133 +#: src/FLTK/fl_callbacks.cpp:4257 +#, c-format +msgid "ERROR: %s" +msgstr "FEHLER: %s" + +#: src/FLTK/fl_callbacks.cpp:3347 +msgid "Select certificate directory..." +msgstr "Zertifikate Ordner auswählen..." + +#: src/FLTK/fl_callbacks.cpp:3458 +msgid "Record to..." +msgstr "Aufnehmen nach..." + +#: src/FLTK/fl_callbacks.cpp:3483 +msgid "File splitting only works if recording is active." +msgstr "Aufnahme nicht aktiv." + +#: src/FLTK/fl_callbacks.cpp:3552 +msgid "Select Songfile" +msgstr "Songdatei wählen" + +#: src/FLTK/fl_callbacks.cpp:3657 +msgid "Gain control is disabled. Enable in Settings->GUI" +msgstr "Lautstärkeregelung ist deaktiviert. Aktivieren in Einstellungen->GUI" + +#: src/FLTK/fl_callbacks.cpp:3718 +msgid "select background color" +msgstr "Hintergrundfarbe wählen" + +#: src/FLTK/fl_callbacks.cpp:3728 +msgid "select text color" +msgstr "Textfarbe wählen" + +#: src/FLTK/fl_callbacks.cpp:3761 src/FLTK/fl_callbacks.cpp:3765 +#: src/FLTK/fl_callbacks.cpp:3774 src/FLTK/fl_callbacks.cpp:3778 +msgid "Value must be a number between -54 and 0" +msgstr "Bitte eine Zahl zwischen --54 und 0 eingeben" + +#: src/FLTK/fl_callbacks.cpp:3788 +msgid "Please restart butt to apply new language." +msgstr "Bitte starte butt neu, um die neue Sprache zu laden." + +#: src/FLTK/fl_callbacks.cpp:3867 src/FLTK/fl_callbacks.cpp:3872 +#: src/FLTK/fl_callbacks.cpp:3882 src/FLTK/fl_callbacks.cpp:3887 +msgid "Value must be a number between -90.0 and 0" +msgstr "Bitte eine Zahl zwischen -90 und 0 eingeben" + +#: src/FLTK/fl_callbacks.cpp:4082 +msgid "Recording volume" +msgstr "Aufnahmelautstärke" + +#: src/FLTK/fl_callbacks.cpp:4103 +msgid "Export to..." +msgstr "Expotieren nach..." + +#: src/FLTK/fl_callbacks.cpp:4146 +#, c-format +msgid "Could not import config %s" +msgstr "Konnte Konfiguration nicht importieren %s" + +#: src/FLTK/fl_callbacks.cpp:4160 +#, c-format +msgid "Config imported %s" +msgstr "Konfiguration importiert %s" + +#: src/FLTK/fl_callbacks.cpp:4234 +msgid "" +"Could not get update information.\n" +"Reason: Network error" +msgstr "" +"Konnte aktuelle Version nicht empfangen.\n" +"Grund: Netzwerkfehler" + +#: src/FLTK/fl_callbacks.cpp:4237 +msgid "" +"Could not get update information.\n" +"Reason: Unknown answer from server" +msgstr "" +"Konnte aktuelle Version nicht empfangen.\n" +"Grund: Ungültige Antwort von Server" + +#: src/FLTK/fl_callbacks.cpp:4240 +msgid "You have the latest version!" +msgstr "Du hast die aktuellste Version!" + +#: src/FLTK/fl_callbacks.cpp:4243 +msgid "" +"Could not get update information.\n" +"Reason: Unknown" +msgstr "" +"Konnte aktuelle Version nicht empfangen.\n" +"Grund: Unbekannt" + +#: src/FLTK/fl_callbacks.cpp:4251 +msgid "Select logfile..." +msgstr "Logdatei wählen..." + +#: src/FLTK/fl_callbacks.cpp:4273 +msgid "" +"butt is currently streaming.\n" +"Do you really want to close butt now?" +msgstr "" +"butt ist gerade mit einem Server verbunden.\n" +"Soll butt wirklich geschlossen werden?" + +#: src/FLTK/fl_callbacks.cpp:4279 +msgid "" +"butt is currently recording.\n" +"Do you really want to close butt now?" +msgstr "" +"butt nimmt gerade auf.\n" +"Soll butt wirklich geschlossen werden?" + +#: src/FLTK/fl_callbacks.cpp:4354 +msgid "The URL must start with either http:// or https://" +msgstr "Die URL muss entweder mit http:// oder https:// beginnen" + +#: src/FLTK/fl_callbacks.cpp:4366 +msgid "Value must be a number between 1 and 1000" +msgstr "Bitte eine Zahl zwischen -1 und 1000" + +#: src/FLTK/fl_callbacks.cpp:5228 src/FLTK/fl_callbacks.cpp:5263 +#: src/FLTK/fl_callbacks.cpp:5298 src/FLTK/fl_callbacks.cpp:5333 +#: src/FLTK/fl_callbacks.cpp:5368 src/FLTK/fl_callbacks.cpp:5859 +#: src/FLTK/fl_callbacks.cpp:5894 src/FLTK/fl_callbacks.cpp:5929 +#: src/FLTK/fl_callbacks.cpp:5964 src/FLTK/fl_callbacks.cpp:5999 +msgid "The encoder could not be initialized with the provided parameters." +msgstr "" +"Der Encoder konnte mit den aktuellen Einstellungen nicht initialisiert " +"werden." + +#: src/FLTK/fl_callbacks.cpp:5246 src/FLTK/fl_callbacks.cpp:5877 +msgid "The value must be between 0.001 kHz and 50 kHz" +msgstr "Der Wert muss zwischen 0.001 kHz und 50 kHz liegen" + +#: src/FLTK/fl_callbacks.cpp:5281 src/FLTK/fl_callbacks.cpp:5316 +#: src/FLTK/fl_callbacks.cpp:5351 src/FLTK/fl_callbacks.cpp:5912 +#: src/FLTK/fl_callbacks.cpp:5947 src/FLTK/fl_callbacks.cpp:5982 +msgid "The value must be between 0.001 kHz and 16 kHz" +msgstr "Der Wert muss zwischen 0.001 kHz und 16 kHz liegen" + +#: src/FLTK/fl_callbacks.cpp:6328 +msgid "MIDI device could not be opened." +msgstr "Das MIDI-Gerät konnte nicht geöffnet werden." + +#: src/FLTK/fl_callbacks.cpp:6334 +#, c-format +msgid "" +"MIDI device:\n" +"%s\n" +msgstr "" +"MIDI-Gerät:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:6339 +msgid "MIDI device could not be started." +msgstr "Das MIDI-Gerät konnte nicht initialisiert werden." + +#: src/FLTK/fl_callbacks.cpp:6344 +msgid "MIDI support disabled\n" +msgstr "MIDI-Unterstützung wurde deaktiviert\n" + +#: src/FLTK/fl_callbacks.cpp:6406 +msgid "The CC value must be between 0 and 127" +msgstr "Der CC-Wert muss zwischen 0 und 127 liegen" + +#: src/FLTK/fl_callbacks.cpp:6429 +msgid "Waiting..." +msgstr "Warte..." + +#: src/FLTK/fl_funcs.cpp:193 +msgid "Disabled" +msgstr "Deaktiviert" + +#: src/FLTK/fl_funcs.cpp:335 +#, c-format +msgid "%d seconds" +msgstr "%d Sekunden" + +#: src/FLTK/fl_funcs.cpp:386 +msgid "Not supported on Windows" +msgstr "Wird nicht unterstüzt" + +#: src/FLTK/fl_funcs.cpp:808 +msgid "Start/Stop broadcasting" +msgstr "Stream starten/stoppen" + +#: src/FLTK/fl_funcs.cpp:809 +msgid "Start/Stop recording" +msgstr "Aufnahme starten/stoppen" + +#: src/FLTK/fl_funcs.cpp:811 +msgid "Streaming Gain" +msgstr "Streaming Verstärkung" + +#: src/FLTK/fl_funcs.cpp:812 +msgid "Recording Gain" +msgstr "Aufnahme Verstärkung" + +#: src/FLTK/fl_funcs.cpp:813 +msgid "Primary Device Gain" +msgstr "Vestärkung des primären Gerätes" + +#: src/FLTK/fl_funcs.cpp:814 +msgid "Secondary Device Gain" +msgstr "Vestärkung des sekundären Gerätes" + +#: src/FLTK/fl_funcs.cpp:815 +msgid "Cross fader" +msgstr "Cross Fader" + +#: src/FLTK/fl_funcs.cpp:816 +msgid "Mute/Unmute Primary Device" +msgstr "Primäres Audiogerät ein/aus" + +#: src/FLTK/fl_funcs.cpp:817 +msgid "Mute/Unmute Secondary Device" +msgstr "Sekundäres Audiogerät ein/aus" + +#: src/FLTK/fl_funcs.cpp:818 +msgid "Start broadcasting" +msgstr "Stream starten" + +#: src/FLTK/fl_funcs.cpp:819 +msgid "Stop broadcasting" +msgstr "Stream beenden" + +#: src/FLTK/fl_funcs.cpp:820 +msgid "Start recording" +msgstr "Aufnahme starten" + +#: src/FLTK/fl_funcs.cpp:821 +msgid "Stop recording" +msgstr "Aufnahme beenden" + +#: src/FLTK/fl_funcs.cpp:870 +msgid "dev. not supported" +msgstr "Gerät wird nicht unterstützt" + +#: src/FLTK/fl_funcs.cpp:1087 +#, c-format +msgid "" +"Could not create recording folder:\n" +"%s\n" +"Please make sure the folder contains only valid format specifiers." +msgstr "" +"Aufnahmeordner konnte nicht erstellt werden:\n" +"%s\n" +"Bitte vergewissern Sie sich, dass der Pfad ausschließlich gültige " +"Vormatvariablen beeinhaltet." + +#: src/FLTK/fl_funcs.cpp:1102 +#, c-format +msgid "Could not create recording folder %s\n" +msgstr "Konnte Datei nicht schreiben: %s\n" + +#: src/FLTK/fl_funcs.cpp:1111 +#, c-format +msgid "" +"Could not create recording file:\n" +"%s\n" +"Please make sure the filename contains only valid format specifiers." +msgstr "" +"Aufnahmedatei konnte nicht erstellt werden:\n" +"%s\n" +"Bitte vergewissern Sie sich, dass der Dateiname ausschließlich gültige " +"Vormatvariablen beeinhaltet." + +#: src/FLTK/fl_funcs.cpp:1157 +msgid "Could not find a valid filename" +msgstr "Konnte keinen gültigen Dateinamen finden" + +#: src/FLTK/fl_funcs.cpp:1462 +msgid "TRUST" +msgstr "VERTRAUE" + +#: src/icecast.cpp:90 +msgid "" +"\n" +"connect: Could not create network socket" +msgstr "" +"\n" +"connect: Netzwerk socket konnte nicht erstellt werden" + +#: src/icecast.cpp:102 +msgid "" +"\n" +"connect: Error resolving server address" +msgstr "" +"\n" +"connect: Konnte Servernamen nicht auflösen" + +#: src/icecast.cpp:142 +msgid "" +"\n" +"connect: SSL connection timed out. Trying again..." +msgstr "" +"\n" +"connect: Zeitüberschreitung der SSL-Verbindung . Versuche erneut..." + +#: src/icecast.cpp:149 +#, c-format +msgid "" +"SSL/TLS certificate verification failed\n" +"Reason: %s\n" +"\n" +"Do you still want to trust this certificate?\n" +"Trusting will be permanent and can be revoked\n" +"in the server settings." +msgstr "" +"SSL/TLS Zertfikat ist ungültig\n" +"Grund: %s\n" +"\n" +"Möchtest Du dem Zertifikat dennoch vertrauen?\n" +"Das Vertrauen kann zu einem späteren Zeitpunkt\n" +"in den Servereinstellungen zurückgezogen werden." + +#: src/icecast.cpp:164 +#, c-format +msgid "" +"\n" +"connect: SSL connection failed\n" +"Reason: %s" +msgstr "" +"\n" +"connect: SSL Verbindung fehlgeschlagen\n" +"Grund: %s" + +#: src/icecast.cpp:320 +msgid "" +"\n" +"connect: connection timed out. Trying again..." +msgstr "" +"\n" +"connect: Zeitüberschreitung. Versuche erneut..." + +#: src/icecast.cpp:373 +msgid "" +"\n" +"connect: server answered with 400!\n" +msgstr "" +"\n" +"connect: Server hat mit Fehler 400 geantworted.\n" + +#: src/icecast.cpp:379 +msgid "" +"\n" +"connect: invalid user/password!\n" +msgstr "" +"\n" +"connect: Falscher Benutzername oder Passwort\n" + +#: src/icecast.cpp:402 +msgid "" +"\n" +"connect: server answered with 404!\n" +msgstr "" +"\n" +"connect: Server hat mit 404 geantwortet. Falscher mountpoint?\n" + +#: src/icecast.cpp:409 +#, c-format +msgid "" +"\n" +"connect: server answered with %d!\n" +msgstr "" +"\n" +"connect: Server hat mit %d geantwortet\n" + +#: src/icecast.cpp:434 +msgid "" +"\n" +"ERROR: Opus is not supported by your\n" +"Icecast server (>=1.4.0 required)!\n" +msgstr "" +"\n" +"FEHLER: Opus wird von Deinem Icecast server\n" +"nicht unterstützt (>=1.4.0 wird benötigt)!\n" + +#: src/icecast.cpp:507 +msgid "" +"\n" +"update_song: could not create network socket" +msgstr "" +"\n" +"update_song: Konnte Netzwerk socket nicht erstellen" + +#: src/icecast.cpp:511 +msgid "" +"\n" +"update_song: error resolving server address" +msgstr "" +"\n" +"update_song: Konnte Servernamen nicht auflösen" + +#: src/lame_encode.cpp:74 +#, c-format +msgid "unable to init lame params %d" +msgstr "Lame Parameter konnten nicht initialisiert werden %d" + +#: src/port_audio.cpp:131 +#, c-format +msgid "" +"PortAudio init failed:\n" +"%s\n" +msgstr "" +"PortAudio Initialisierung fehlgeschlagen:\n" +"%s\n" + +#: src/port_audio.cpp:180 +msgid "ERROR: no sound device with input channels found" +msgstr "FEHLER: Konnte kein Aufnahmegerät finden" + +#: src/port_audio.cpp:198 src/port_audio.cpp:289 src/port_audio.cpp:1331 +#: src/port_midi.cpp:177 +#, c-format +msgid "Error getting device Info (%d)" +msgstr "Fehler beim Einholen der Geräteinfos (%d)" + +#: src/port_audio.cpp:241 +#, c-format +msgid "" +"Samplerate not supported: %dHz\n" +"Using default samplerate: %dHz" +msgstr "" +"Samplerate nicht unterstsützt: %dHz\n" +"Nutze Samplerate: %dHz" + +#: src/port_audio.cpp:258 src/port_audio.cpp:360 +#, c-format +msgid "PA: Format not supported: %s\n" +msgstr "PA: Format wird nicht unterstützt: %s\n" + +#: src/port_audio.cpp:268 +#, c-format +msgid "error opening sound device: %s" +msgstr "Fehler beim Öffnen des Audiogerätes: %s" + +#: src/port_audio.cpp:326 +msgid "The selected secondary audio device can not be used" +msgstr "Das ausgewählte sekundäre Audiogerät kann nicht verwendet werden" + +#: src/port_audio.cpp:343 src/port_audio.cpp:1452 src/port_audio.cpp:1469 +msgid "ERROR: Could not initialize samplerate converter" +msgstr "FEHLER: Konnte Sampleratenkonverter nicht initialisieren" + +#: src/port_audio.cpp:354 +#, c-format +msgid "Samplerate of secondary device is resampled from %dHz to %dHz\n" +msgstr "" +"Die Samplerate des sekundären Audiogerätes wird von %dHz auf %dHz angepasst\n" + +#: src/port_audio.cpp:381 +#, c-format +msgid "error opening secondary sound device: %s" +msgstr "Fehler beim Öffnen des sekundären Audiogerätes: %s" + +#: src/port_audio.cpp:921 +msgid "disconnected\n" +msgstr "Verbindung getrennt\n" + +#: src/port_audio.cpp:949 +msgid "recording stopped" +msgstr "Aufnahme gestoppt" + +#: src/port_midi.cpp:152 src/port_midi.cpp:211 src/port_midi.cpp:233 +#: src/port_midi.cpp:255 src/port_midi.cpp:282 src/port_midi.cpp:301 +#: src/port_midi.cpp:316 src/port_midi.cpp:341 src/port_midi.cpp:352 +msgid "Error: PortMidi was not initialized." +msgstr "Error: PortMidi wurde nicht initialisiert." + +#: src/port_midi.cpp:262 +#, c-format +msgid "" +"Error: MIDI device %s could not be opened because no MIDI devices were found." +msgstr "" +"Error: Das MIDI-Gerät %s konnte nicht geöffnet werden, weil keine MIDI-" +"Geräte gefunden wurden." + +#: src/port_midi.cpp:269 +#, c-format +msgid "Error: MIDI device %s could not be found." +msgstr "Das MIDI-Gerät %s wurde nicht gefunden." + +#: src/port_midi.cpp:286 +msgid "Error: MIDI thread already active." +msgstr "Error: MIDI-Thread läuft bereits." + +#: src/port_midi.cpp:291 +msgid "Error: Could not start MIDI thread." +msgstr "Error: MIDI-Thread konnte nicht gestartet werden." + +#: src/shoutcast.cpp:80 +msgid "" +"\n" +"Connect: Could not create network socket" +msgstr "" +"\n" +"Connect: Netzwerk Socket konnte nicht erstellen werden" + +#: src/shoutcast.cpp:92 +msgid "" +"\n" +"Connect: Error resolving server address" +msgstr "" +"\n" +"Connect: Fehler beim Auflösen des Servernamens" + +#: src/shoutcast.cpp:172 +msgid "" +"\n" +"connect: connection timed out. Trying again...\n" +msgstr "" +"\n" +"connect: Zeitüberschreitung. Versuche erneut...\n" + +#: src/shoutcast.cpp:189 +msgid "" +"\n" +"Connect: Invalid password!\n" +msgstr "" +"\n" +"Connect: Falsches Passwort\n" + +#: src/shoutcast.cpp:238 +msgid "" +"\n" +"Update song: Could not create network socket" +msgstr "" +"\n" +"Update song: Netzwerk Socket konnte nicht erstellt werden" + +#: src/shoutcast.cpp:242 +msgid "" +"\n" +"Update song: Error resolving server address" +msgstr "" +"\n" +"Update song: Fehler beim Auflösung des Servernamens" + +#: src/tls.cpp:159 +msgid "check_host: could not read host name from cert" +msgstr "check_host: Zertifikat enthält keinen Hostnamen" + +#: src/tls.cpp:194 +msgid "check_cert: No peer certificate available" +msgstr "check_cert: Kein peer Zertifikat vorhanden" + +#: src/tls.cpp:207 +msgid "check_cert: X509_check_host failed" +msgstr "check_cert: X509_check_host fehlgeschlagen" + +#: src/tls.cpp:213 +msgid "check_cert: check_host failed" +msgstr "check_ert: check_host fehlgeschlagen" + +#: src/tls.cpp:229 +msgid "calc_cert_hash: No peer certificate available" +msgstr "calc_cert_hash: Kein peer Zertifikat vorhanden" + +#: src/tls.cpp:236 +msgid "calc_cert_hash: Hash calculation failed" +msgstr "calc_cert_hash: Konnte Hash nicht berechnen" + +#: src/tls.cpp:305 +msgid "tls_setup: Could not set cipher list" +msgstr "tls_setup: Konnte cipher Liste nicht setzen" + +#: src/tls.cpp:318 +msgid "tls_setup: SSL_new failed" +msgstr "tls_setup: SSL_new fehlgeschlagen" + +#: src/tls.cpp:324 +msgid "tls_setup: Could not bind socket to SSL" +msgstr "tls_setup: Konnte socket nicht an SSL binden" + +#: src/tls.cpp:338 +msgid "tls_setup: SSL_connect read timeout" +msgstr "tls_setup: SSL_connect Zeitüberschreitung beim Lesen" + +#: src/tls.cpp:344 +msgid "tls_setup: SSL_connect write timeout" +msgstr "tls_setup: SSL_connect Zeitüberschreitung beim Schreiben" + +#: src/tls.cpp:361 +msgid "tls_setup: Cert hash could not be calculated" +msgstr "tls_setup: Es konnte kein Hashwert für das Zertifikat berechnet werden" + +#: src/tls.cpp:385 +msgid "tls_send: read timeout" +msgstr "tls_send: Zeitüberschreitung beim Lesen" + +#: src/tls.cpp:392 +msgid "tls_send: write timeout" +msgstr "tls_send: Zeitüberschreitung beim Schreiben" + +#: src/tls.cpp:418 +msgid "tls_recv: read timeout" +msgstr "tls_recv: Zeitüberschreitung beim Lesen" + +#: src/tls.cpp:425 +msgid "tls_recv: write timeout" +msgstr "tls_recv: Zeitüberschreitung beim Schreiben" + +#~ msgid "Listeners: 99999" +#~ msgstr "Zuhörer: 99999" + +#~ msgid "Resample output" +#~ msgstr "Resample Frequenz" + +#~ msgid "Resample output to selected sample rate" +#~ msgstr "Ausgang zur selektierten Samplerate resamplen" + +#, c-format +#~ msgid "" +#~ "error while parsing config. Missing WebRTC WHIP URL entry for server " +#~ "\"%s\".\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "Fehler beim Lesen der Konfigurationsdatei. Die WebRTC WHIP URL für Server " +#~ "\"%s\" fehlt.\n" +#~ "butt wird mit den Standardeinstellungen gestartet" + +#, c-format +#~ msgid "" +#~ "error while parsing config. Missing WebRTC ICE server entry for server " +#~ "\"%s\".\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "Fehler beim Lesen der Konfigurationsdatei. Der WebRTC ICE Server Eintrag " +#~ "für Server \"%s\" fehlt.\n" +#~ "butt wird mit den Standardeinstellungen gestartet" + +#~ msgid "No ICE server specified" +#~ msgstr "Kein ICE Server angegeben" + +#~ msgid "Text color" +#~ msgstr "Textfarbe " + +#~ msgid "Preset " +#~ msgstr "Voreinstellung" + +#~ msgid "Volume of Primary Device" +#~ msgstr "Lautstärke des primäre Audiogerätes" + +#~ msgid "Volume of Secondary Device" +#~ msgstr "Lautstärke des sekundären Audiogerätes" + +#~ msgid "" +#~ "error while parsing config. Illegal value (-1) for num_of_srv.\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "Fehler beim lesen der Konfigurationsdatei. Ungültiger Wert (-1) für " +#~ "num_of_srv.\n" +#~ "butt wird mit den Standardeinstellungen gestartet" + +#~ msgid "" +#~ "error while parsing config. Illegal value (-1) for num_of_icy.\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "Fehler beim Lesen der Konfigurationsdatei. Ungültiger Wert (-1) für " +#~ "num_of_icy.\n" +#~ "butt wird mit den Standardeinstellungen gestartet" + +#~ msgid "Dash address has been copied to clipboard." +#~ msgstr "Dash Adresse wurde in die Zwischenablage kopiert." + +#~ msgid "Dash" +#~ msgstr "Dash" + +#~ msgid "recording to:" +#~ msgstr "Nehme auf nach:" + +#~ msgid "Convert Mono to Stereo" +#~ msgstr "Konvertiere Mono nach Stereo" + +#~ msgid "Copies a mono channel to both stereo channels" +#~ msgstr "Kopiert einen Mono Kanal in beide Stereo Kanäle" + +#~ msgid "IceCast" +#~ msgstr "IceCast" + +#~ msgid "3.5kHz" +#~ msgstr "3.5kHz" + +#~ msgid "10kHz" +#~ msgstr "10kHz" + +#~ msgid "hello\n" +#~ msgstr "HAllo\n" + +#~ msgid "More @2<" +#~ msgstr "Mehr @2<" diff --git a/po/en@boldquot.header b/po/en@boldquot.header new file mode 100644 index 0000000..fedb6a0 --- /dev/null +++ b/po/en@boldquot.header @@ -0,0 +1,25 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# +# This catalog furthermore displays the text between the quotation marks in +# bold face, assuming the VT100/XTerm escape sequences. +# diff --git a/po/en@quot.header b/po/en@quot.header new file mode 100644 index 0000000..a9647fc --- /dev/null +++ b/po/en@quot.header @@ -0,0 +1,22 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# diff --git a/po/es.gmo b/po/es.gmo new file mode 100644 index 0000000..0f9909a Binary files /dev/null and b/po/es.gmo differ diff --git a/po/es.po b/po/es.po new file mode 100644 index 0000000..a46fdec --- /dev/null +++ b/po/es.po @@ -0,0 +1,3239 @@ +# Spanish translation for butt-0.1.41 package. +# Copyright (C) 2021 Daniel Nöthen +# This file is distributed under the same license as the butt package. +# 01iver , 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: butt 1.45.0\n" +"Report-Msgid-Bugs-To: butt@danielnoethen.de\n" +"POT-Creation-Date: 2025-04-19 14:55+0200\n" +"PO-Revision-Date: 2025-04-19 15:14+0200\n" +"Last-Translator: 01iver \n" +"Language-Team: Spanish\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 3.0.1\n" + +#: src/AskForMicPermission.m:20 +msgid "Microphone access" +msgstr "Acesso al micrófono" + +#: src/AskForMicPermission.m:21 +msgid "" +"butt needs access to your microphone.\n" +"\n" +"Please go to\n" +"System Preferences->Privacy & Security->Microphone\n" +"and activate the check mark next to the butt entry." +msgstr "" +"butt necesita acceder a su micrófono\n" +"Por favor, vaya a\n" +"Preferencias del Sistema->Seguridad y privacidad->Privacidad->Micrófono\n" +"y active la casilla de verificación junto a la línea de butt" + +#: src/butt.cpp:219 +msgid "No home-directory found" +msgstr "No se encontró directorio de inicio" + +#: src/butt.cpp:230 +#, c-format +msgid "" +"The shift key was held down during startup.\n" +"Do you want to start butt with a new configuration file?\n" +"This will overwrite your existing configuration file at\n" +"%s" +msgstr "" +"La tecla Shift (mayúsculas) estaba presionada durante el inicio\n" +"¿Desea iniciar butt con un archivo de configuración nuevo?\n" +"Esto sobreescribirá su archivo de configuración existente en\n" +"%s" + +#: src/butt.cpp:233 +msgid "Start with old" +msgstr "Iniciar con el anterior" + +#: src/butt.cpp:233 +msgid "Start with new" +msgstr "Iniciar con el nuevo" + +#: src/butt.cpp:236 src/butt.cpp:253 +#, c-format +msgid "" +"Could not create config %s\n" +"butt is going to close now" +msgstr "" +"No se pudo crear la configuración %s\n" +"butt se cerrará ahora" + +#: src/butt.cpp:242 +#, c-format +msgid "Reading config %s\n" +msgstr "Leyendo la configuración %s\n" + +#: src/butt.cpp:250 +#, c-format +msgid "Could not find config %s\n" +msgstr "No pudo encontrar la configuración %s\n" + +#: src/butt.cpp:257 +#, c-format +msgid "" +"butt created a default config at\n" +"%s\n" +msgstr "" +"butt creó una configuración por defecto en\n" +"%s\n" + +#: src/butt.cpp:265 +msgid "" +"Could not find any audio device with input channels.\n" +"butt requires at least one audio device with input channels in order to " +"work.\n" +"This can either be a built-in audio device, an external audio device or a " +"virtual audio device.\n" +"\n" +"butt is going to close now." +msgstr "" +"No se pudo encontrar un dispositivo de audio con canales de entrada\n" +"butt requiere al menos un dispositivo de audio con canales de entrada para " +"funcionar.\n" +"Puede ser un dispositivo de audio integrado, externo o virtual.\n" +"\n" +"butt se cerrará ahora." + +#: src/butt.cpp:358 +#, c-format +msgid "Illegal argument: Threshold must be a non-negative number\n" +msgstr "Argumento inválido: El umbral debe ser un número positivo\n" + +#: src/butt.cpp:382 +#, c-format +msgid "%c threshold set to %0.1f\n" +msgstr "Umbral de %c definido en %0.1f\n" + +#: src/butt.cpp:464 +#, c-format +msgid "Illegal argument: Port must be a number between 1023 and 65535\n" +msgstr "Argumento inválido: El puerto debe ser un número entre 1023 y 65535\n" + +#: src/butt.cpp:472 src/butt.cpp:482 src/butt.cpp:489 src/butt.cpp:496 +#: src/butt.cpp:503 src/butt.cpp:510 src/butt.cpp:521 src/butt.cpp:540 +#: src/butt.cpp:550 src/butt.cpp:597 +#, c-format +msgid "" +"Warning: You may only pass one control option. Option -%c has been ignored.\n" +msgstr "" +"Advertencia: Solo puede pasar una opción de control. La opción -%c se ha " +"ignorado.\n" + +#: src/butt.cpp:559 +#, c-format +msgid "" +"\n" +"Options:\n" +"-h\tPrint this help text\n" +"-v\tPrint version information\n" +msgstr "" +"\n" +"Opciones:\n" +"-h\tImprima este texto de ayuda\n" +"-v\tImprima la información sobre la versión\n" + +#: src/butt.cpp:563 +#, c-format +msgid "" +"\n" +"Options for operating mode:\n" +"-c\tPath to configuration file\n" +"-L\tPrint available audio devices\n" +"-A\tCommand server will be accessible from your network/internet (default: " +"localhost only)\n" +"-U\tCommand server will use UDP instead of TCP\n" +"-x\tDo not start a command server\n" +"-p\tPort where the command server shall listen to (default: 1256)\n" +msgstr "" +"\n" +"Opciones para el modo de operación\n" +"-c\tRuta del archivo de configuración\n" +"-L\tImprimir dispositivos de audio disponibles\n" +"-A\tServidor de mandatos que será accesible desde su red o internet (por " +"defecto: solamente localhost)\n" +"-U\tEl servidor de mandatos usará UDP en vez de TCP\n" +"-x\tNo iniciar un servidor de mandatos\n" +"-p\tPuerto que escuchará el servidor de mandatos (por defecto: 1256)\n" + +#: src/butt.cpp:572 +#, c-format +msgid "" +"\n" +"Options for control mode:\n" +"-s\tConnect to streaming server\n" +"-d\tDisconnect from streaming server\n" +"-r\tStart recording\n" +"-t\tStop recording\n" +"-n\tSplit recording\n" +"-q\tQuit butt\n" +"-u\tupdate song name\n" +"-S\tRequest status\n" +"-M\tSet streaming signal threshold (seconds)\n" +"-m\tSet streaming silence threshold (seconds)\n" +"-O\tSet recording signal threshold (seconds)\n" +"-o\tSet recording silence threshold (seconds)\n" +"-U\tConnect via UDP instead of TCP\n" +"-a\tAddress of the butt instance to be controlled (default: 127.0.0.1)\n" +"-p\tPort of the butt instance to be controlled (default: 1256)\n" +msgstr "" +"\n" +"Opciones para el modo de control:\n" +"-s\tConectar al servidor de streaming\n" +"-d\tDesconectar del servidor de streaming\n" +"-r\tComenzar grabación\n" +"-t\tDetener grabación\n" +"-n\tDividir grabación\n" +"-q\tSalir de butt\n" +"-u\tactualizar nombre de la canción\n" +"-S\tEstado de la solicitud\n" +"-M\tDefinir umbral de señal para streaming (segundos)\n" +"-m\tDefinir umbral de silencio (segundos)\n" +"-O\tDefinir umbral de señal para grabación (segundos)\n" +"-o\tDefinir umbral de silencio para grabación (segundos)\n" +"-U\tConectar por UDP en vez de TCP\n" +"-a\tDirección de la instancia de butt a controlar (por defecto: 127.0.0.1)\n" +"-p\tPuerto de la instancia de butt a controlar (por defecto: 1256)\n" + +#: src/butt.cpp:591 +#, c-format +msgid "" +"Illegal option -%c.\n" +"Type butt -h to get a list of supported options.\n" +msgstr "" +"Opción inválida -%c.\n" +"Escriba butt -h para obtener una lista de opciones permitidas.\n" + +#: src/butt.cpp:603 +#, c-format +msgid "Option -%c requires an argument\n" +msgstr "La opción -%c requiere un argumento\n" + +#: src/butt.cpp:607 +#, c-format +msgid "Command line parsing failed\n" +msgstr "Falló el análisis de la línea del mandato\n" + +#: src/butt.cpp:630 +#, c-format +msgid "No butt instance running on %s at port %d\n" +msgstr "No hay una instancia de butt en ejecución en %s en el puerto %d\n" + +#: src/butt.cpp:635 +#, c-format +msgid "Error while sending command\n" +msgstr "Error al enviar el mandato\n" + +#: src/butt.cpp:640 +#, c-format +msgid "Error: Did not receive response packet\n" +msgstr "Error: No se recibió el paquete de respuesta\n" + +#: src/butt.cpp:653 +#, c-format +msgid "Error: You may only request one status packet per second\n" +msgstr "Error: Solo puede solicitar un paquete de status por segundo\n" + +#: src/butt.cpp:657 +#, c-format +msgid "Error: Did not receive status packet (UDP server not running?)\n" +msgstr "" +"No se recibió paquete de status (El servidor de UDP no está en ejecución?)\n" + +#: src/butt.cpp:661 +#, c-format +msgid "Network error while receiving status packet: %d\n" +msgstr "Error de red al recibir el paquete de status: %d\n" + +#: src/butt.cpp:665 +#, c-format +msgid "Error: Client and server versions do not match\n" +msgstr "Error: Las versiones de cliente y servidor no coinciden\n" + +#: src/butt.cpp:676 +#, c-format +msgid "" +"connected: %d\n" +"connecting: %d\n" +"recording: %d\n" +"signal present: %d\n" +"signal absent: %d\n" +msgstr "" +"conectado: %d\n" +"conectando: %d\n" +"grabando: %d\n" +"señal presente: %d\n" +"señal ausente: %d\n" + +#: src/butt.cpp:681 +#, c-format +msgid "stream seconds: %lu\n" +msgstr "segundos streaming: %lu\n" + +#: src/butt.cpp:682 +#, c-format +msgid "stream kBytes: %lu\n" +msgstr "kBytes streaming: %lu\n" + +#: src/butt.cpp:683 +#, c-format +msgid "record seconds: %lu\n" +msgstr "segundos grabación: %lu\n" + +#: src/butt.cpp:684 +#, c-format +msgid "record kBytes: %lu\n" +msgstr "kBytes grabación: %lu\n" + +#: src/butt.cpp:685 +#, c-format +msgid "volume left: %0.1f\n" +msgstr "volumen izquierda: %0.1f\n" + +#: src/butt.cpp:686 +#, c-format +msgid "volume right: %0.1f\n" +msgstr "volumen derecha: %0.1f\n" + +#: src/butt.cpp:687 +#, c-format +msgid "song: %s\n" +msgstr "canción: %s\n" + +#: src/butt.cpp:688 +#, c-format +msgid "record path: %s\n" +msgstr "ruta de grabación: %s\n" + +#: src/butt.cpp:689 +#, c-format +msgid "listeners: %d\n" +msgstr "Oyentes: %d\n" + +#: src/butt.cpp:703 +msgid "" +"The control key was held down during startup.\n" +"butt will start without opening an audio device.\n" +"Please select your preferred audio device in settings->audio" +msgstr "" +"La tecla Control estaba presionada durante el arranque.\n" +"butt iniciará sin abrir ningún dispositivo de audio.\n" +"Por favor, seleccione su dispositivo preferido en Config. -> audio" + +#: src/butt.cpp:712 +msgid "" +"PortAudio init failed\n" +"butt is going to close now" +msgstr "" +"Falló la inicialización de PortAudio\n" +"butt se cerrará ahora" + +#: src/butt.cpp:747 src/FLTK/fl_timer_funcs.cpp:476 +#: src/FLTK/fl_callbacks.cpp:123 src/FLTK/fl_callbacks.cpp:899 +#: src/FLTK/fl_callbacks.cpp:977 src/FLTK/fl_funcs.cpp:1047 +msgid "idle" +msgstr "inactivo" + +#: src/butt.cpp:780 +#, c-format +msgid "" +"Starting %s\n" +"Written by Daniel Nöthen\n" +"iPhone/iPad client: https://izicast.de\n" +"Donate: paypal@danielnoethen.de\n" +msgstr "" +"Iniciando %s\n" +"Escrito por Daniel Nöthen\n" +"Cliente iPhone/iPad: https://izicast.de\n" +"Donaciones: paypal@danielnoethen.de\n" + +#: src/butt.cpp:792 src/butt.cpp:793 src/cfg.cpp:577 src/port_audio.cpp:1314 +#: src/port_audio.cpp:1315 +msgid "Default PCM device (default)" +msgstr "Dispositivo PCM predeterminado (por defecto)" + +#: src/butt.cpp:796 src/butt.cpp:797 src/cfg.cpp:578 +#: src/FLTK/fl_callbacks.cpp:2820 src/FLTK/fl_funcs.cpp:227 +msgid "None" +msgstr "Ninguno" + +#: src/butt.cpp:800 +msgid "" +"Could not open audio device.\n" +"Please select your preferred audio device in settings->audio" +msgstr "" +"No se pudo abrir el dispositivo de audio.\n" +"Por favor, seleccione su dispositivo preferido en Config. -> audio" + +#: src/butt.cpp:803 +msgid "" +"butt could not open previously used audio device.\n" +"The system default audio device will be used.\n" +msgstr "" +"butt no pudo abrir el dispositivo de audio usado anteriormente.\n" +"Se usará el dispositivo de audio predeterminado del sistema.\n" + +#: src/butt.cpp:830 +#, c-format +msgid "Command server listening on port %d\n" +msgstr "Servidor de mandatos escuchando en el puerto %d\n" + +#: src/butt.cpp:837 +#, c-format +msgid "Warning: could not start command server on port %d\n" +msgstr "" +"Advertencia: no se pudo iniciar el servidor de mandatos en el puerto %d\n" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:4225 +#, c-format +msgid "" +"New version available: %s\n" +"You have version %s" +msgstr "" +"Nueva versión disponible: %s\n" +"Usted tiene la versión %s" + +#: src/butt.cpp:853 +msgid "Don't ask again" +msgstr "No volver a preguntar" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:1594 +#: src/FLTK/fl_callbacks.cpp:4225 +msgid "Cancel" +msgstr "Cancelar" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:4225 +msgid "Get new version" +msgstr "Obtener nueva versión" + +#: src/butt.cpp:874 +#, c-format +msgid "Could not initialize PortMidi: %s" +msgstr "No se pudo inicializar PortMidi: %s" + +#: src/butt.cpp:902 +msgid "butt was built without WebRTC support" +msgstr "butt se construyó sin apoyo de WebRTC" + +#: src/cfg.cpp:55 +#, c-format +msgid "Could not write to file: %s" +msgstr "No se pudo escribir en el archivo: %s" + +#: src/cfg.cpp:550 +#, c-format +msgid "Config written to %s" +msgstr "Configuración escrita en %s" + +#: src/cfg.cpp:674 +msgid "" +"error while parsing config. Missing main/server entry.\n" +"butt will start with default settings" +msgstr "" +"Error al analizar la configuración. Falta el servidor principal.\n" +"butt iniciará con la configuración por defecto" + +#: src/cfg.cpp:680 +msgid "" +"error while parsing config. Missing main/srv_ent entry.\n" +"butt will start with default settings" +msgstr "" +"Error al analizar la configuración. Falta el servidor principal (main/" +"srv_ent).\n" +"butt iniciará con la configuración por defecto" + +#: src/cfg.cpp:699 +#, c-format +msgid "" +"error while parsing config. Missing type entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"Error al analizar la configuración. Falta el tipo para el servidor \"%s\".\n" +"butt iniciará con la configuración por defecto" + +#: src/cfg.cpp:707 +#, c-format +msgid "" +"error while parsing config. Missing address entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"Error al analizar la configuración. Falta la dirección del servidor \"%s\".\n" +"butt iniciará con la configuración por defecto" + +#: src/cfg.cpp:716 +#, c-format +msgid "" +"error while parsing config. Missing port entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"Error al analizar la configuración. Falta el puerto para el servidor " +"\"%s\".\n" +"butt iniciará con la configuración por defecto" + +#: src/cfg.cpp:725 +#, c-format +msgid "" +"error while parsing config. Missing password entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"Error al analizar la configuración. Falta la contraseña para el servidor " +"\"%s\".\n" +"butt iniciará con la configuración por defecto" + +#: src/cfg.cpp:734 +#, c-format +msgid "" +"error while parsing config. Missing mount entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"Error al analizar la configuración. Falta el punto de montaje \"%s\".\n" +"butt iniciará con la configuración por defecto" + +#: src/cfg.cpp:790 +msgid "" +"error while parsing config. Missing main/icy entry.\n" +"butt will start with default settings" +msgstr "" +"Error al analizar la configuración. Falta el valor de icy principal (main/" +"icy).\n" +"butt iniciará con la configuración por defecto" + +#: src/cfg.cpp:795 +msgid "" +"error while parsing config. Missing main/icy_ent entry.\n" +"butt will start with default settings" +msgstr "" +"Error al analizar la configuración. Falta el valor de icy principal (main/" +"icy_ent).\n" +"butt iniciará con la configuración por defecto" + +#: src/cfg.cpp:821 +#, c-format +msgid "" +"error while parsing config. Missing pub entry for icy \"%s\".\n" +"butt will start with default settings" +msgstr "" +"Error al analizar la configuración. Falta el valor pub para icy \"%s\".\n" +"butt iniciará con la configuración por defecto" + +#: src/FLTK/flgui.cpp:3088 +msgid "Bitcoin address has been copied to clipboard." +msgstr "Se copió la dirección de Bitcoin al portapapeles." + +#: src/FLTK/flgui.cpp:3099 +msgid "Litecoin address has been copied to clipboard." +msgstr "Se copió la dirección de Litecoin al portapapeles." + +#: src/FLTK/flgui.cpp:3110 +msgid "Monero address has been copied to clipboard." +msgstr "Se copió la dirección de Monero al portapapeles." + +#: src/FLTK/flgui.cpp:4041 +msgid "press left mouse to toggle lcd info" +msgstr "" +"Presione click izquierdo en el ratón para activar o desactivar la " +"información del lcd" + +#: src/FLTK/flgui.cpp:4053 src/FLTK/fl_callbacks.cpp:4078 +msgid "Streaming volume" +msgstr "Volumen de streaming" + +#: src/FLTK/flgui.cpp:4057 +msgid "Mixer" +msgstr "Mezclador" + +#: src/FLTK/flgui.cpp:4058 +msgid "show/hide mixer window" +msgstr "Mostrar/ocultar Consola de mezclas" + +#: src/FLTK/flgui.cpp:4065 +msgid "@circle" +msgstr "@circle" + +#: src/FLTK/flgui.cpp:4066 +msgid "start/stop recording" +msgstr "iniciar/detener grabación" + +#: src/FLTK/flgui.cpp:4077 +msgid "@square" +msgstr "@square" + +#: src/FLTK/flgui.cpp:4078 +msgid "disconnect from server" +msgstr "desconectar del servidor" + +#: src/FLTK/flgui.cpp:4089 +msgid "@>" +msgstr "@>" + +#: src/FLTK/flgui.cpp:4090 +msgid "connect to server" +msgstr "conectar al servidor" + +#: src/FLTK/flgui.cpp:4106 src/FLTK/flgui.cpp:4438 src/FLTK/flgui.cpp:4657 +#: src/FLTK/fl_callbacks.cpp:4077 +msgid "Streaming" +msgstr "Streaming" + +#: src/FLTK/flgui.cpp:4110 src/FLTK/flgui.cpp:4469 src/FLTK/flgui.cpp:4771 +msgid "Recording" +msgstr "Grabación" + +#: src/FLTK/flgui.cpp:4140 +msgid "Settings" +msgstr "Config." + +#: src/FLTK/flgui.cpp:4141 +msgid "show/hide config window" +msgstr "Mostrar/ocultar ventana de configuración" + +#: src/FLTK/flgui.cpp:4148 src/FLTK/fl_callbacks.cpp:1098 +msgid "Show log" +msgstr "Mostrar log" + +#: src/FLTK/flgui.cpp:4149 +msgid "show/hide info window" +msgstr "Mostrar/ocultar ventana de información" + +#: src/FLTK/flgui.cpp:4156 +msgid "-24 dB" +msgstr "-24 dB" + +#: src/FLTK/flgui.cpp:4159 +msgid "Gain" +msgstr "Ganancia" + +#: src/FLTK/flgui.cpp:4160 src/FLTK/fl_callbacks.cpp:3663 +#: src/FLTK/fl_funcs.cpp:810 +msgid "Master Gain" +msgstr "Ganancia maestra" + +#: src/FLTK/flgui.cpp:4178 +msgid "+24 dB" +msgstr "+24 dB" + +#: src/FLTK/flgui.cpp:4185 +msgid "Listeners: 0" +msgstr "Oyentes: 0" + +#: src/FLTK/flgui.cpp:4200 +msgid "butt settings" +msgstr "configuraciones de butt" + +#: src/FLTK/flgui.cpp:4213 +msgid "Main" +msgstr "Principal" + +#: src/FLTK/flgui.cpp:4215 +msgid "Server Settings" +msgstr "Configuraciones del Servidor" + +#: src/FLTK/flgui.cpp:4218 +msgid "Server" +msgstr "Servidor" + +#: src/FLTK/flgui.cpp:4219 +msgid "Server to connect to" +msgstr "Servidor al que se conectará" + +#: src/FLTK/flgui.cpp:4224 src/FLTK/flgui.cpp:4245 +msgid "ADD" +msgstr "AGREGAR" + +#: src/FLTK/flgui.cpp:4225 src/FLTK/flgui.cpp:5550 +msgid "Add server" +msgstr "Agregar servidor" + +#: src/FLTK/flgui.cpp:4229 src/FLTK/flgui.cpp:4250 +msgid "EDIT" +msgstr "EDITAR" + +#: src/FLTK/flgui.cpp:4230 +msgid "Edit selected server" +msgstr "Editar servidor seleccionado" + +#: src/FLTK/flgui.cpp:4234 src/FLTK/flgui.cpp:4255 +msgid "DEL" +msgstr "ELIM" + +#: src/FLTK/flgui.cpp:4235 +msgid "Delete selected server" +msgstr "Eliminar servidor seleccionado" + +#: src/FLTK/flgui.cpp:4239 +msgid "Stream Infos" +msgstr "Información de transmisión" + +#: src/FLTK/flgui.cpp:4240 +msgid "Stream info that shall be used" +msgstr "Información de transmisión que se utlilizará" + +#: src/FLTK/flgui.cpp:4246 src/FLTK/flgui.cpp:5671 +msgid "Add stream info" +msgstr "Agregar información de transmisión" + +#: src/FLTK/flgui.cpp:4251 +msgid "Edit stream info" +msgstr "Editar información de transmisión" + +#: src/FLTK/flgui.cpp:4256 +msgid "Delete stream info" +msgstr "Eliminar información de transmisión" + +#: src/FLTK/flgui.cpp:4262 +msgid "Log File" +msgstr "Archivo de log" + +#: src/FLTK/flgui.cpp:4266 +msgid "Log file path" +msgstr "Dirección del archivo de log" + +#: src/FLTK/flgui.cpp:4271 +msgid "Select log file" +msgstr "Seleccionar archivo de log" + +#: src/FLTK/flgui.cpp:4278 +msgid "Configuration" +msgstr "Configuración" + +#: src/FLTK/flgui.cpp:4281 src/FLTK/fl_callbacks.cpp:4128 +msgid "Import..." +msgstr "Importar..." + +#: src/FLTK/flgui.cpp:4282 +msgid "Import settings from config file" +msgstr "Importar configuración desde archivo" + +#: src/FLTK/flgui.cpp:4286 src/FLTK/flgui.cpp:5615 src/FLTK/flgui.cpp:5717 +msgid "&Save" +msgstr "&Guardar" + +#: src/FLTK/flgui.cpp:4287 +msgid "Save settings" +msgstr "Guardar configuraciones" + +#: src/FLTK/flgui.cpp:4291 +msgid "Export..." +msgstr "Exportar..." + +#: src/FLTK/flgui.cpp:4292 +msgid "export settings" +msgstr "exportar configuraciones" + +#: src/FLTK/flgui.cpp:4298 +msgid "Butt Agent" +msgstr "Agente de Butt" + +#: src/FLTK/flgui.cpp:4301 +msgid "Start agent at startup" +msgstr "Comenzar agente al iniciar" + +#: src/FLTK/flgui.cpp:4302 +msgid "Start the butt agent when butt starts" +msgstr "Comenzar el agente de butt cuando butt inicie" + +#: src/FLTK/flgui.cpp:4306 src/FLTK/flgui.cpp:4307 +msgid "Minimize butt to tray" +msgstr "Minim. butt a la bandeja" + +#: src/FLTK/flgui.cpp:4311 +msgid "Start Agent" +msgstr "Iniciar Agente" + +#: src/FLTK/flgui.cpp:4312 +msgid "Start the butt agent now" +msgstr "Inicia el agente de butt ahora" + +#: src/FLTK/flgui.cpp:4316 +msgid "Stop Agent" +msgstr "Detener Agente" + +#: src/FLTK/flgui.cpp:4317 +msgid "Stop the butt agent" +msgstr "Detener el agente de butt" + +#: src/FLTK/flgui.cpp:4323 +msgid "Updates" +msgstr "Actualizaciones" + +#: src/FLTK/flgui.cpp:4326 +msgid "Check at startup" +msgstr "Verificar al iniciar" + +#: src/FLTK/flgui.cpp:4327 +msgid "Check for updates at start" +msgstr "Buscar actualizaciones al iniciar" + +#: src/FLTK/flgui.cpp:4331 +msgid "Check now" +msgstr "Verificar ahora" + +#: src/FLTK/flgui.cpp:4332 +msgid "Check if a new version is available" +msgstr "Verificar si hay una nueva versión disponible" + +#: src/FLTK/flgui.cpp:4338 +msgid "Help" +msgstr "Ayuda" + +#: src/FLTK/flgui.cpp:4341 +msgid "Manual" +msgstr "Manual" + +#: src/FLTK/flgui.cpp:4345 +msgid " YouTube" +msgstr "YouTube" + +#: src/FLTK/flgui.cpp:4355 +msgid "Audio" +msgstr "Audio" + +#: src/FLTK/flgui.cpp:4357 +msgid "Main Audio Settings" +msgstr "Configuraciones principales de audio" + +#: src/FLTK/flgui.cpp:4360 +msgid "Channel mode" +msgstr "Modo de canal" + +#: src/FLTK/flgui.cpp:4361 +msgid "Select input channel" +msgstr "Seleccione el canal de entrada" + +#: src/FLTK/flgui.cpp:4374 +msgid "Samplerate" +msgstr "Tasa de muestreo" + +#: src/FLTK/flgui.cpp:4375 +msgid "Select input sample rate" +msgstr "Seleccione la tasa de muestreo de entrada" + +#: src/FLTK/flgui.cpp:4380 +msgid "Remember Device by" +msgstr "Recordar dispositivo por" + +#: src/FLTK/flgui.cpp:4383 +msgid "ID" +msgstr "ID" + +#: src/FLTK/flgui.cpp:4388 +msgid "Name" +msgstr "Nombre" + +#: src/FLTK/flgui.cpp:4395 +msgid "Update devices" +msgstr "Actualizar dispositivos" + +#: src/FLTK/flgui.cpp:4396 +msgid "Rescan audio devices" +msgstr "Volver a buscar dispositivos de audio" + +#: src/FLTK/flgui.cpp:4400 +msgid "Primary Audio Device" +msgstr "Dispositivo de audio principal" + +#: src/FLTK/flgui.cpp:4401 +msgid "Select your primary sound card device" +msgstr "Seleccione la tarjeta de sonido de su dispositivo principal" + +#: src/FLTK/flgui.cpp:4406 src/FLTK/flgui.cpp:4424 +msgid "Left" +msgstr "Izquierda" + +#: src/FLTK/flgui.cpp:4407 src/FLTK/flgui.cpp:4425 +msgid "Select left audio channel" +msgstr "Seleccione el canal izquierdo de audio" + +#: src/FLTK/flgui.cpp:4412 src/FLTK/flgui.cpp:4430 +msgid "Right" +msgstr "Derecha" + +#: src/FLTK/flgui.cpp:4413 src/FLTK/flgui.cpp:4431 +msgid "Select right audio channel" +msgstr "Seleccione el canal derecho de audio" + +#: src/FLTK/flgui.cpp:4418 +msgid "Secondary Audio Device" +msgstr "Mezclador de audio" + +#: src/FLTK/flgui.cpp:4419 +msgid "Select your secondary sound card device" +msgstr "Seleccione la tarjeta de sonido de su dispositivo secundario" + +#: src/FLTK/flgui.cpp:4441 src/FLTK/flgui.cpp:4472 +msgid "Codec" +msgstr "Códec" + +#: src/FLTK/flgui.cpp:4442 +msgid "Select streaming codec" +msgstr "Seleccione el códec de streaming" + +#: src/FLTK/flgui.cpp:4455 src/FLTK/flgui.cpp:4486 +msgid "Bitrate" +msgstr "Tasa de bits" + +#: src/FLTK/flgui.cpp:4456 +msgid "Select streaming bitrate" +msgstr "Seleccionar la tasa de bits del streaming" + +#: src/FLTK/flgui.cpp:4473 +msgid "Select recording codec" +msgstr "Seleccionar el códec de grabación" + +#: src/FLTK/flgui.cpp:4487 +msgid "Select recording bitrate" +msgstr "Seleccionar la tasa de bits para la grabación" + +#: src/FLTK/flgui.cpp:4499 +msgid "Advanced..." +msgstr "Avanzado..." + +#: src/FLTK/flgui.cpp:4505 +msgid "Buffer (ms)" +msgstr "Buffer (ms)" + +#: src/FLTK/flgui.cpp:4514 +msgid "Resample Quality" +msgstr "Calidad de remuestreo" + +#: src/FLTK/flgui.cpp:4529 +msgid "Signal detection levels" +msgstr "Niveles de detección de señal" + +#: src/FLTK/flgui.cpp:4532 +msgid "Signal present" +msgstr "Señal presente" + +#: src/FLTK/flgui.cpp:4539 src/FLTK/flgui.cpp:4549 +msgid "dB" +msgstr "dB" + +#: src/FLTK/flgui.cpp:4542 +msgid "Signal absent" +msgstr "Señal ausente" + +#: src/FLTK/flgui.cpp:4556 src/FLTK/flgui.cpp:4833 src/FLTK/flgui.cpp:5084 +msgid "Stream" +msgstr "Stream" + +#: src/FLTK/flgui.cpp:4558 +msgid "Update song name from file" +msgstr "Actualizar nombre de canción desde archivo" + +#: src/FLTK/flgui.cpp:4562 +msgid "Filename that holds the current song name" +msgstr "Nombre de archivo que contiene el nombre de la canción actual" + +#: src/FLTK/flgui.cpp:4568 +msgid "Select file that holds the current song name" +msgstr "Seleccione el archivo que contiene el nombre de la canción actual" + +#: src/FLTK/flgui.cpp:4573 src/FLTK/flgui.cpp:4606 src/FLTK/flgui.cpp:4724 +msgid "Activate" +msgstr "Activar" + +#: src/FLTK/flgui.cpp:4574 src/FLTK/flgui.cpp:4579 +msgid "Activate auto update song name from file" +msgstr "Activar actualización automática de nombre de canción desde archivo" + +#: src/FLTK/flgui.cpp:4578 +msgid "Read last line instead of first" +msgstr "Leer últ. línea en vez de la primera" + +#: src/FLTK/flgui.cpp:4585 +msgid "Update song name from application" +msgstr "Actualizar nombre de la canción desde la aplicación" + +#: src/FLTK/flgui.cpp:4589 +msgid "Changes the song through an running application" +msgstr "Cambia la canción mediante una aplicación en ejecución" + +#: src/FLTK/flgui.cpp:4594 +msgid "Title - Artist" +msgstr "Título - Artista" + +#: src/FLTK/flgui.cpp:4599 +msgid "Artist - Title" +msgstr "Artista - Título" + +#: src/FLTK/flgui.cpp:4612 +msgid "Update song name manually" +msgstr "Actualizar nombre de canción manualmente" + +#: src/FLTK/flgui.cpp:4616 +msgid "Current song name" +msgstr "Nombre de la canción actual" + +#: src/FLTK/flgui.cpp:4622 src/FLTK/fl_callbacks.cpp:1594 +msgid "OK" +msgstr "OK" + +#: src/FLTK/flgui.cpp:4623 +msgid "Send current song name to the server" +msgstr "Enviar nombre de la canción actual al servidor" + +#: src/FLTK/flgui.cpp:4631 +msgid "Update song name delay" +msgstr "Tiempo espera para actualizar nombre canción" + +#: src/FLTK/flgui.cpp:4635 +msgid "Introduces a delay until the song name is actually updated" +msgstr "" +"Introduce un tiempo de espera hasta que el nombre de canción se actualice " +"realmente" + +#: src/FLTK/flgui.cpp:4642 +msgid "Extend song name" +msgstr "Extender el nombre de canción" + +#: src/FLTK/flgui.cpp:4645 +msgid "Prefix:" +msgstr "Prefijo:" + +#: src/FLTK/flgui.cpp:4650 +msgid "Suffix:" +msgstr "Sufijo:" + +#: src/FLTK/flgui.cpp:4660 src/FLTK/flgui.cpp:4789 +msgid "Start if signal is present for" +msgstr "Iniciar si hay señal durante" + +#: src/FLTK/flgui.cpp:4661 +msgid "" +"Start streaming if the audio level exceeds the \"Signal present\" level set " +"in the \"Audio\" tab" +msgstr "" +"Comenzar la transmisión si el nivel de audio supera el valor asignado en " +"\"Señal presente\" en la pestaña \"Audio\"" + +#: src/FLTK/flgui.cpp:4670 src/FLTK/flgui.cpp:4683 src/FLTK/flgui.cpp:4702 +#: src/FLTK/flgui.cpp:4799 src/FLTK/flgui.cpp:4812 src/FLTK/flgui.cpp:5499 +msgid "seconds" +msgstr "segundos" + +#: src/FLTK/flgui.cpp:4673 src/FLTK/flgui.cpp:4802 +msgid "Stop if signal is absent for" +msgstr "Detener si no hay señal durante" + +#: src/FLTK/flgui.cpp:4674 +msgid "" +"Stop streaming if the audio level falls below the \"Signal absent level set " +"in the \"Audio\" tab" +msgstr "" +"Detener la transmisión si el nivel de audio baja del valor asignado en " +"\"Señal presente\" en la pestaña \"Audio\"" + +#: src/FLTK/flgui.cpp:4686 +msgid "Start streaming after launch" +msgstr "Comenzar streaming después de iniciar" + +#: src/FLTK/flgui.cpp:4687 +msgid "Connect automatically to a server after launch" +msgstr "Conectar automáticamente al servidor al iniciar" + +#: src/FLTK/flgui.cpp:4691 +msgid "Force reconnecting" +msgstr "Forzar reconexión" + +#: src/FLTK/flgui.cpp:4692 +msgid "If enabled butt keeps reconnecting regardless of the error message" +msgstr "" +"Si está activado butt intenta reconectarse sin importar el mensaje de error" + +#: src/FLTK/flgui.cpp:4696 +msgid "Reconnect delay:" +msgstr "Tiempo de espera para reconexión:" + +#: src/FLTK/flgui.cpp:4707 +msgid "Update song name from URL" +msgstr "Actualizar nombre de canción desde URL" + +#: src/FLTK/flgui.cpp:4711 +msgid "URL to get song name from" +msgstr "URL para obteer el nombre de la canción" + +#: src/FLTK/flgui.cpp:4716 +msgid "Update interval" +msgstr "Intervalo de actualización" + +#: src/FLTK/flgui.cpp:4717 +msgid "Update interval in seconds" +msgstr "Intervalo de actualización en segundos" + +#: src/FLTK/flgui.cpp:4732 +msgid "Record" +msgstr "Grabar" + +#: src/FLTK/flgui.cpp:4734 +msgid "Record File Name:" +msgstr "archivo de grabación:" + +#: src/FLTK/flgui.cpp:4735 +msgid "Record file name" +msgstr "archivo de grabación" + +#: src/FLTK/flgui.cpp:4740 +msgid "Record Directory:" +msgstr "Directorio de grabación:" + +#: src/FLTK/flgui.cpp:4741 +msgid "Directory of recordings" +msgstr "Directorio para las grabaciones" + +#: src/FLTK/flgui.cpp:4747 +msgid "Select recording directory" +msgstr "Seleccionar el directorio de grabación" + +#: src/FLTK/flgui.cpp:4752 +msgid "Split file" +msgstr "Dividir archivo" + +#: src/FLTK/flgui.cpp:4755 +msgid "every" +msgstr "cada" + +#: src/FLTK/flgui.cpp:4758 +msgid "minutes" +msgstr "minutos" + +#: src/FLTK/flgui.cpp:4760 src/FLTK/flgui.cpp:4761 +msgid "Sync to full hour" +msgstr "Sincronizar a hora completa" + +#: src/FLTK/flgui.cpp:4765 +msgid "Split now" +msgstr "Dividir ahora" + +#: src/FLTK/flgui.cpp:4774 src/FLTK/flgui.cpp:4775 +msgid "Start recording when connected" +msgstr "Comenzar grabación al conectar" + +#: src/FLTK/flgui.cpp:4779 +msgid "Stop recording when disconnected" +msgstr "Detener grabación al desconectar" + +#: src/FLTK/flgui.cpp:4780 +msgid "Start recording when disconnected" +msgstr "Comenzar grabación al desconectar" + +#: src/FLTK/flgui.cpp:4784 src/FLTK/flgui.cpp:4785 +msgid "Start recording after launch" +msgstr "Comenzar grabación después de iniciar" + +#: src/FLTK/flgui.cpp:4790 +msgid "" +"Start recording if the audio level exceeds the \"Signal present\" level set " +"in the \"Audio\" tab" +msgstr "" +"Comenzar la grabación si el nivel de audio supera el valor asignado en " +"\"Señal presente\" en la pestaña \"Audio\"" + +#: src/FLTK/flgui.cpp:4803 +msgid "" +"Stop recording if the audio level falls below the \"Signal absent level set " +"in the \"Audio\" tab" +msgstr "" +"Detener la grabación si el nivel de audio baja del valor asignado en \"Señal " +"presente\" en la pestaña \"Audio\"" + +#: src/FLTK/flgui.cpp:4815 +msgid "Overwrite existing files" +msgstr "Sobreescribir archivos existentes" + +#: src/FLTK/flgui.cpp:4823 +msgid "DSP" +msgstr "DSP" + +#: src/FLTK/flgui.cpp:4825 src/FLTK/flgui.cpp:5076 src/FLTK/flgui.cpp:6478 +msgid "Reset" +msgstr "Restablecer" + +#: src/FLTK/flgui.cpp:4830 +msgid "Equalizer" +msgstr "Ecualizador" + +#: src/FLTK/flgui.cpp:4837 src/FLTK/flgui.cpp:5088 +msgid "Rec" +msgstr "Grab" + +#: src/FLTK/flgui.cpp:4842 +msgid "Equalizer Preset" +msgstr "Ecualizador predeterminado" + +#: src/FLTK/flgui.cpp:4854 src/FLTK/flgui.cpp:4876 src/FLTK/flgui.cpp:4898 +#: src/FLTK/flgui.cpp:4920 src/FLTK/flgui.cpp:4942 src/FLTK/flgui.cpp:4964 +#: src/FLTK/flgui.cpp:4986 src/FLTK/flgui.cpp:5008 src/FLTK/flgui.cpp:5030 +#: src/FLTK/flgui.cpp:5052 src/FLTK/flgui.cpp:5096 src/FLTK/flgui.cpp:5118 +#: src/FLTK/flgui.cpp:5186 +msgid "+0.0" +msgstr "+0.0" + +#: src/FLTK/flgui.cpp:4858 +msgid "32Hz" +msgstr "32Hz" + +#: src/FLTK/flgui.cpp:4880 +msgid "64Hz" +msgstr "64Hz" + +#: src/FLTK/flgui.cpp:4902 +msgid "125Hz" +msgstr "125Hz" + +#: src/FLTK/flgui.cpp:4924 +msgid "250Hz" +msgstr "250Hz" + +#: src/FLTK/flgui.cpp:4946 +msgid "500Hz" +msgstr "500Hz" + +#: src/FLTK/flgui.cpp:4968 +msgid "1kHz" +msgstr "1kHz" + +#: src/FLTK/flgui.cpp:4990 +msgid "2kHz" +msgstr "2kHz" + +#: src/FLTK/flgui.cpp:5012 +msgid "4kHz" +msgstr "4kHz" + +#: src/FLTK/flgui.cpp:5034 +msgid "8kHz" +msgstr "8kHz" + +#: src/FLTK/flgui.cpp:5056 +msgid "16kHz" +msgstr "16kHz" + +#: src/FLTK/flgui.cpp:5081 +msgid "Dynamic Range Compressor" +msgstr "Compresor dinámico de rango" + +#: src/FLTK/flgui.cpp:5092 +msgid "Aggressive Mode" +msgstr "Modo Agresivo" + +#: src/FLTK/flgui.cpp:5100 +msgid "Threshold" +msgstr "Umbral" + +#: src/FLTK/flgui.cpp:5122 +msgid "Ratio" +msgstr "relación" + +#: src/FLTK/flgui.cpp:5140 src/FLTK/flgui.cpp:5163 +msgid "+0.00" +msgstr "+0.00" + +#: src/FLTK/flgui.cpp:5144 +msgid "Attack" +msgstr "Ataque" + +#: src/FLTK/flgui.cpp:5167 +msgid "Release" +msgstr "Liberar" + +#: src/FLTK/flgui.cpp:5190 +msgid "MakeupGain" +msgstr "Ganancia" + +#: src/FLTK/flgui.cpp:5224 src/FLTK/flgui.cpp:5237 +msgid "MIDI" +msgstr "MIDI" + +#: src/FLTK/flgui.cpp:5226 +msgid "MIDI Device" +msgstr "Disposit. MIDI" + +#: src/FLTK/flgui.cpp:5227 +msgid "Select your MIDI device" +msgstr "Seleccione su dispositivo MIDI" + +#: src/FLTK/flgui.cpp:5232 +msgid "Rescan" +msgstr "Volver a buscar" + +#: src/FLTK/flgui.cpp:5233 +msgid "Rescan MIDI devices" +msgstr "Volver a buscar dispositivos MIDI" + +#: src/FLTK/flgui.cpp:5238 +msgid "MIDI signal indicator" +msgstr "Indicador de señal de MIDI" + +#: src/FLTK/flgui.cpp:5250 +msgid "MIDI Commands" +msgstr "Mandatos MIDI" + +#: src/FLTK/flgui.cpp:5255 +msgid "Enable" +msgstr "Activar" + +#: src/FLTK/flgui.cpp:5256 +msgid "Enable/Disable the selected MIDI command" +msgstr "Activar/Desactivar el mandato MIDI seleccionado" + +#: src/FLTK/flgui.cpp:5262 +msgid "Channel" +msgstr "Canal" + +#: src/FLTK/flgui.cpp:5263 +msgid "Select MIDI channel" +msgstr "Seleccionar canal MIDI" + +#: src/FLTK/flgui.cpp:5277 +msgid "CC" +msgstr "CC" + +#: src/FLTK/flgui.cpp:5278 +msgid "Select CC number" +msgstr "Seleccionar número de CC" + +#: src/FLTK/flgui.cpp:5283 src/FLTK/fl_callbacks.cpp:6425 +msgid "Learn" +msgstr "Aprender" + +#: src/FLTK/flgui.cpp:5284 +msgid "Activate to auto detect the channel and CC number" +msgstr "Activar para autodetectar el canal y número de CC" + +#: src/FLTK/flgui.cpp:5289 +msgid "CC Mode" +msgstr "Modo de CC" + +#: src/FLTK/flgui.cpp:5290 +msgid "Select CC mode" +msgstr "Seleccionar modo de CC" + +#: src/FLTK/flgui.cpp:5304 +msgid "Soft takeover" +msgstr "Toma de control suave" + +#: src/FLTK/flgui.cpp:5305 +msgid "Prevents jumps when controlling a slider in absolute mode" +msgstr "" +"Impide saltos al desplazar un control de deslizamiento en modo absoluto" + +#: src/FLTK/flgui.cpp:5313 +msgid "TLS" +msgstr "TLS" + +#: src/FLTK/flgui.cpp:5315 src/FLTK/flgui.cpp:5619 +msgid "SSL/TLS" +msgstr "SSL/TLS" + +#: src/FLTK/flgui.cpp:5318 +msgid "" +"If your server uses a certificate from\n" +"Let's Encrypt or another well known\n" +"CA, you can leave these fields blank." +msgstr "" +"Si su servidor usa un certificado de\n" +"Let's Encrypt u otra CA reconocida\n" +"puede dejar estos campos en blanco." + +#: src/FLTK/flgui.cpp:5322 +msgid "CA Certificate File:" +msgstr "Archivo de Certificado CA:" + +#: src/FLTK/flgui.cpp:5323 +msgid "Certificate file" +msgstr "Archivo de Certificado" + +#: src/FLTK/flgui.cpp:5329 +msgid "Select certificate file" +msgstr "Seleccionar archivo de certificado" + +#: src/FLTK/flgui.cpp:5334 +msgid "CA Certificate Directory:" +msgstr "Directorio de Certificado CA:" + +#: src/FLTK/flgui.cpp:5335 +msgid "Certificate directory" +msgstr "Directorio de certificado" + +#: src/FLTK/flgui.cpp:5341 +msgid "Select certificate directory" +msgstr "Seleccionar directorio de certificado" + +#: src/FLTK/flgui.cpp:5350 +msgid "GUI" +msgstr "GUI" + +#: src/FLTK/flgui.cpp:5352 +msgid "Language" +msgstr "Idioma" + +#: src/FLTK/flgui.cpp:5369 +msgid "Display Color" +msgstr "Color para mostrar" + +#: src/FLTK/flgui.cpp:5372 +msgid "Text" +msgstr "Texto" + +#: src/FLTK/flgui.cpp:5373 +msgid "Select text color" +msgstr "Seleccione color del texto" + +#: src/FLTK/flgui.cpp:5379 +msgid "Background" +msgstr "Color de fondo" + +#: src/FLTK/flgui.cpp:5380 +msgid "Select background color" +msgstr "Seleccione color de fondo" + +#: src/FLTK/flgui.cpp:5388 +msgid "VU meter" +msgstr "VU meter" + +#: src/FLTK/flgui.cpp:5391 +msgid "Gradient colors" +msgstr "Colores degradados" + +#: src/FLTK/flgui.cpp:5396 +msgid "Solid colors" +msgstr "Colores sólidos" + +#: src/FLTK/flgui.cpp:5401 +msgid "Always show tabs" +msgstr "Mostrar las pestañas siempre" + +#: src/FLTK/flgui.cpp:5406 +msgid "Select lower range color" +msgstr "Seleccione color del texto para rango bajo" + +#: src/FLTK/flgui.cpp:5413 +msgid "Select mid range color" +msgstr "Seleccione color del texto para rango medio" + +#: src/FLTK/flgui.cpp:5420 +msgid "Select high range color" +msgstr "Seleccione color del texto para rango alto" + +#: src/FLTK/flgui.cpp:5427 +msgid "Low range start value (dB)" +msgstr "Valor inicial de rango bajo (dB)" + +#: src/FLTK/flgui.cpp:5431 +msgid "Mid range start value (dB)" +msgstr "Valor inicial de rango medio (dB)" + +#: src/FLTK/flgui.cpp:5440 +msgid "High range start value (dB)" +msgstr "Valor inicial de rango alto (dB)" + +#: src/FLTK/flgui.cpp:5450 +msgid "Misc" +msgstr "Misc." + +#: src/FLTK/flgui.cpp:5453 +msgid "Attach settings window to main window" +msgstr "Anexar ventana configs. a ventana principal" + +#: src/FLTK/flgui.cpp:5454 +msgid "Attach this window to the butt window" +msgstr "Anexar esta ventana a la pantalla de butt" + +#: src/FLTK/flgui.cpp:5458 src/FLTK/flgui.cpp:5459 +msgid "Stay always on top" +msgstr "Siempre arriba" + +#: src/FLTK/flgui.cpp:5463 src/FLTK/flgui.cpp:5464 +msgid "Remember main window position" +msgstr "Recordar la posición de la ventana principal" + +#: src/FLTK/flgui.cpp:5468 src/FLTK/flgui.cpp:5469 +msgid "Hide log window after start up" +msgstr "Ocultar ventana de log después de iniciar" + +#: src/FLTK/flgui.cpp:5473 src/FLTK/flgui.cpp:5474 +msgid "Change display mode every 5 seconds" +msgstr "Cambiar modo visualización cada 5 segundos" + +#: src/FLTK/flgui.cpp:5478 +msgid "Start minimized" +msgstr "Iniciar minimizado" + +#: src/FLTK/flgui.cpp:5479 +msgid "Minimize butt at startup" +msgstr "Minimizar butt al iniciar" + +#: src/FLTK/flgui.cpp:5483 +msgid "Disable gain control" +msgstr "Desactivar control de ganancia" + +#: src/FLTK/flgui.cpp:5489 +msgid "Show listeners" +msgstr "Mostrar oyentes" + +#: src/FLTK/flgui.cpp:5490 +msgid "Show current listeners in the display (not always available)" +msgstr "" +"Mostrar el número actual de oyentes en la pantalla (no siempre es posible)" + +#: src/FLTK/flgui.cpp:5494 +msgid "Update rate:" +msgstr "Actualizaciones:" + +#: src/FLTK/flgui.cpp:5504 +msgid "Custom window title:" +msgstr "Título personalizado de ventana:" + +#: src/FLTK/flgui.cpp:5505 +msgid "Define a custom window title" +msgstr "Defina un título personalizado de ventana" + +#: src/FLTK/flgui.cpp:5515 +msgid "Donate" +msgstr "Donar" + +#: src/FLTK/flgui.cpp:5517 +msgid "Donation" +msgstr "Donación" + +#: src/FLTK/flgui.cpp:5520 +msgid "" +"Keeping this software up to date, adding\n" +"new features and answering support mails\n" +"takes a lot of time and effort. If you can\n" +"afford it, please consider supporting this\n" +"project.\n" +"\n" +"Thank you!" +msgstr "" +"Mantener este software actualizado, agregar\n" +"nuevas funcionalidades y responder correos\n" +"de consultas consume mucho tiempo y esfuerzo.\n" +"Si le es posible, por favor, considere apoyar este \n" +"proyecto.\n" +"\n" +"¡Gracias!" + +#: src/FLTK/flgui.cpp:5525 +msgid "&Donate via PayPal" +msgstr "&Donar via PayPal" + +#: src/FLTK/flgui.cpp:5529 +msgid "Become a &patron" +msgstr "Convertirse en &patrón" + +#: src/FLTK/flgui.cpp:5533 +msgid "&Apple Pay, Google Pay, CC and more" +msgstr "&Apple Pay, Google Pay, CC y más" + +#: src/FLTK/flgui.cpp:5537 +msgid "&Bitcoin && Co" +msgstr "&Bitcoin && Co" + +#: src/FLTK/flgui.cpp:5552 src/FLTK/flgui.cpp:5673 +msgid "Name:" +msgstr "Nombre:" + +#: src/FLTK/flgui.cpp:5556 +msgid "Address:" +msgstr "Dirección:" + +#: src/FLTK/flgui.cpp:5560 +msgid "Port:" +msgstr "Puerto:" + +#: src/FLTK/flgui.cpp:5564 +msgid "Password:" +msgstr "Contraseña:" + +#: src/FLTK/flgui.cpp:5569 +msgid "Icecast mountpoint:" +msgstr "Punto montaje Icecast:" + +#: src/FLTK/flgui.cpp:5573 +msgid "Icecast user:" +msgstr "Usuario de Icecast:" + +#: src/FLTK/flgui.cpp:5577 src/FLTK/fl_callbacks.cpp:1136 +#: src/FLTK/fl_callbacks.cpp:1215 src/FLTK/fl_callbacks.cpp:1623 +msgid "Show" +msgstr "Mostrar" + +#: src/FLTK/flgui.cpp:5578 +msgid "show/hide password" +msgstr "mostrar/ocultar contraseña" + +#: src/FLTK/flgui.cpp:5582 +msgid "Type" +msgstr "Tipo" + +#: src/FLTK/flgui.cpp:5585 +msgid "Shoutcast" +msgstr "Shoutcast" + +#: src/FLTK/flgui.cpp:5590 +msgid "Icecast" +msgstr "Icecast" + +#: src/FLTK/flgui.cpp:5595 +msgid "WebRTC" +msgstr "WebRTC" + +#: src/FLTK/flgui.cpp:5600 +msgid "Radio.co" +msgstr "Radio.co" + +#: src/FLTK/flgui.cpp:5607 src/FLTK/flgui.cpp:5709 +msgid "&Cancel" +msgstr "&Cancelar" + +#: src/FLTK/flgui.cpp:5611 src/FLTK/flgui.cpp:5713 +msgid "&ADD" +msgstr "&AGREGAR" + +#: src/FLTK/flgui.cpp:5622 +msgid "Use SSL/TLS" +msgstr "Usar SSL/TLS" + +#: src/FLTK/flgui.cpp:5625 +msgid "Revoke certificate trust" +msgstr "Revocar certif. confianza" + +#: src/FLTK/flgui.cpp:5631 +msgid "Radio.co Stations" +msgstr "Estaciones de Radio.co" + +#: src/FLTK/flgui.cpp:5634 +msgid "Get Stations" +msgstr "Obtener Estaciones" + +#: src/FLTK/flgui.cpp:5638 +msgid "Select all" +msgstr "Seleccionar todo" + +#: src/FLTK/flgui.cpp:5642 +msgid "Deselect all" +msgstr "No seleccionar ninguno" + +#: src/FLTK/flgui.cpp:5646 +msgid "Use legacy Icecast protocol" +msgstr "Use protocolo anticuado Icecast" + +#: src/FLTK/flgui.cpp:5647 +msgid "" +"Activate this if you want to use the older SOURCE protocol instead of the " +"newer PUT protocol" +msgstr "" +"Active esto si desea usar el antiguo protocolo SOURCE en lugar del nuevo " +"protocolo PUT" + +#: src/FLTK/flgui.cpp:5651 +msgid "ICE server (optional):" +msgstr "Servidor ICE (opcional):" + +#: src/FLTK/flgui.cpp:5654 +msgid "WebRTC (WHIP) URL:" +msgstr "URL WebRTC (WHIP):" + +#: src/FLTK/flgui.cpp:5657 +msgid "Bearer token (optional):" +msgstr "Token de portador (opcional):" + +#: src/FLTK/flgui.cpp:5660 +msgid "Custom listener URL (optional):" +msgstr "URL para los números de oyente (opcional):" + +#: src/FLTK/flgui.cpp:5664 +msgid "Custom listener mountpoint (optional):" +msgstr "Punto de montaje para números de oyente (opcional):" + +#: src/FLTK/flgui.cpp:5674 +msgid "The name of your new ICY-entrie" +msgstr "Nombre de su nuevo valor de ICY" + +#: src/FLTK/flgui.cpp:5678 +msgid "Description:" +msgstr "Descripción:" + +#: src/FLTK/flgui.cpp:5682 +msgid "Genre:" +msgstr "Género:" + +#: src/FLTK/flgui.cpp:5686 +msgid "URL:" +msgstr "URL:" + +#: src/FLTK/flgui.cpp:5690 +msgid "ICQ:" +msgstr "ICQ:" + +#: src/FLTK/flgui.cpp:5694 +msgid "IRC:" +msgstr "IRC:" + +#: src/FLTK/flgui.cpp:5698 +msgid "AIM:" +msgstr "AIM:" + +#: src/FLTK/flgui.cpp:5702 +msgid "Make server public" +msgstr "Hacer público el servidor" + +#: src/FLTK/flgui.cpp:5705 +msgid "Expand variables" +msgstr "Expandir variables" + +#: src/FLTK/flgui.cpp:5706 +msgid "Activate to expand date variables in name and description" +msgstr "Activar para expandir las variables de fecha en nombre y descripción" + +#: src/FLTK/flgui.cpp:5736 +msgid "Donate Cryptocurrency" +msgstr "Donar criptomoedas" + +#: src/FLTK/flgui.cpp:5747 +msgid "Bitcoin" +msgstr "Bitcoin" + +#: src/FLTK/flgui.cpp:5752 src/FLTK/flgui.cpp:5761 src/FLTK/flgui.cpp:5770 +msgid "Copy" +msgstr "Copiar" + +#: src/FLTK/flgui.cpp:5756 +msgid "Litecoin" +msgstr "Litecoin" + +#: src/FLTK/flgui.cpp:5765 +msgid "Monero" +msgstr "Monero" + +#: src/FLTK/flgui.cpp:5774 src/FLTK/flgui.cpp:6106 src/FLTK/flgui.cpp:6461 +#: src/FLTK/flgui.cpp:6669 +msgid "&Close" +msgstr "&Cerrar" + +#: src/FLTK/flgui.cpp:5780 +msgid "Streaming Codec Settings" +msgstr "Configuraciones del códec de Streaming" + +#: src/FLTK/flgui.cpp:5792 src/FLTK/flgui.cpp:6124 +msgid "MP3" +msgstr "MP3" + +#: src/FLTK/flgui.cpp:5793 src/FLTK/flgui.cpp:6125 +msgid "Encoding Quality" +msgstr "Calidad de codificación" + +#: src/FLTK/flgui.cpp:5806 src/FLTK/flgui.cpp:6138 +msgid "Stereo Mode" +msgstr "Modo Estéreo" + +#: src/FLTK/flgui.cpp:5819 src/FLTK/flgui.cpp:5949 src/FLTK/flgui.cpp:6015 +#: src/FLTK/flgui.cpp:6071 src/FLTK/flgui.cpp:6151 src/FLTK/flgui.cpp:6281 +#: src/FLTK/flgui.cpp:6334 src/FLTK/flgui.cpp:6403 +msgid "Bitrate Mode" +msgstr "Modo de tasa de Bits" + +#: src/FLTK/flgui.cpp:5832 src/FLTK/flgui.cpp:6164 +msgid "VBR" +msgstr "VBR" + +#: src/FLTK/flgui.cpp:5835 src/FLTK/flgui.cpp:5989 src/FLTK/flgui.cpp:6167 +#: src/FLTK/flgui.cpp:6347 +msgid "Quality" +msgstr "Calidad" + +#: src/FLTK/flgui.cpp:5848 src/FLTK/flgui.cpp:6180 +msgid "Min. Bitrate" +msgstr "Tasa bits mín." + +#: src/FLTK/flgui.cpp:5861 src/FLTK/flgui.cpp:6193 +msgid "Max. Bitrate" +msgstr "Tasa bits máx." + +#: src/FLTK/flgui.cpp:5874 src/FLTK/flgui.cpp:6206 +msgid "Force" +msgstr "Fuerza" + +#: src/FLTK/flgui.cpp:5875 src/FLTK/flgui.cpp:6207 +msgid "Strictly enforce mininum Bitrate (-F option of the lame encoder)" +msgstr "" +"Implementar estrictamente tasa de bits mínima (opción -F del codificador " +"lame)" + +#: src/FLTK/flgui.cpp:5881 src/FLTK/flgui.cpp:6227 +msgid "Lowpass (kHz)" +msgstr "Paso bajo (kHz)" + +#: src/FLTK/flgui.cpp:5884 src/FLTK/flgui.cpp:5909 src/FLTK/flgui.cpp:6230 +#: src/FLTK/flgui.cpp:6255 +msgid "Frequency" +msgstr "Frecuencia" + +#: src/FLTK/flgui.cpp:5890 src/FLTK/flgui.cpp:5915 src/FLTK/flgui.cpp:6236 +#: src/FLTK/flgui.cpp:6261 +msgid "Width" +msgstr "Ancho" + +#: src/FLTK/flgui.cpp:5906 src/FLTK/flgui.cpp:6252 +msgid "Highpass (kHz)" +msgstr "Paso alto" + +#: src/FLTK/flgui.cpp:5931 src/FLTK/flgui.cpp:6213 +msgid "Resampling" +msgstr "Remuestreo" + +#: src/FLTK/flgui.cpp:5932 src/FLTK/flgui.cpp:6214 +msgid "Resample to the selected sample rate" +msgstr "Remostrar a la tasa de muestreo seleccionada" + +#: src/FLTK/flgui.cpp:5947 src/FLTK/flgui.cpp:6279 +msgid "OGG" +msgstr "OGG" + +#: src/FLTK/flgui.cpp:5962 src/FLTK/flgui.cpp:6294 +msgid "VBR Quality" +msgstr "Calidad de VBR" + +#: src/FLTK/flgui.cpp:5975 src/FLTK/flgui.cpp:6307 +msgid "VBR min. Bitrate" +msgstr "Tasa bits mín. VBR" + +#: src/FLTK/flgui.cpp:5980 src/FLTK/flgui.cpp:6312 +msgid "VBR max. Bitrate" +msgstr "Tasa bits máx. VBR" + +#: src/FLTK/flgui.cpp:5987 src/FLTK/flgui.cpp:6319 +msgid "OPUS" +msgstr "OPUS" + +#: src/FLTK/flgui.cpp:6002 src/FLTK/flgui.cpp:6321 +msgid "Optimize for" +msgstr "Optimizar para" + +#: src/FLTK/flgui.cpp:6028 src/FLTK/flgui.cpp:6360 +msgid "Max. Bandwidth" +msgstr "Máximo ancho de banda" + +#: src/FLTK/flgui.cpp:6043 src/FLTK/flgui.cpp:6375 +msgid "AAC" +msgstr "AAC" + +#: src/FLTK/flgui.cpp:6045 src/FLTK/flgui.cpp:6377 +msgid "Profile" +msgstr "Perfil" + +#: src/FLTK/flgui.cpp:6058 src/FLTK/flgui.cpp:6390 +msgid "Afterburner" +msgstr "Afterburner" + +#: src/FLTK/flgui.cpp:6086 src/FLTK/flgui.cpp:6418 +msgid "FLAC" +msgstr "FLAC" + +#: src/FLTK/flgui.cpp:6088 src/FLTK/flgui.cpp:6420 src/FLTK/flgui.cpp:6438 +msgid "Bit depth" +msgstr "Profundidad de bits" + +#: src/FLTK/flgui.cpp:6090 src/FLTK/flgui.cpp:6422 src/FLTK/flgui.cpp:6440 +msgid "16 bit" +msgstr "16 bit" + +#: src/FLTK/flgui.cpp:6095 src/FLTK/flgui.cpp:6427 src/FLTK/flgui.cpp:6450 +msgid "24 bit" +msgstr "24 bit" + +#: src/FLTK/flgui.cpp:6112 +msgid "Recording Codec Settings" +msgstr "Configuraciones del códec de grabación" + +#: src/FLTK/flgui.cpp:6436 +msgid "WAV" +msgstr "WAV" + +#: src/FLTK/flgui.cpp:6445 +msgid "32 bit" +msgstr "32 bit" + +#: src/FLTK/flgui.cpp:6467 +msgid "butt audio mixer" +msgstr "Mezclador de audio de butt" + +#: src/FLTK/flgui.cpp:6483 +msgid "Audio Mixer" +msgstr "Mezclador de audio" + +#: src/FLTK/flgui.cpp:6486 src/FLTK/flgui.cpp:6516 src/FLTK/flgui.cpp:6546 +#: src/FLTK/flgui.cpp:6569 src/FLTK/flgui.cpp:6592 +msgid "+0.0 dB" +msgstr "+0.0 dB" + +#: src/FLTK/flgui.cpp:6491 src/FLTK/flgui.cpp:6634 +msgid "" +"Primary\n" +"Device" +msgstr "" +"Dispositivo\n" +"principal" + +#: src/FLTK/flgui.cpp:6509 src/FLTK/flgui.cpp:6510 src/FLTK/flgui.cpp:6539 +#: src/FLTK/flgui.cpp:6540 +msgid "Mute" +msgstr "Mudo" + +#: src/FLTK/flgui.cpp:6521 src/FLTK/flgui.cpp:6642 +msgid "" +"Secondary\n" +"Device" +msgstr "" +"Dispositivo\n" +"secundario" + +#: src/FLTK/flgui.cpp:6551 +msgid "" +"Streaming\n" +"Gain" +msgstr "" +"Ganancia\n" +"de streaming" + +#: src/FLTK/flgui.cpp:6574 +msgid "" +"Recording\n" +"Gain" +msgstr "" +"Ganancia\n" +"de grabación" + +#: src/FLTK/flgui.cpp:6597 +msgid "" +"Master\n" +"Gain" +msgstr "" +"Ganancia\n" +"maestra" + +#: src/FLTK/flgui.cpp:6615 +msgid "" +"\n" +"Cross Fader" +msgstr "" +"\n" +"Cross fader" + +#: src/FLTK/flgui.cpp:6638 +msgid "|" +msgstr "|" + +#: src/FLTK/flgui.cpp:6650 +msgid "Alert" +msgstr "Alerta" + +#: src/FLTK/flgui.cpp:6661 +msgid "&Open the manual" +msgstr "&Abrir el manual" + +#: src/FLTK/flgui.cpp:6665 +msgid "" +"Could not find aac library.\n" +"\n" +"Please follow the instructions in the manual\n" +"for adding aac support." +msgstr "" +"No pudo encontrar la biblioteca de aac.\n" +"Por favor, siga las instrucciones del manual para agregar el soporte a aac." + +#: src/FLTK/fl_timer_funcs.cpp:318 +#, c-format +msgid "" +"stream sent\n" +"%0.2lfMB" +msgstr "" +"transm. enviada\n" +"%0.2lfMB" + +#: src/FLTK/fl_timer_funcs.cpp:323 +#, c-format +msgid "" +"stream time\n" +"%s" +msgstr "" +"tiempo transm.\n" +"%s" + +# Will be shown in the main display and thus +# may only contain ascii-characters. When +# in doubt just keep "Listeners". Also the +# string length should not exceed 10 +# characters. +#: src/FLTK/fl_timer_funcs.cpp:330 +#, c-format +msgid "" +"On Air\n" +"Listeners %5d" +msgstr "" +"Al aire\n" +"Oyentes %5d" + +# Will be shown in the main display and thus +# may only contain ascii-characters. When +# in doubt just keep "Listeners>". Also the +# string length should not exceed 10 +# characters. +#: src/FLTK/fl_timer_funcs.cpp:333 +#, c-format +msgid "" +"On Air\n" +"Listeners>%5d" +msgstr "" +"Al aire\n" +"Oyentes>%5d" + +# Will be shown in the main display and thus +# may only contain ascii-characters. When +# in doubt just keep "On Air" +#: src/FLTK/fl_timer_funcs.cpp:337 +#, c-format +msgid "On Air" +msgstr "Al aire" + +#: src/FLTK/fl_timer_funcs.cpp:343 +#, c-format +msgid "" +"record time\n" +"%s" +msgstr "" +"tiempo grabac.\n" +"%s" + +#: src/FLTK/fl_timer_funcs.cpp:348 +#, c-format +msgid "" +"record size\n" +"%0.2lfMB" +msgstr "" +"tamaño grabac.\n" +"%0.2lfMB" + +#: src/FLTK/fl_timer_funcs.cpp:479 +#, c-format +msgid "" +"ERROR: Connection lost\n" +"reconnecting in %d seconds..." +msgstr "" +"ERROR: Conexión perdida\n" +"reconnexión en %d segundos..." + +#: src/FLTK/fl_timer_funcs.cpp:483 +msgid "" +"ERROR: Connection lost\n" +"reconnecting..." +msgstr "" +"ERROR: Conexión perdida\n" +"reconectando..." + +#: src/FLTK/fl_timer_funcs.cpp:608 +msgid "Listeners" +msgstr "Oyentes" + +#: src/FLTK/fl_timer_funcs.cpp:674 +msgid "" +"Could not find a file extension in current filename\n" +"Automatic file splitting is deactivated" +msgstr "" +"No se pudo encontrar una extensión en el nombre actual de archivo\n" +"Se desactivó la división automática de archivo" + +#: src/FLTK/fl_timer_funcs.cpp:704 +msgid "" +"Could not find a valid filename for next file\n" +"butt keeps recording to current file" +msgstr "" +"No se pudo encontrar un nombre válido para el próximo archivo\n" +"butt continuará grabando en el archivo actual" + +#: src/FLTK/fl_timer_funcs.cpp:717 src/FLTK/fl_callbacks.cpp:1033 +#, c-format +msgid "" +"Could not open:\n" +"%s" +msgstr "" +"No se pudo abrir:\n" +"%s" + +#: src/FLTK/fl_timer_funcs.cpp:721 src/port_audio.cpp:938 +msgid "Recording to:" +msgstr "Grabando en:" + +#: src/FLTK/fl_timer_funcs.cpp:964 +#, c-format +msgid "" +"Warning\n" +"Could not open: %s.\n" +"Will retry in 5 seconds" +msgstr "" +"Advertencia\n" +"No se pudo abrir %s.\n" +"Se volverá a intentar en 5 segundos" + +#: src/FLTK/fl_callbacks.cpp:145 +msgid "connecting" +msgstr "conectando" + +#: src/FLTK/fl_callbacks.cpp:187 +msgid "" +"Error: No server entry found.\n" +"Please add a server in the settings-window." +msgstr "" +"Error: No se encontró valor para el servidor.\n" +"Por favor, agregue un servidor en la ventana de configuración." + +#: src/FLTK/fl_callbacks.cpp:192 +msgid "" +"Error: ogg vorbis encoder doesn't support bitrates\n" +"lower than 48kbit" +msgstr "" +"Error: el codificador de ogg vorbis no soporta las tasas de bits\n" +"menores a 48kbit" + +#: src/FLTK/fl_callbacks.cpp:200 +#, c-format +msgid "Warning: %s is not supported by every Shoutcast version" +msgstr "Advertencia: %s no está soportado por todas las versiones de Shoutcast" + +#: src/FLTK/fl_callbacks.cpp:204 +msgid "Error: FLAC is not supported by ShoutCast" +msgstr "Error: ShoutCast no soporta FLAC" + +#: src/FLTK/fl_callbacks.cpp:211 +#, c-format +msgid "Error: Radio.co supports only mp3 and aac" +msgstr "Error: Radio.co soporta solo mp3 y aac" + +#: src/FLTK/fl_callbacks.cpp:219 +#, c-format +msgid "Error: WebRTC only supports opus" +msgstr "Error: WebRTC solo soporta opus" + +#: src/FLTK/fl_callbacks.cpp:226 +#, c-format +msgid "Connecting to %s via %s ..." +msgstr "Conectando a %s mediante %s ..." + +#: src/FLTK/fl_callbacks.cpp:229 +#, c-format +msgid "Connecting to %s:%u ..." +msgstr "Conectando a %s:%u ..." + +#: src/FLTK/fl_callbacks.cpp:232 +#, c-format +msgid "Connecting to %s:%u (%u) ..." +msgstr "Conectando a %s:%u (%u) ..." + +#: src/FLTK/fl_callbacks.cpp:328 +msgid "Connection established" +msgstr "Conexión establecida" + +#: src/FLTK/fl_callbacks.cpp:342 src/FLTK/fl_callbacks.cpp:4275 +#: src/FLTK/fl_callbacks.cpp:4281 +msgid "no" +msgstr "no" + +#: src/FLTK/fl_callbacks.cpp:342 src/FLTK/fl_callbacks.cpp:4275 +#: src/FLTK/fl_callbacks.cpp:4281 +msgid "yes" +msgstr "sí" + +#: src/FLTK/fl_callbacks.cpp:344 +#, c-format +msgid "Device 1:\t%s\n" +msgstr "Dispositivo 1:\t%s\n" + +#: src/FLTK/fl_callbacks.cpp:345 +#, c-format +msgid "Device 2:\t%s\n" +msgstr "Dispositivo 2:\t%s\n" + +#: src/FLTK/fl_callbacks.cpp:396 +#, c-format +msgid "Connected to: %s" +msgstr "Conectado a %s" + +#: src/FLTK/fl_callbacks.cpp:567 src/FLTK/fl_callbacks.cpp:1669 +msgid "The custom listener URL must start with http:// or https://" +msgstr "La URL debe empezar con http:// o https://" + +#: src/FLTK/fl_callbacks.cpp:574 src/FLTK/fl_callbacks.cpp:1676 +msgid "" +"No mountpoint specified\n" +"Setting mountpoint to \"stream\"" +msgstr "" +"No hay ningún punto de montaje definido\n" +"Definiendo punto de montaje como \"streaming\"" + +#: src/FLTK/fl_callbacks.cpp:578 src/FLTK/fl_callbacks.cpp:1680 +msgid "" +"No user specified\n" +"Setting user to \"source\"" +msgstr "" +"No se especificó un usuario\n" +"Definiendo usuario como \"source\"" + +#: src/FLTK/fl_callbacks.cpp:586 src/FLTK/fl_callbacks.cpp:1688 +msgid "" +"Unsupported listener URL.\n" +"The listener URL must end with status-json.xsl, 7.xsl, 7.html or contain " +"stats?sid" +msgstr "" +"URL de escucha no compatible.\n" +"La URL de escucha debe terminar en status-json.xsl, 7.xsl, 7.html o contener " +"stats?sid" + +#: src/FLTK/fl_callbacks.cpp:592 src/FLTK/fl_callbacks.cpp:1694 +#: src/FLTK/fl_callbacks.cpp:1857 src/FLTK/fl_callbacks.cpp:2545 +msgid "No name specified" +msgstr "No se especificó un nombre" + +#: src/FLTK/fl_callbacks.cpp:597 src/FLTK/fl_callbacks.cpp:1699 +msgid "" +"The number of characters of all your server names exeeds 1000\n" +"Please reduce the number of characters of each server name" +msgstr "" +"La cantidad de caracteres de todos sus nombres de servidor excede los 1000\n" +"Por favor, reduzca la cantidad de caracteres de cada nombre de servidor" + +#: src/FLTK/fl_callbacks.cpp:603 src/FLTK/fl_callbacks.cpp:1705 +msgid "Newline characters and [];/\\ are not allowed within the server name" +msgstr "" +"No se permiten los caracteres de salto de línea ni [];/\\ en el nombre de " +"servidor" + +#: src/FLTK/fl_callbacks.cpp:609 src/FLTK/fl_callbacks.cpp:1710 +msgid "No address specified" +msgstr "No se especificó una dirección" + +#: src/FLTK/fl_callbacks.cpp:613 src/FLTK/fl_callbacks.cpp:1714 +msgid "No password specified" +msgstr "No se especificó una contraseña" + +#: src/FLTK/fl_callbacks.cpp:617 src/FLTK/fl_callbacks.cpp:1718 +msgid "No port specified" +msgstr "No se especificó un puerto" + +#: src/FLTK/fl_callbacks.cpp:621 src/FLTK/fl_callbacks.cpp:1722 +msgid "" +"Invalid port number\n" +"The port number must be between 1 and 65535" +msgstr "" +"Número de puerto inválido\n" +"El número de puerto debe estar entre 1 y 65535" + +#: src/FLTK/fl_callbacks.cpp:628 src/FLTK/fl_callbacks.cpp:1729 +msgid "No WHIP URL specified" +msgstr "No se especificó URL WHIP" + +#: src/FLTK/fl_callbacks.cpp:637 src/FLTK/fl_callbacks.cpp:1740 +#: src/FLTK/fl_callbacks.cpp:2564 +msgid "Server name already exist!" +msgstr "¡Nombre de servidor ya existe!" + +#: src/FLTK/fl_callbacks.cpp:966 +msgid "stop recording?" +msgstr "¿detener grabación?" + +#: src/FLTK/fl_callbacks.cpp:966 src/FLTK/fl_funcs.cpp:1462 +msgid "No" +msgstr "No" + +#: src/FLTK/fl_callbacks.cpp:966 +msgid "Yes" +msgstr "Sí" + +#: src/FLTK/fl_callbacks.cpp:1005 +msgid "No recording filename specified" +msgstr "No se especificó un nombre de archivo de grabación" + +#: src/FLTK/fl_callbacks.cpp:1015 +#, c-format +msgid "%s already exists!" +msgstr "¡%s ya existe!" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "overwrite" +msgstr "sobrescribir" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "cancel" +msgstr "cancelar" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "append" +msgstr "anexar" + +#: src/FLTK/fl_callbacks.cpp:1021 +msgid "Recording canceled" +msgstr "Grabación cancelada" + +#: src/FLTK/fl_callbacks.cpp:1090 src/FLTK/fl_funcs.cpp:1308 +msgid "Hide log" +msgstr "Ocultar log" + +#: src/FLTK/fl_callbacks.cpp:1123 +msgid "Add Server" +msgstr "Agregar servidor" + +#: src/FLTK/fl_callbacks.cpp:1176 +msgid "Edit Server" +msgstr "Editar servidor" + +#: src/FLTK/fl_callbacks.cpp:1181 +msgid "Radio.co stations cannot be edited." +msgstr "Las estaciones de Radio.co no pueden editarse." + +#: src/FLTK/fl_callbacks.cpp:1267 +msgid "Add Server Infos" +msgstr "Agregar datos de Servidor" + +#: src/FLTK/fl_callbacks.cpp:1302 +msgid "Song update failed: WebRTC does not support song names" +msgstr "" +"Falló la actualización de canción: WebRTC no soporta el uso de nombres de " +"canciones" + +#: src/FLTK/fl_callbacks.cpp:1345 +#, c-format +msgid "" +"Updated songname to:\n" +"%s\n" +msgstr "" +"Se actualizó el nombre de canción a:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:1354 +msgid "Updating songname failed" +msgstr "Falló la actualización del nombre de canción" + +#: src/FLTK/fl_callbacks.cpp:1428 +#, c-format +msgid "Audio buffer has been set to %d ms" +msgstr "Se asignó el valor de buffer de audio en %d ms" + +#: src/FLTK/fl_callbacks.cpp:1592 +msgid "" +"butt will open Radio.co in a new browser window.\n" +"\n" +"Login to Radio.co and allow butt access to your account." +msgstr "" +"butt abrirá Radio.co en una nueva ventana del navegador.\n" +"\n" +"Inicie sesión en Radio.co y permita el acceso a su cuenta a butt." + +#: src/FLTK/fl_callbacks.cpp:1618 +msgid "Hide" +msgstr "Ocultar" + +#: src/FLTK/fl_callbacks.cpp:1638 +msgid "Could not revoke trust for certificate" +msgstr "No fue posible revocar el certificado de confianza" + +#: src/FLTK/fl_callbacks.cpp:1862 +msgid "" +"The number of characters of all your icy names exeeds 1000\n" +"Please reduce the count of characters of each icy name" +msgstr "" +"La cantidad de caracteres de todos sus nombres de icy supera los 1000\n" +"Por favor, reduzca la cantidad de caracteres de cada nombre icy" + +#: src/FLTK/fl_callbacks.cpp:1868 src/FLTK/fl_callbacks.cpp:2557 +msgid "Newline characters and [];/\\ are not allowed within the icy name" +msgstr "" +"No se permiten los caracteres de salto de línea ni [];/\\ en el nombre de icy" + +#: src/FLTK/fl_callbacks.cpp:1877 +msgid "Icy name already exist!" +msgstr "¡Nombre de icy ya existe!" + +#: src/FLTK/fl_callbacks.cpp:2002 src/FLTK/fl_callbacks.cpp:2015 +#: src/FLTK/fl_callbacks.cpp:2029 src/FLTK/fl_callbacks.cpp:2044 +#: src/FLTK/fl_callbacks.cpp:2233 src/FLTK/fl_callbacks.cpp:2246 +#: src/FLTK/fl_callbacks.cpp:2260 src/FLTK/fl_callbacks.cpp:2275 +#: src/FLTK/fl_callbacks.cpp:2290 +msgid "" +"Warning:\n" +"The stream Sample-/Bitrate combination is invalid" +msgstr "" +"Advertencia:\n" +"La combinación de tasa de bits y de muestreo de transmisión es inválida" + +#: src/FLTK/fl_callbacks.cpp:2008 src/FLTK/fl_callbacks.cpp:2021 +#: src/FLTK/fl_callbacks.cpp:2035 src/FLTK/fl_callbacks.cpp:2050 +msgid "The previous values have been set\n" +msgstr "Se asignaron los valores previos\n" + +#: src/FLTK/fl_callbacks.cpp:2056 +#, c-format +msgid "Stream bitrate set to: %dk" +msgstr "la tasa de bits de transmisión se asignó en: %dk" + +#: src/FLTK/fl_callbacks.cpp:2142 src/FLTK/fl_callbacks.cpp:2155 +#: src/FLTK/fl_callbacks.cpp:2169 src/FLTK/fl_callbacks.cpp:2184 +#: src/FLTK/fl_callbacks.cpp:2313 src/FLTK/fl_callbacks.cpp:2326 +#: src/FLTK/fl_callbacks.cpp:2340 src/FLTK/fl_callbacks.cpp:2355 +#: src/FLTK/fl_callbacks.cpp:2369 +msgid "" +"Warning:\n" +"The record Sample-/Bitrate combination is invalid" +msgstr "" +"Advertencia:\n" +"La combinación de tasa de bits y de muestreo de grabación es inválida" + +#: src/FLTK/fl_callbacks.cpp:2148 src/FLTK/fl_callbacks.cpp:2161 +#: src/FLTK/fl_callbacks.cpp:2175 src/FLTK/fl_callbacks.cpp:2190 +#: src/FLTK/fl_callbacks.cpp:2239 src/FLTK/fl_callbacks.cpp:2252 +#: src/FLTK/fl_callbacks.cpp:2266 src/FLTK/fl_callbacks.cpp:2281 +#: src/FLTK/fl_callbacks.cpp:2296 src/FLTK/fl_callbacks.cpp:2319 +#: src/FLTK/fl_callbacks.cpp:2332 src/FLTK/fl_callbacks.cpp:2346 +#: src/FLTK/fl_callbacks.cpp:2361 src/FLTK/fl_callbacks.cpp:2375 +msgid "The previous values have been set" +msgstr "Se asignaron los valores previos" + +#: src/FLTK/fl_callbacks.cpp:2196 +#, c-format +msgid "Record bitrate set to: %dk" +msgstr "la tasa de bits de grabación se asignó en: %dk" + +#: src/FLTK/fl_callbacks.cpp:2383 +#, c-format +msgid "Samplerate set to: %dHz" +msgstr "Se asignó la tasa de muestreo en: %dHz" + +#: src/FLTK/fl_callbacks.cpp:2449 +msgid "Channels set to: stereo" +msgstr "Se configuraron los canales en: estéreo" + +#: src/FLTK/fl_callbacks.cpp:2512 +msgid "Channels set to: mono" +msgstr "Se configuraron los canales en: mono" + +#: src/FLTK/fl_callbacks.cpp:2551 +msgid "" +"The number of characters of all your icy names exeeds 1000\n" +"Please reduce the number of characters of each icy name" +msgstr "" +"La cantidad de caracteres de todos sus nombres de icy supera los 1000\n" +"Por favor, reduzca la cantidad de caracteres de cada nombre icy" + +#: src/FLTK/fl_callbacks.cpp:2659 +msgid "Edit Server Infos" +msgstr "Editar datos de Servidor" + +#: src/FLTK/fl_callbacks.cpp:2696 src/FLTK/fl_callbacks.cpp:2749 +msgid "" +"Primary and secondary audio device are both ASIO devices.\n" +"You can not use two ASIO devices at the same time.\n" +"Please select a different device.\n" +msgstr "" +"Los dispositivos de audio principal y secundario son ambos ASIO.\n" +"No puede usar dos dispositivos ASIO a la vez.\n" +"Por favor, seleccione un dispositivo diferente.\n" + +#: src/FLTK/fl_callbacks.cpp:2717 src/FLTK/fl_callbacks.cpp:4155 +msgid "" +"butt could not open selected audio device.\n" +"Please try another device.\n" +msgstr "" +"butt no pudo abrir el dispositivo de audio seleccionado.\n" +"Por favor, intente con otro dispositivo.\n" + +#: src/FLTK/fl_callbacks.cpp:2732 +#, c-format +msgid "" +"Primary device:\n" +"%s\n" +msgstr "" +"Dispositivo principal:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:2769 +msgid "" +"butt could not open secondary audio device.\n" +"Please try another device.\n" +msgstr "" +"butt no pudo abrir el dispositivo secundario de audio.\n" +"Por favor, intente con otro dispositivo.\n" + +#: src/FLTK/fl_callbacks.cpp:2783 +#, c-format +msgid "" +"Secondary device:\n" +"%s\n" +msgstr "" +"Dispositivo secundario:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:2894 src/FLTK/fl_callbacks.cpp:3072 +msgid "" +"MP3 encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"El codificador de MP3 no soporta la combinación actual\n" +"de tasa de bits y de muestreo" + +#: src/FLTK/fl_callbacks.cpp:2915 +msgid "Stream codec set to mp3" +msgstr "El códec de transmisión se asigno a mp3" + +#: src/FLTK/fl_callbacks.cpp:2927 src/FLTK/fl_callbacks.cpp:3112 +msgid "" +"OGG Vorbis encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"El codificador de OGG Vorbis no soporta la combinación actual\n" +"de tasa de bits y de muestreo" + +#: src/FLTK/fl_callbacks.cpp:2948 +msgid "Stream codec set to ogg/vorbis" +msgstr "El códec de transmisión se asigno a ogg/vorbis" + +#: src/FLTK/fl_callbacks.cpp:2959 src/FLTK/fl_callbacks.cpp:3151 +msgid "" +"Opus encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"El codificador de Opus no soporta la combinación actual\n" +"de tasa de bits y de muestreo" + +#: src/FLTK/fl_callbacks.cpp:2979 +msgid "Stream codec set to opus" +msgstr "El códec de transmisión se asigno a opus" + +#: src/FLTK/fl_callbacks.cpp:3011 src/FLTK/fl_callbacks.cpp:3213 +msgid "" +"AAC encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"El codificador de AAC no soporta la combinación actual\n" +"de tasa de bits y de muestreo" + +#: src/FLTK/fl_callbacks.cpp:3032 +msgid "Stream codec set to aac" +msgstr "El códec de transmisión se asigno a aac" + +#: src/FLTK/fl_callbacks.cpp:3042 src/FLTK/fl_callbacks.cpp:3252 +msgid "ERROR: While initializing flac settings" +msgstr "ERROR: Al inicializar la configuración de flac" + +#: src/FLTK/fl_callbacks.cpp:3060 +msgid "Stream codec set to flac" +msgstr "El códec de transmisión se asigno a flac" + +#: src/FLTK/fl_callbacks.cpp:3101 +msgid "Record codec set to mp3" +msgstr "El códec de grabación se asigno a mp3" + +#: src/FLTK/fl_callbacks.cpp:3140 +msgid "Record codec set to ogg/vorbis" +msgstr "El códec de grabación se asigno a ogg/vorbis" + +#: src/FLTK/fl_callbacks.cpp:3179 +msgid "Record codec set to opus" +msgstr "El códec de grabación se asigno a opus" + +#: src/FLTK/fl_callbacks.cpp:3242 +msgid "Record codec set to aac" +msgstr "El códec de grabación se asigno a aac" + +#: src/FLTK/fl_callbacks.cpp:3278 +msgid "Record codec set to flac" +msgstr "El códec de grabación se asigno a flac" + +#: src/FLTK/fl_callbacks.cpp:3294 +msgid "Record codec set to wav" +msgstr "El códec de grabación se asigno a wav" + +#: src/FLTK/fl_callbacks.cpp:3329 +msgid "Select certificate file..." +msgstr "Seleccionar certificado..." + +#: src/FLTK/fl_callbacks.cpp:3334 src/FLTK/fl_callbacks.cpp:3355 +#: src/FLTK/fl_callbacks.cpp:3466 src/FLTK/fl_callbacks.cpp:3556 +#: src/FLTK/fl_callbacks.cpp:4109 src/FLTK/fl_callbacks.cpp:4133 +#: src/FLTK/fl_callbacks.cpp:4257 +#, c-format +msgid "ERROR: %s" +msgstr "ERROR: %s" + +#: src/FLTK/fl_callbacks.cpp:3347 +msgid "Select certificate directory..." +msgstr "Seleccione el directorio del certificado..." + +#: src/FLTK/fl_callbacks.cpp:3458 +msgid "Record to..." +msgstr "Grabar en..." + +#: src/FLTK/fl_callbacks.cpp:3483 +msgid "File splitting only works if recording is active." +msgstr "La división de archivos solo funciona si la grabación está activa." + +#: src/FLTK/fl_callbacks.cpp:3552 +msgid "Select Songfile" +msgstr "Seleccionar archivo de audio" + +#: src/FLTK/fl_callbacks.cpp:3657 +msgid "Gain control is disabled. Enable in Settings->GUI" +msgstr "El control de ganancia está desactivado. Actívelo en Config. -> GUI" + +#: src/FLTK/fl_callbacks.cpp:3718 +msgid "select background color" +msgstr "Seleccione el color de fondo" + +#: src/FLTK/fl_callbacks.cpp:3728 +msgid "select text color" +msgstr "Seleccione el color del texto" + +#: src/FLTK/fl_callbacks.cpp:3761 src/FLTK/fl_callbacks.cpp:3765 +#: src/FLTK/fl_callbacks.cpp:3774 src/FLTK/fl_callbacks.cpp:3778 +msgid "Value must be a number between -54 and 0" +msgstr "El valor debe ser un número entre -54 y 0" + +#: src/FLTK/fl_callbacks.cpp:3788 +msgid "Please restart butt to apply new language." +msgstr "Por favor, reinicie butt para aplicar el nuevo idioma." + +#: src/FLTK/fl_callbacks.cpp:3867 src/FLTK/fl_callbacks.cpp:3872 +#: src/FLTK/fl_callbacks.cpp:3882 src/FLTK/fl_callbacks.cpp:3887 +msgid "Value must be a number between -90.0 and 0" +msgstr "El valor debe ser un número entre -90.0 y 0" + +#: src/FLTK/fl_callbacks.cpp:4082 +msgid "Recording volume" +msgstr "Volumen de grabación" + +#: src/FLTK/fl_callbacks.cpp:4103 +msgid "Export to..." +msgstr "Exportar a..." + +#: src/FLTK/fl_callbacks.cpp:4146 +#, c-format +msgid "Could not import config %s" +msgstr "No pudo importar la configuración %s" + +#: src/FLTK/fl_callbacks.cpp:4160 +#, c-format +msgid "Config imported %s" +msgstr "Configuración %s importada" + +#: src/FLTK/fl_callbacks.cpp:4234 +msgid "" +"Could not get update information.\n" +"Reason: Network error" +msgstr "" +"No pudo obtener la información sobre la actualización.\n" +"Razón: Error de red" + +#: src/FLTK/fl_callbacks.cpp:4237 +msgid "" +"Could not get update information.\n" +"Reason: Unknown answer from server" +msgstr "" +"No se pudo obtener respuesta del servidor.\n" +"Razón: Respuesta desconocida del servidor" + +#: src/FLTK/fl_callbacks.cpp:4240 +msgid "You have the latest version!" +msgstr "¡Usted tiene la última versión!" + +#: src/FLTK/fl_callbacks.cpp:4243 +msgid "" +"Could not get update information.\n" +"Reason: Unknown" +msgstr "" +"No pudo obtener la información sobre la actualización.\n" +"Razón: Desconocida" + +#: src/FLTK/fl_callbacks.cpp:4251 +msgid "Select logfile..." +msgstr "Seleccionar archivo de log..." + +#: src/FLTK/fl_callbacks.cpp:4273 +msgid "" +"butt is currently streaming.\n" +"Do you really want to close butt now?" +msgstr "" +"butt está transmitiendo por streaming.\n" +"¿Está seguro de que desea cerrar butt ahora?" + +#: src/FLTK/fl_callbacks.cpp:4279 +msgid "" +"butt is currently recording.\n" +"Do you really want to close butt now?" +msgstr "" +"butt está grabando.\n" +"¿Está seguro de que desea cerrar butt ahora?" + +#: src/FLTK/fl_callbacks.cpp:4354 +msgid "The URL must start with either http:// or https://" +msgstr "La URL debe empezar con http:// o https://" + +#: src/FLTK/fl_callbacks.cpp:4366 +msgid "Value must be a number between 1 and 1000" +msgstr "El valor debe ser un número entre 1 y 1000" + +#: src/FLTK/fl_callbacks.cpp:5228 src/FLTK/fl_callbacks.cpp:5263 +#: src/FLTK/fl_callbacks.cpp:5298 src/FLTK/fl_callbacks.cpp:5333 +#: src/FLTK/fl_callbacks.cpp:5368 src/FLTK/fl_callbacks.cpp:5859 +#: src/FLTK/fl_callbacks.cpp:5894 src/FLTK/fl_callbacks.cpp:5929 +#: src/FLTK/fl_callbacks.cpp:5964 src/FLTK/fl_callbacks.cpp:5999 +msgid "The encoder could not be initialized with the provided parameters." +msgstr "" +"El codificador no se pudo inicializar con los parámetros suministrados." + +#: src/FLTK/fl_callbacks.cpp:5246 src/FLTK/fl_callbacks.cpp:5877 +msgid "The value must be between 0.001 kHz and 50 kHz" +msgstr "El valor debe estar entre 0.001 y 50 kHz" + +#: src/FLTK/fl_callbacks.cpp:5281 src/FLTK/fl_callbacks.cpp:5316 +#: src/FLTK/fl_callbacks.cpp:5351 src/FLTK/fl_callbacks.cpp:5912 +#: src/FLTK/fl_callbacks.cpp:5947 src/FLTK/fl_callbacks.cpp:5982 +msgid "The value must be between 0.001 kHz and 16 kHz" +msgstr "El valor debe estar entre 0.001 y 16 kHz" + +#: src/FLTK/fl_callbacks.cpp:6328 +msgid "MIDI device could not be opened." +msgstr "No se pudo abrir el Dispositivo MIDI." + +#: src/FLTK/fl_callbacks.cpp:6334 +#, c-format +msgid "" +"MIDI device:\n" +"%s\n" +msgstr "" +"Dispositivo MIDI:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:6339 +msgid "MIDI device could not be started." +msgstr "No se pudo iniciar el dispositivo MIDI." + +#: src/FLTK/fl_callbacks.cpp:6344 +msgid "MIDI support disabled\n" +msgstr "Soporte de MIDI desactivado\n" + +#: src/FLTK/fl_callbacks.cpp:6406 +msgid "The CC value must be between 0 and 127" +msgstr "El valor de CC debe estar entre 0 y 127" + +#: src/FLTK/fl_callbacks.cpp:6429 +msgid "Waiting..." +msgstr "Esperando..." + +#: src/FLTK/fl_funcs.cpp:193 +msgid "Disabled" +msgstr "Desactivado" + +#: src/FLTK/fl_funcs.cpp:335 +#, c-format +msgid "%d seconds" +msgstr "%d segundos" + +#: src/FLTK/fl_funcs.cpp:386 +msgid "Not supported on Windows" +msgstr "No soportado en Windows" + +#: src/FLTK/fl_funcs.cpp:808 +msgid "Start/Stop broadcasting" +msgstr "Iniciar/Detener transmisión" + +#: src/FLTK/fl_funcs.cpp:809 +msgid "Start/Stop recording" +msgstr "Iniciar/Detener grabación" + +#: src/FLTK/fl_funcs.cpp:811 +msgid "Streaming Gain" +msgstr "Ganancia de streaming" + +#: src/FLTK/fl_funcs.cpp:812 +msgid "Recording Gain" +msgstr "Ganancia de grabación" + +#: src/FLTK/fl_funcs.cpp:813 +msgid "Primary Device Gain" +msgstr "Ganacia de dispositivo principal" + +#: src/FLTK/fl_funcs.cpp:814 +msgid "Secondary Device Gain" +msgstr "Ganacia de dispositivo secundario" + +#: src/FLTK/fl_funcs.cpp:815 +msgid "Cross fader" +msgstr "Cross fader" + +#: src/FLTK/fl_funcs.cpp:816 +msgid "Mute/Unmute Primary Device" +msgstr "Silenciar/Activar dispositivo principal" + +#: src/FLTK/fl_funcs.cpp:817 +msgid "Mute/Unmute Secondary Device" +msgstr "Silenciar/Activar dispositivo secundario" + +#: src/FLTK/fl_funcs.cpp:818 +msgid "Start broadcasting" +msgstr "Iniciar transmisión" + +#: src/FLTK/fl_funcs.cpp:819 +msgid "Stop broadcasting" +msgstr "Detener transmisión" + +#: src/FLTK/fl_funcs.cpp:820 +msgid "Start recording" +msgstr "Iniciar grabación" + +#: src/FLTK/fl_funcs.cpp:821 +msgid "Stop recording" +msgstr "Detener grabación" + +#: src/FLTK/fl_funcs.cpp:870 +msgid "dev. not supported" +msgstr "Dispositivo no compatible" + +#: src/FLTK/fl_funcs.cpp:1087 +#, c-format +msgid "" +"Could not create recording folder:\n" +"%s\n" +"Please make sure the folder contains only valid format specifiers." +msgstr "" +"No pudo crear la carpeta de grabación:\n" +"%s\n" +"Por favor, asegúrese de que la carpeta contenga solo especificadores de " +"formato válidos." + +#: src/FLTK/fl_funcs.cpp:1102 +#, c-format +msgid "Could not create recording folder %s\n" +msgstr "No se pudo crear la carpeta de grabación %s\n" + +#: src/FLTK/fl_funcs.cpp:1111 +#, c-format +msgid "" +"Could not create recording file:\n" +"%s\n" +"Please make sure the filename contains only valid format specifiers." +msgstr "" +"No pudo crear el archivo de grabación:\n" +"%s\n" +"Por favor, asegúrese de que el nombre de archivo contenga solo " +"especificadores de formato válidos." + +#: src/FLTK/fl_funcs.cpp:1157 +msgid "Could not find a valid filename" +msgstr "No se pudo encontrar un nombre de archivo válido" + +#: src/FLTK/fl_funcs.cpp:1462 +msgid "TRUST" +msgstr "CONFIANZA" + +#: src/icecast.cpp:90 +msgid "" +"\n" +"connect: Could not create network socket" +msgstr "" +"\n" +"conectar: No pudo crear el socket de red" + +#: src/icecast.cpp:102 +msgid "" +"\n" +"connect: Error resolving server address" +msgstr "" +"\n" +"conectar: Error al resolver la dirección del servidor" + +#: src/icecast.cpp:142 +msgid "" +"\n" +"connect: SSL connection timed out. Trying again..." +msgstr "" +"\n" +"conectar: Se excedió el tiempo límite de espera por conexión SSL. Intentando " +"de nuevo..." + +#: src/icecast.cpp:149 +#, c-format +msgid "" +"SSL/TLS certificate verification failed\n" +"Reason: %s\n" +"\n" +"Do you still want to trust this certificate?\n" +"Trusting will be permanent and can be revoked\n" +"in the server settings." +msgstr "" +"Falló la verificación del certificado SSL/TLS\n" +"Razón: %s\n" +"\n" +"¿Desea seguir confiando en este certificado?\n" +"La confianza será permanente y también puede ser revocada\n" +"en las configuraciones del servidor." + +#: src/icecast.cpp:164 +#, c-format +msgid "" +"\n" +"connect: SSL connection failed\n" +"Reason: %s" +msgstr "" +"\n" +"conectar: Falló la conexión SSL\n" +"Motivo: %s" + +#: src/icecast.cpp:320 +msgid "" +"\n" +"connect: connection timed out. Trying again..." +msgstr "" +"\n" +"conectar: Se excedió el tiempo límite de espera para conectarse. Intentando " +"nuevamente..." + +#: src/icecast.cpp:373 +msgid "" +"\n" +"connect: server answered with 400!\n" +msgstr "" +"\n" +"conectar: ¡el servidor respondió con 400!\n" + +#: src/icecast.cpp:379 +msgid "" +"\n" +"connect: invalid user/password!\n" +msgstr "" +"\n" +"conectar: ¡Usuario/Contraseña inválidos!\n" + +#: src/icecast.cpp:402 +msgid "" +"\n" +"connect: server answered with 404!\n" +msgstr "" +"\n" +"conectar: ¡el servidor respondió con 404!\n" + +#: src/icecast.cpp:409 +#, c-format +msgid "" +"\n" +"connect: server answered with %d!\n" +msgstr "" +"\n" +"conectar: ¡el servidor respondió con %d!\n" + +#: src/icecast.cpp:434 +msgid "" +"\n" +"ERROR: Opus is not supported by your\n" +"Icecast server (>=1.4.0 required)!\n" +msgstr "" +"\n" +"ERROR: ¡Opus no está soportado por su\n" +"servidor Icecast (versión >=1.4.0 requerida)!\n" + +#: src/icecast.cpp:507 +msgid "" +"\n" +"update_song: could not create network socket" +msgstr "" +"\n" +"update_song: No fue posible crear el socket de red" + +#: src/icecast.cpp:511 +msgid "" +"\n" +"update_song: error resolving server address" +msgstr "" +"\n" +"update_song: error al resolver la dirección del servidor" + +#: src/lame_encode.cpp:74 +#, c-format +msgid "unable to init lame params %d" +msgstr "No fue posible iniciar los parámetros de lame %d" + +#: src/port_audio.cpp:131 +#, c-format +msgid "" +"PortAudio init failed:\n" +"%s\n" +msgstr "" +"Falló la inicialización de PortAudio:\n" +"%s\n" + +#: src/port_audio.cpp:180 +msgid "ERROR: no sound device with input channels found" +msgstr "" +"ERROR: No se encontró ningún dispositivo de audio con canales de entrada" + +#: src/port_audio.cpp:198 src/port_audio.cpp:289 src/port_audio.cpp:1331 +#: src/port_midi.cpp:177 +#, c-format +msgid "Error getting device Info (%d)" +msgstr "Error al obtener la información del dispositivo (%d)" + +#: src/port_audio.cpp:241 +#, c-format +msgid "" +"Samplerate not supported: %dHz\n" +"Using default samplerate: %dHz" +msgstr "" +"Tasa de muestreo no soportada: %dHz\n" +"Usando la tasa por defecto: %dHz" + +#: src/port_audio.cpp:258 src/port_audio.cpp:360 +#, c-format +msgid "PA: Format not supported: %s\n" +msgstr "PA: Formato no soportado: %s\n" + +#: src/port_audio.cpp:268 +#, c-format +msgid "error opening sound device: %s" +msgstr "error al abrir dispositivo de audio: %s" + +#: src/port_audio.cpp:326 +msgid "The selected secondary audio device can not be used" +msgstr "El dispositivo secundario de audio no se puede usar" + +#: src/port_audio.cpp:343 src/port_audio.cpp:1452 src/port_audio.cpp:1469 +msgid "ERROR: Could not initialize samplerate converter" +msgstr "ERROR: No se pudo inicializar el convertidor de tasa de muestreo" + +#: src/port_audio.cpp:354 +#, c-format +msgid "Samplerate of secondary device is resampled from %dHz to %dHz\n" +msgstr "Tasa de muestreo del dispositivo secundario se ajustó de %dHz a %dHz\n" + +#: src/port_audio.cpp:381 +#, c-format +msgid "error opening secondary sound device: %s" +msgstr "error al abrir dispositivo de audio secundario: %s" + +#: src/port_audio.cpp:921 +msgid "disconnected\n" +msgstr "desconectado\n" + +#: src/port_audio.cpp:949 +msgid "recording stopped" +msgstr "grabación detenida" + +#: src/port_midi.cpp:152 src/port_midi.cpp:211 src/port_midi.cpp:233 +#: src/port_midi.cpp:255 src/port_midi.cpp:282 src/port_midi.cpp:301 +#: src/port_midi.cpp:316 src/port_midi.cpp:341 src/port_midi.cpp:352 +msgid "Error: PortMidi was not initialized." +msgstr "Error: PortMidi no estaba inicializado." + +#: src/port_midi.cpp:262 +#, c-format +msgid "" +"Error: MIDI device %s could not be opened because no MIDI devices were found." +msgstr "" +"Error: Dispositivo MIDI %s no se pudo abrir porque no se encontraron " +"dispositivos MIDI." + +#: src/port_midi.cpp:269 +#, c-format +msgid "Error: MIDI device %s could not be found." +msgstr "Error: No se pudo encontrar el dispositivo MIDI %s" + +#: src/port_midi.cpp:286 +msgid "Error: MIDI thread already active." +msgstr "Error: hilo MIDI ya está activo." + +#: src/port_midi.cpp:291 +msgid "Error: Could not start MIDI thread." +msgstr "Error: No se pudo iniciar el hilo MIDI." + +#: src/shoutcast.cpp:80 +msgid "" +"\n" +"Connect: Could not create network socket" +msgstr "" +"\n" +"Conectar: No se pudo crear el socket de red" + +#: src/shoutcast.cpp:92 +msgid "" +"\n" +"Connect: Error resolving server address" +msgstr "" +"\n" +"Conectar: Error al resolver la dirección del servidor" + +#: src/shoutcast.cpp:172 +msgid "" +"\n" +"connect: connection timed out. Trying again...\n" +msgstr "" +"\n" +"conectar: Se excedió el tiempo límite de espera para conectarse. Intentando " +"nuevamente...\n" + +#: src/shoutcast.cpp:189 +msgid "" +"\n" +"Connect: Invalid password!\n" +msgstr "" +"\n" +"Conectar: ¡Contraseña inválida!\n" + +#: src/shoutcast.cpp:238 +msgid "" +"\n" +"Update song: Could not create network socket" +msgstr "" +"\n" +"Actualizar canción: No fue posible crear el socket de red" + +#: src/shoutcast.cpp:242 +msgid "" +"\n" +"Update song: Error resolving server address" +msgstr "" +"\n" +"Actualizar canción: Error resolviendo la dirección del servidor" + +#: src/tls.cpp:159 +msgid "check_host: could not read host name from cert" +msgstr "" +"check_host: no fue posible leer el nombre del host desde el certificado" + +#: src/tls.cpp:194 +msgid "check_cert: No peer certificate available" +msgstr "check_cert: No hay disponible ningún certificado de pares" + +#: src/tls.cpp:207 +msgid "check_cert: X509_check_host failed" +msgstr "check_cert: Falló el proceso X509_check_host" + +#: src/tls.cpp:213 +msgid "check_cert: check_host failed" +msgstr "check_cert: falló el proceso check_host" + +#: src/tls.cpp:229 +msgid "calc_cert_hash: No peer certificate available" +msgstr "calc_cert_hash: No hay disponible ningún certificado de pares" + +#: src/tls.cpp:236 +msgid "calc_cert_hash: Hash calculation failed" +msgstr "calc_cert_hash: Falló el cálculo de hash" + +#: src/tls.cpp:305 +msgid "tls_setup: Could not set cipher list" +msgstr "tls_setup: No pudo asignar una lista de cifrado" + +#: src/tls.cpp:318 +msgid "tls_setup: SSL_new failed" +msgstr "tls_setup: Falló el proceso SSL_new" + +#: src/tls.cpp:324 +msgid "tls_setup: Could not bind socket to SSL" +msgstr "tls_setup: No fue posible asociar el socket a SSL" + +#: src/tls.cpp:338 +msgid "tls_setup: SSL_connect read timeout" +msgstr "" +"tls_setup: Se excedió el tiempo límite de espera para lectura de SSL_connect" + +#: src/tls.cpp:344 +msgid "tls_setup: SSL_connect write timeout" +msgstr "" +"tls_setup: Se excedió el tiempo límite de espera para escritura de " +"SSL_connect" + +#: src/tls.cpp:361 +msgid "tls_setup: Cert hash could not be calculated" +msgstr "tls_setup: El hash del certificado no pudo ser calculado" + +#: src/tls.cpp:385 +msgid "tls_send: read timeout" +msgstr "tls_send: Se excedió el tiempo límite de espera para lectura" + +#: src/tls.cpp:392 +msgid "tls_send: write timeout" +msgstr "tls_send: Se excedió el tiempo límite de espera para escritura" + +#: src/tls.cpp:418 +msgid "tls_recv: read timeout" +msgstr "tls_recv: Se excedió el tiempo límite de espera para lectura" + +#: src/tls.cpp:425 +msgid "tls_recv: write timeout" +msgstr "tls_recv: Se excedió el tiempo límite de espera para escritura" + +#~ msgid "Listeners: 99999" +#~ msgstr "Oyentes: 99999" + +#~ msgid "Resample output" +#~ msgstr "Calidad de remuestreo" + +#~ msgid "Resample output to selected sample rate" +#~ msgstr "Seleccione la tasa de muestreo de entrada" + +#, c-format +#~ msgid "" +#~ "error while parsing config. Missing WebRTC WHIP URL entry for server " +#~ "\"%s\".\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "Error al analizar la configuración. Falta el tipo para el servidor " +#~ "\"%s\".\n" +#~ "butt iniciará con la configuración por defecto" + +#~ msgid "Preset " +#~ msgstr "Predeterminado " + +#~ msgid "Text color" +#~ msgstr "Color del texto" + +#~ msgid "Volume of Primary Device" +#~ msgstr "Volumen de dispositivo principal" + +#~ msgid "Volume of Secondary Device" +#~ msgstr "Volumen de dispositivo secundario" + +#~ msgid "" +#~ "error while parsing config. Illegal value (-1) for num_of_srv.\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "Error al analizar la configuración. Valor inválido (-1) para num_of_srv\n" +#~ "butt iniciará con la configuración por defecto" + +#~ msgid "" +#~ "error while parsing config. Illegal value (-1) for num_of_icy.\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "Error al analizar la configuración. Valor inválido (-1) para num_of_icy.\n" +#~ "butt iniciará con la configuración por defecto" + +#~ msgid "Dash address has been copied to clipboard." +#~ msgstr "Se copió la dirección de Dash al portapapeles." + +#~ msgid "Dash" +#~ msgstr "Dash" + +#~ msgid "recording to:" +#~ msgstr "grabando en:" + +#~ msgid "Convert Mono to Stereo" +#~ msgstr "Convertir Mono en Estéreo" + +#~ msgid "Copies a mono channel to both stereo channels" +#~ msgstr "Copia un canal mono a ambos canales estéreo" diff --git a/po/fr.gmo b/po/fr.gmo new file mode 100644 index 0000000..a015c9b Binary files /dev/null and b/po/fr.gmo differ diff --git a/po/fr.po b/po/fr.po new file mode 100644 index 0000000..4d04680 --- /dev/null +++ b/po/fr.po @@ -0,0 +1,3202 @@ +# French translations for butt-0.1.41 package. +# Copyright (C) 2020 Daniel Nöthen +# This file is distributed under the same license as the butt package. +# Daniel Nöthen , 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: butt 0.1.41\n" +"Report-Msgid-Bugs-To: butt@danielnoethen.de\n" +"POT-Creation-Date: 2025-04-19 14:55+0200\n" +"PO-Revision-Date: 2024-08-04 12:17+0200\n" +"Last-Translator: cacatoès \n" +"Language-Team: French\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.0.1\n" + +#: src/AskForMicPermission.m:20 +msgid "Microphone access" +msgstr "Accès au microphone" + +#: src/AskForMicPermission.m:21 +#, fuzzy +msgid "" +"butt needs access to your microphone.\n" +"\n" +"Please go to\n" +"System Preferences->Privacy & Security->Microphone\n" +"and activate the check mark next to the butt entry." +msgstr "" +"butt demande l'accès à votre microphone\n" +"Veuillez vous rendre dans\n" +"Préférences Système->Sécurité et Confidentialité->Confidentialité-" +">Microphone\n" +"et cocher la case relative à butt" + +#: src/butt.cpp:219 +msgid "No home-directory found" +msgstr "Aucun répertoire personnel trouvé" + +#: src/butt.cpp:230 +#, c-format +msgid "" +"The shift key was held down during startup.\n" +"Do you want to start butt with a new configuration file?\n" +"This will overwrite your existing configuration file at\n" +"%s" +msgstr "" +"La touche majuscule a été maintenue au démarrage.\n" +"Voulez-vous démarrer butt avec une nouvelle configuration ?\n" +"Cela écrasera la configuration existante sur\n" +"%s" + +#: src/butt.cpp:233 +msgid "Start with old" +msgstr "Démarrer avec ancienne" + +#: src/butt.cpp:233 +msgid "Start with new" +msgstr "Démarrer avec nouvelle" + +#: src/butt.cpp:236 src/butt.cpp:253 +#, c-format +msgid "" +"Could not create config %s\n" +"butt is going to close now" +msgstr "" +"Impossible de créer la configuration %s\n" +"butt va fermer maintenant" + +#: src/butt.cpp:242 +#, c-format +msgid "Reading config %s\n" +msgstr "Lecture de la configuration %s\n" + +#: src/butt.cpp:250 +#, c-format +msgid "Could not find config %s\n" +msgstr "La configuration %s n'a pas été trouvée\n" + +#: src/butt.cpp:257 +#, c-format +msgid "" +"butt created a default config at\n" +"%s\n" +msgstr "" +"Création d'une configuration par défaut dans\n" +"%s\n" + +#: src/butt.cpp:265 +msgid "" +"Could not find any audio device with input channels.\n" +"butt requires at least one audio device with input channels in order to " +"work.\n" +"This can either be a built-in audio device, an external audio device or a " +"virtual audio device.\n" +"\n" +"butt is going to close now." +msgstr "" +"Aucun périphérique audio disposant de canaux d'entrée trouvé.\n" +"butt nécessite au moins un périphérique audio disposant de canaux d'entrée " +"pour fonctionner correctement.\n" +"Cela peut être un périphérique audio intégré, une carte son externe ou un " +"périphérique virtuel.\n" +"\n" +"butt va fermer maintenant." + +#: src/butt.cpp:358 +#, c-format +msgid "Illegal argument: Threshold must be a non-negative number\n" +msgstr "Argument incorrect : le seuil doit être un nombre non négatif\n" + +#: src/butt.cpp:382 +#, c-format +msgid "%c threshold set to %0.1f\n" +msgstr "%c seuil défini sur %0.1f\n" + +#: src/butt.cpp:464 +#, c-format +msgid "Illegal argument: Port must be a number between 1023 and 65535\n" +msgstr "Argument incorrect : Le port doit être compris entre 1023 et 65535\n" + +#: src/butt.cpp:472 src/butt.cpp:482 src/butt.cpp:489 src/butt.cpp:496 +#: src/butt.cpp:503 src/butt.cpp:510 src/butt.cpp:521 src/butt.cpp:540 +#: src/butt.cpp:550 src/butt.cpp:597 +#, c-format +msgid "" +"Warning: You may only pass one control option. Option -%c has been ignored.\n" +msgstr "" +"Attention : Vous ne pouvez passer qu'une seule option de contrôle. L'option -" +"%c a été ignorée.\n" + +#: src/butt.cpp:559 +#, c-format +msgid "" +"\n" +"Options:\n" +"-h\tPrint this help text\n" +"-v\tPrint version information\n" +msgstr "" +"\n" +"Options :\n" +"-h\tImprimer ce texte d'aide\n" +"-v\tImprimer les informations de version\n" + +#: src/butt.cpp:563 +#, c-format +msgid "" +"\n" +"Options for operating mode:\n" +"-c\tPath to configuration file\n" +"-L\tPrint available audio devices\n" +"-A\tCommand server will be accessible from your network/internet (default: " +"localhost only)\n" +"-U\tCommand server will use UDP instead of TCP\n" +"-x\tDo not start a command server\n" +"-p\tPort where the command server shall listen to (default: 1256)\n" +msgstr "" +"\n" +"Options pour le mode opératoire :\n" +"-c\tChemin du fichier de configuration\n" +"-L\tPrint available audio devices\n" +"-A\tLe serveur de commande sera accessible sur votre réseau/internet (par " +"défaut : hôte local uniquement)\n" +"-U\tLe serveur de commande utilisera le protocole UDP au lieu du protocole " +"TCP.\n" +"-x\tNe pas démarrer le serveur de commande\n" +"-p\tPort d'écoute du serveur de commande (par défaut : 1256)\n" + +#: src/butt.cpp:572 +#, c-format +msgid "" +"\n" +"Options for control mode:\n" +"-s\tConnect to streaming server\n" +"-d\tDisconnect from streaming server\n" +"-r\tStart recording\n" +"-t\tStop recording\n" +"-n\tSplit recording\n" +"-q\tQuit butt\n" +"-u\tupdate song name\n" +"-S\tRequest status\n" +"-M\tSet streaming signal threshold (seconds)\n" +"-m\tSet streaming silence threshold (seconds)\n" +"-O\tSet recording signal threshold (seconds)\n" +"-o\tSet recording silence threshold (seconds)\n" +"-U\tConnect via UDP instead of TCP\n" +"-a\tAddress of the butt instance to be controlled (default: 127.0.0.1)\n" +"-p\tPort of the butt instance to be controlled (default: 1256)\n" +msgstr "" +"\n" +"Options pour le mode contrôle :\n" +"-s\tSe connecter au serveur de diffusion\n" +"-d\tSe déconnecter du serveur de diffusion\n" +"-r\tDémarrer l'enregistrement\n" +"-t\tArrêter l'enregistrement\n" +"-n\tScinder l'enregistrement\n" +"-q\tFermer butt\n" +"-u\tMettre à jour le titre du morceau\n" +"-S\tRécupérer le statut\n" +"-M\tDéfinir le seuil du signal de diffusion (secondes)\n" +"-m\tDéfinir le seuil de silence du streaming (secondes)\n" +"-O\tDéfinir le seuil du signal d'enregistrement (secondes)\n" +"-o\tDéfinir le seuil de silence d'enregistrement (secondes)\n" +"-U\tConnexion via UDP au lieu de TCP\n" +"-a\tAdresse de l'instance butt à contrôler (par défaut : 127.0.0.1)\n" +"-p\tPort de l'instance butt à contrôler (default : 1256)\n" + +#: src/butt.cpp:591 +#, c-format +msgid "" +"Illegal option -%c.\n" +"Type butt -h to get a list of supported options.\n" +msgstr "" +"Option incorrecte -%c.\n" +"Tapez butt -h pour afficher la liste des options disponibles.\n" + +#: src/butt.cpp:603 +#, c-format +msgid "Option -%c requires an argument\n" +msgstr "L'option -%c nécessite un argument\n" + +#: src/butt.cpp:607 +#, c-format +msgid "Command line parsing failed\n" +msgstr "L'interprétation de la ligne de commande a échoué\n" + +#: src/butt.cpp:630 +#, c-format +msgid "No butt instance running on %s at port %d\n" +msgstr "Aucune instance de butt active sur %s sur le port %d\n" + +#: src/butt.cpp:635 +#, c-format +msgid "Error while sending command\n" +msgstr "Erreur lors de l'envoi de l'instruction\n" + +#: src/butt.cpp:640 +#, c-format +msgid "Error: Did not receive response packet\n" +msgstr "Erreur : N'a pas reçu le paquet de réponse\n" + +#: src/butt.cpp:653 +#, c-format +msgid "Error: You may only request one status packet per second\n" +msgstr "" +"Erreur : Vous ne pouvez demander qu'un seul paquet d'état par seconde\n" + +#: src/butt.cpp:657 +#, c-format +msgid "Error: Did not receive status packet (UDP server not running?)\n" +msgstr "" +"Erreur : N'a pas reçu le paquet d'état (le serveur UDP n'est pas actif ?)\n" + +#: src/butt.cpp:661 +#, c-format +msgid "Network error while receiving status packet: %d\n" +msgstr "Erreur de réseau lors de la réception du paquet d'état : %d\n" + +#: src/butt.cpp:665 +#, c-format +msgid "Error: Client and server versions do not match\n" +msgstr "Erreur : Les versions du client et du serveur ne correspondent pas\n" + +#: src/butt.cpp:676 +#, c-format +msgid "" +"connected: %d\n" +"connecting: %d\n" +"recording: %d\n" +"signal present: %d\n" +"signal absent: %d\n" +msgstr "" +"connecté : %d\n" +"se connecte : %d\n" +"enregistre : %d\n" +"signal présent : %d\n" +"signal absent : %d\n" + +#: src/butt.cpp:681 +#, c-format +msgid "stream seconds: %lu\n" +msgstr "secondes de flux : %lu\n" + +#: src/butt.cpp:682 +#, c-format +msgid "stream kBytes: %lu\n" +msgstr "kBytes de flux : %lu\n" + +#: src/butt.cpp:683 +#, c-format +msgid "record seconds: %lu\n" +msgstr "enregistrer les secondes : %lu\n" + +#: src/butt.cpp:684 +#, c-format +msgid "record kBytes: %lu\n" +msgstr "kBytes de enregistrerment : %lu\n" + +#: src/butt.cpp:685 +#, c-format +msgid "volume left: %0.1f\n" +msgstr "Volume à gauche : %0.1f\n" + +#: src/butt.cpp:686 +#, c-format +msgid "volume right: %0.1f\n" +msgstr "Volume droit : %0.1f\n" + +#: src/butt.cpp:687 +#, c-format +msgid "song: %s\n" +msgstr "titre : %s\n" + +#: src/butt.cpp:688 +#, c-format +msgid "record path: %s\n" +msgstr "voie d'enregistrement : %s\n" + +#: src/butt.cpp:689 +#, c-format +msgid "listeners: %d\n" +msgstr "Auditeurs : %d\n" + +#: src/butt.cpp:703 +msgid "" +"The control key was held down during startup.\n" +"butt will start without opening an audio device.\n" +"Please select your preferred audio device in settings->audio" +msgstr "" +"La touche de contrôle a été maintenue enfoncée pendant le démarrage.\n" +"butt démarre sans ouvrir de périphérique audio.\n" +"Veuillez sélectionner votre périphérique audio préféré dans Paramètres->Audio" + +#: src/butt.cpp:712 +msgid "" +"PortAudio init failed\n" +"butt is going to close now" +msgstr "" +"L'initialisation de PortAudio a échoué\n" +"butt va fermer maintenant" + +#: src/butt.cpp:747 src/FLTK/fl_timer_funcs.cpp:476 +#: src/FLTK/fl_callbacks.cpp:123 src/FLTK/fl_callbacks.cpp:899 +#: src/FLTK/fl_callbacks.cpp:977 src/FLTK/fl_funcs.cpp:1047 +msgid "idle" +msgstr "inactif" + +#: src/butt.cpp:780 +#, c-format +msgid "" +"Starting %s\n" +"Written by Daniel Nöthen\n" +"iPhone/iPad client: https://izicast.de\n" +"Donate: paypal@danielnoethen.de\n" +msgstr "" +"Démarrage de %s\n" +"Écrit par Daniel Nöthen\n" +"Client iPhone/iPad : https://izicast.de\n" +"Donations : paypal@danielnoethen.de\n" + +#: src/butt.cpp:792 src/butt.cpp:793 src/cfg.cpp:577 src/port_audio.cpp:1314 +#: src/port_audio.cpp:1315 +msgid "Default PCM device (default)" +msgstr "Périphérique PCM par défaut (default)" + +#: src/butt.cpp:796 src/butt.cpp:797 src/cfg.cpp:578 +#: src/FLTK/fl_callbacks.cpp:2820 src/FLTK/fl_funcs.cpp:227 +msgid "None" +msgstr "" + +#: src/butt.cpp:800 +msgid "" +"Could not open audio device.\n" +"Please select your preferred audio device in settings->audio" +msgstr "" +"Impossible d'ouvrir le périphérique audio.\n" +"Veuillez sélectionner votre périphérique audio préféré dans Paramètres-" +">Audio." + +#: src/butt.cpp:803 +msgid "" +"butt could not open previously used audio device.\n" +"The system default audio device will be used.\n" +msgstr "" +"butt n'a pas pu ouvrir le périphérique audio précédemment utilisé.\n" +"Le périphérique audio par défaut du système sera utilisé.\n" + +#: src/butt.cpp:830 +#, c-format +msgid "Command server listening on port %d\n" +msgstr "Serveur de commande en écoute sur le port %d\n" + +#: src/butt.cpp:837 +#, c-format +msgid "Warning: could not start command server on port %d\n" +msgstr "" +"Attention : impossible démarrer le serveur de commande sur le port %d\n" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:4225 +#, c-format +msgid "" +"New version available: %s\n" +"You have version %s" +msgstr "" +"Nouvelle version disponible : %s\n" +"Vous disposez de la version %s" + +#: src/butt.cpp:853 +msgid "Don't ask again" +msgstr "Ne plus demander" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:1594 +#: src/FLTK/fl_callbacks.cpp:4225 +msgid "Cancel" +msgstr "Annuler" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:4225 +msgid "Get new version" +msgstr "Obtenir la nouvelle version" + +#: src/butt.cpp:874 +#, c-format +msgid "Could not initialize PortMidi: %s" +msgstr "" + +#: src/butt.cpp:902 +msgid "butt was built without WebRTC support" +msgstr "" + +#: src/cfg.cpp:55 +#, c-format +msgid "Could not write to file: %s" +msgstr "Impossible d'écrire dans le fichier : %s" + +#: src/cfg.cpp:550 +#, c-format +msgid "Config written to %s" +msgstr "Configuration écrite dans %s" + +#: src/cfg.cpp:674 +msgid "" +"error while parsing config. Missing main/server entry.\n" +"butt will start with default settings" +msgstr "" +"erreur de lecture de la configuration. L'entrée main/server est manquante.\n" +"butt va fermer maintenant" + +#: src/cfg.cpp:680 +msgid "" +"error while parsing config. Missing main/srv_ent entry.\n" +"butt will start with default settings" +msgstr "" +"erreur de lecture de la configuration. L'entrée main/srv_ent est manquante.\n" +"butt va fermer maintenant" + +#: src/cfg.cpp:699 +#, c-format +msgid "" +"error while parsing config. Missing type entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"erreur de lecture de la configuration. Le type du serveur \"%s\" est " +"manquant.\n" +"butt va fermer maintenant" + +#: src/cfg.cpp:707 +#, c-format +msgid "" +"error while parsing config. Missing address entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"erreur de lecture de la configuration. L'adresse du serveur \"%s\" est " +"manquante.\n" +"butt va fermer maintenant" + +#: src/cfg.cpp:716 +#, c-format +msgid "" +"error while parsing config. Missing port entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"erreur de lecture de la configuration. Le port du serveur \"%s\" est " +"manquant.\n" +"butt va fermer maintenant" + +#: src/cfg.cpp:725 +#, c-format +msgid "" +"error while parsing config. Missing password entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"erreur de lecture de la configuration. Le mot de passe du serveur \"%s\" est " +"manquant.\n" +"butt va fermer maintenant" + +#: src/cfg.cpp:734 +#, c-format +msgid "" +"error while parsing config. Missing mount entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"erreur de lecture de la configuration. Le point de montage du serveur \"%s\" " +"est manquant.\n" +"butt va fermer maintenant" + +#: src/cfg.cpp:790 +msgid "" +"error while parsing config. Missing main/icy entry.\n" +"butt will start with default settings" +msgstr "" +"erreur de lecture de la configuration. L'entrée main/num_of_icy est " +"manquante.\n" +"butt va fermer maintenant" + +#: src/cfg.cpp:795 +msgid "" +"error while parsing config. Missing main/icy_ent entry.\n" +"butt will start with default settings" +msgstr "" +"erreur de lecture de la configuration. L'entrée main/icy_ent est manquante.\n" +"butt va fermer maintenant" + +#: src/cfg.cpp:821 +#, c-format +msgid "" +"error while parsing config. Missing pub entry for icy \"%s\".\n" +"butt will start with default settings" +msgstr "" +"erreur de lecture de la configuration. L'entrée pub pour icy \"%s\" est " +"manquante.\n" +"butt va fermer maintenant" + +#: src/FLTK/flgui.cpp:3088 +msgid "Bitcoin address has been copied to clipboard." +msgstr "L'adresse Bitcoin a été copiée dans le presse papier." + +#: src/FLTK/flgui.cpp:3099 +msgid "Litecoin address has been copied to clipboard." +msgstr "L'adresse Litecoin a été copiée dans le presse papier." + +#: src/FLTK/flgui.cpp:3110 +msgid "Monero address has been copied to clipboard." +msgstr "L'adresse Monero a été copiée dans le presse papier." + +#: src/FLTK/flgui.cpp:4041 +msgid "press left mouse to toggle lcd info" +msgstr "Faire un clic gauche pour activer les informations du LCD" + +#: src/FLTK/flgui.cpp:4053 src/FLTK/fl_callbacks.cpp:4078 +msgid "Streaming volume" +msgstr "" + +#: src/FLTK/flgui.cpp:4057 +msgid "Mixer" +msgstr "" + +#: src/FLTK/flgui.cpp:4058 +msgid "show/hide mixer window" +msgstr "montrer/cacher Table de mixage" + +#: src/FLTK/flgui.cpp:4065 +msgid "@circle" +msgstr "@circle" + +#: src/FLTK/flgui.cpp:4066 +msgid "start/stop recording" +msgstr "démarrer/arrêter l'enregistrement" + +#: src/FLTK/flgui.cpp:4077 +msgid "@square" +msgstr "@square" + +#: src/FLTK/flgui.cpp:4078 +msgid "disconnect from server" +msgstr "déconnexion du serveur" + +#: src/FLTK/flgui.cpp:4089 +msgid "@>" +msgstr "@>" + +#: src/FLTK/flgui.cpp:4090 +msgid "connect to server" +msgstr "connexion au serveur" + +#: src/FLTK/flgui.cpp:4106 src/FLTK/flgui.cpp:4438 src/FLTK/flgui.cpp:4657 +#: src/FLTK/fl_callbacks.cpp:4077 +msgid "Streaming" +msgstr "Diffusion" + +#: src/FLTK/flgui.cpp:4110 src/FLTK/flgui.cpp:4469 src/FLTK/flgui.cpp:4771 +msgid "Recording" +msgstr "Enregistrement" + +#: src/FLTK/flgui.cpp:4140 +msgid "Settings" +msgstr "Paramètres" + +#: src/FLTK/flgui.cpp:4141 +msgid "show/hide config window" +msgstr "montrer/cacher la fenêtre de configuration" + +#: src/FLTK/flgui.cpp:4148 src/FLTK/fl_callbacks.cpp:1098 +msgid "Show log" +msgstr "Journal" + +#: src/FLTK/flgui.cpp:4149 +msgid "show/hide info window" +msgstr "montrer/cacher la fenêtre d'informations" + +#: src/FLTK/flgui.cpp:4156 +msgid "-24 dB" +msgstr "-24 dB" + +#: src/FLTK/flgui.cpp:4159 +msgid "Gain" +msgstr "Gain" + +#: src/FLTK/flgui.cpp:4160 src/FLTK/fl_callbacks.cpp:3663 +#: src/FLTK/fl_funcs.cpp:810 +msgid "Master Gain" +msgstr "" + +#: src/FLTK/flgui.cpp:4178 +msgid "+24 dB" +msgstr "+24 dB" + +#: src/FLTK/flgui.cpp:4185 +#, fuzzy +msgid "Listeners: 0" +msgstr "Auditeurs" + +#: src/FLTK/flgui.cpp:4200 +msgid "butt settings" +msgstr "Paramètres de butt" + +#: src/FLTK/flgui.cpp:4213 +msgid "Main" +msgstr "Principal" + +#: src/FLTK/flgui.cpp:4215 +msgid "Server Settings" +msgstr "Paramètres du serveur" + +#: src/FLTK/flgui.cpp:4218 +msgid "Server" +msgstr "Serveur" + +#: src/FLTK/flgui.cpp:4219 +msgid "Server to connect to" +msgstr "Serveur auquel se connecter" + +#: src/FLTK/flgui.cpp:4224 src/FLTK/flgui.cpp:4245 +msgid "ADD" +msgstr "Ajout." + +#: src/FLTK/flgui.cpp:4225 src/FLTK/flgui.cpp:5550 +msgid "Add server" +msgstr "Ajouter un serveur" + +#: src/FLTK/flgui.cpp:4229 src/FLTK/flgui.cpp:4250 +msgid "EDIT" +msgstr "Modif." + +#: src/FLTK/flgui.cpp:4230 +msgid "Edit selected server" +msgstr "Modifier le serveur sélectionné" + +#: src/FLTK/flgui.cpp:4234 src/FLTK/flgui.cpp:4255 +msgid "DEL" +msgstr "Suppr." + +#: src/FLTK/flgui.cpp:4235 +msgid "Delete selected server" +msgstr "Supprimer le serveur sélectionné" + +#: src/FLTK/flgui.cpp:4239 +msgid "Stream Infos" +msgstr "Informations du flux" + +#: src/FLTK/flgui.cpp:4240 +msgid "Stream info that shall be used" +msgstr "Informations du flux devant être utilisé" + +#: src/FLTK/flgui.cpp:4246 src/FLTK/flgui.cpp:5671 +msgid "Add stream info" +msgstr "Ajouter les informations du flux" + +#: src/FLTK/flgui.cpp:4251 +msgid "Edit stream info" +msgstr "Modifier les informations du flux" + +#: src/FLTK/flgui.cpp:4256 +msgid "Delete stream info" +msgstr "Supprimer les informations du flux" + +#: src/FLTK/flgui.cpp:4262 +msgid "Log File" +msgstr "Fichier du journal" + +#: src/FLTK/flgui.cpp:4266 +msgid "Log file path" +msgstr "Chemin vers le fichier du journal" + +#: src/FLTK/flgui.cpp:4271 +msgid "Select log file" +msgstr "Sélectionnez le fichier du journal" + +#: src/FLTK/flgui.cpp:4278 +msgid "Configuration" +msgstr "Configuration" + +#: src/FLTK/flgui.cpp:4281 src/FLTK/fl_callbacks.cpp:4128 +msgid "Import..." +msgstr "Importer…" + +#: src/FLTK/flgui.cpp:4282 +msgid "Import settings from config file" +msgstr "Importer les paramètres depuis le fichier de configuration" + +#: src/FLTK/flgui.cpp:4286 src/FLTK/flgui.cpp:5615 src/FLTK/flgui.cpp:5717 +msgid "&Save" +msgstr "&Sauvegarder" + +#: src/FLTK/flgui.cpp:4287 +msgid "Save settings" +msgstr "Sauvegarder les paramètres" + +#: src/FLTK/flgui.cpp:4291 +msgid "Export..." +msgstr "Exporter…" + +#: src/FLTK/flgui.cpp:4292 +msgid "export settings" +msgstr "Exporter les paramètres" + +#: src/FLTK/flgui.cpp:4298 +msgid "Butt Agent" +msgstr "Agent Butt" + +#: src/FLTK/flgui.cpp:4301 +msgid "Start agent at startup" +msgstr "Démarrer au démarrage du système" + +#: src/FLTK/flgui.cpp:4302 +msgid "Start the butt agent when butt starts" +msgstr "Démarrer l'agent au démarrage de butt" + +#: src/FLTK/flgui.cpp:4306 src/FLTK/flgui.cpp:4307 +msgid "Minimize butt to tray" +msgstr "Réduire butt dans le systray" + +#: src/FLTK/flgui.cpp:4311 +msgid "Start Agent" +msgstr "Démarrer" + +#: src/FLTK/flgui.cpp:4312 +msgid "Start the butt agent now" +msgstr "Démarrer l'agent maintenant" + +#: src/FLTK/flgui.cpp:4316 +msgid "Stop Agent" +msgstr "Fermer" + +#: src/FLTK/flgui.cpp:4317 +msgid "Stop the butt agent" +msgstr "Fermer l'agent butt" + +#: src/FLTK/flgui.cpp:4323 +msgid "Updates" +msgstr "Mises à jour" + +#: src/FLTK/flgui.cpp:4326 +msgid "Check at startup" +msgstr "Vérifier au démarrage" + +#: src/FLTK/flgui.cpp:4327 +msgid "Check for updates at start" +msgstr "Vérifier les mises à jour au démarrage" + +#: src/FLTK/flgui.cpp:4331 +msgid "Check now" +msgstr "Vérifier" + +#: src/FLTK/flgui.cpp:4332 +msgid "Check if a new version is available" +msgstr "Vérifier si une mise à jour est disponible" + +#: src/FLTK/flgui.cpp:4338 +msgid "Help" +msgstr "" + +#: src/FLTK/flgui.cpp:4341 +msgid "Manual" +msgstr "" + +#: src/FLTK/flgui.cpp:4345 +msgid " YouTube" +msgstr "" + +#: src/FLTK/flgui.cpp:4355 +msgid "Audio" +msgstr "Audio" + +#: src/FLTK/flgui.cpp:4357 +msgid "Main Audio Settings" +msgstr "Paramètres audio principaux" + +#: src/FLTK/flgui.cpp:4360 +msgid "Channel mode" +msgstr "Mode du canal" + +#: src/FLTK/flgui.cpp:4361 +msgid "Select input channel" +msgstr "Sélectionnez le canal d'entrée" + +#: src/FLTK/flgui.cpp:4374 +msgid "Samplerate" +msgstr "Taux échantillonnage" + +#: src/FLTK/flgui.cpp:4375 +msgid "Select input sample rate" +msgstr "Sélectionnez le taux d'échantillonnage de l'entrée" + +#: src/FLTK/flgui.cpp:4380 +msgid "Remember Device by" +msgstr "Se souvenir du périph. par" + +#: src/FLTK/flgui.cpp:4383 +msgid "ID" +msgstr "ID" + +#: src/FLTK/flgui.cpp:4388 +msgid "Name" +msgstr "Nom" + +#: src/FLTK/flgui.cpp:4395 +msgid "Update devices" +msgstr "" + +#: src/FLTK/flgui.cpp:4396 +msgid "Rescan audio devices" +msgstr "Détecter les périphériques audio" + +#: src/FLTK/flgui.cpp:4400 +msgid "Primary Audio Device" +msgstr "" + +#: src/FLTK/flgui.cpp:4401 +msgid "Select your primary sound card device" +msgstr "" + +#: src/FLTK/flgui.cpp:4406 src/FLTK/flgui.cpp:4424 +msgid "Left" +msgstr "Gauche" + +#: src/FLTK/flgui.cpp:4407 src/FLTK/flgui.cpp:4425 +msgid "Select left audio channel" +msgstr "" + +#: src/FLTK/flgui.cpp:4412 src/FLTK/flgui.cpp:4430 +msgid "Right" +msgstr "Droite" + +#: src/FLTK/flgui.cpp:4413 src/FLTK/flgui.cpp:4431 +msgid "Select right audio channel" +msgstr "" + +#: src/FLTK/flgui.cpp:4418 +msgid "Secondary Audio Device" +msgstr "" + +#: src/FLTK/flgui.cpp:4419 +msgid "Select your secondary sound card device" +msgstr "" + +#: src/FLTK/flgui.cpp:4441 src/FLTK/flgui.cpp:4472 +msgid "Codec" +msgstr "Codec" + +#: src/FLTK/flgui.cpp:4442 +msgid "Select streaming codec" +msgstr "Sélectionnez le codec du flux" + +#: src/FLTK/flgui.cpp:4455 src/FLTK/flgui.cpp:4486 +msgid "Bitrate" +msgstr "Bitrate" + +#: src/FLTK/flgui.cpp:4456 +msgid "Select streaming bitrate" +msgstr "Sélectionnez le bitrate du flux" + +#: src/FLTK/flgui.cpp:4473 +msgid "Select recording codec" +msgstr "Sélectionnez le codec d'enregistrement" + +#: src/FLTK/flgui.cpp:4487 +msgid "Select recording bitrate" +msgstr "Sélectionnez le bitrate d'enregistrement" + +#: src/FLTK/flgui.cpp:4499 +msgid "Advanced..." +msgstr "Avancé…" + +#: src/FLTK/flgui.cpp:4505 +msgid "Buffer (ms)" +msgstr "Tampon (ms)" + +#: src/FLTK/flgui.cpp:4514 +msgid "Resample Quality" +msgstr "Qualité du rééchantillonnage" + +#: src/FLTK/flgui.cpp:4529 +msgid "Signal detection levels" +msgstr "Détection des niveaux du signal" + +#: src/FLTK/flgui.cpp:4532 +msgid "Signal present" +msgstr "Signal présent" + +#: src/FLTK/flgui.cpp:4539 src/FLTK/flgui.cpp:4549 +msgid "dB" +msgstr "dB" + +#: src/FLTK/flgui.cpp:4542 +msgid "Signal absent" +msgstr "Signal absent" + +#: src/FLTK/flgui.cpp:4556 src/FLTK/flgui.cpp:4833 src/FLTK/flgui.cpp:5084 +msgid "Stream" +msgstr "Flux" + +#: src/FLTK/flgui.cpp:4558 +msgid "Update song name from file" +msgstr "Mettre à jour le titre du morceau depuis un fichier" + +#: src/FLTK/flgui.cpp:4562 +msgid "Filename that holds the current song name" +msgstr "Fichier contenant le titre du morceau actuel" + +#: src/FLTK/flgui.cpp:4568 +msgid "Select file that holds the current song name" +msgstr "Sélectionnez le fichier contenant le titre du morceau actuel" + +#: src/FLTK/flgui.cpp:4573 src/FLTK/flgui.cpp:4606 src/FLTK/flgui.cpp:4724 +msgid "Activate" +msgstr "Activer" + +#: src/FLTK/flgui.cpp:4574 src/FLTK/flgui.cpp:4579 +msgid "Activate auto update song name from file" +msgstr "Activer la mise à jour automatique du nom du morceau depuis un fichier" + +#: src/FLTK/flgui.cpp:4578 +msgid "Read last line instead of first" +msgstr "Dernière ligne plutôt que la première" + +#: src/FLTK/flgui.cpp:4585 +msgid "Update song name from application" +msgstr "Mettre à jour le titre du morceau depuis une application" + +#: src/FLTK/flgui.cpp:4589 +msgid "Changes the song through an running application" +msgstr "Change le morceau depuis une application en cours d'exécution" + +#: src/FLTK/flgui.cpp:4594 +msgid "Title - Artist" +msgstr "Titre - Artiste" + +#: src/FLTK/flgui.cpp:4599 +msgid "Artist - Title" +msgstr "Artiste - Titre" + +#: src/FLTK/flgui.cpp:4612 +msgid "Update song name manually" +msgstr "Mettre à jour le titre du morceau manuellement" + +#: src/FLTK/flgui.cpp:4616 +msgid "Current song name" +msgstr "Titre du morceau actuel" + +#: src/FLTK/flgui.cpp:4622 src/FLTK/fl_callbacks.cpp:1594 +msgid "OK" +msgstr "OK" + +#: src/FLTK/flgui.cpp:4623 +msgid "Send current song name to the server" +msgstr "Envoyer le titre du morceau actuel vers le serveur" + +#: src/FLTK/flgui.cpp:4631 +msgid "Update song name delay" +msgstr "Retard du titre de la chanson" + +#: src/FLTK/flgui.cpp:4635 +msgid "Introduces a delay until the song name is actually updated" +msgstr "Retarde la mise à jour de la chanson" + +#: src/FLTK/flgui.cpp:4642 +msgid "Extend song name" +msgstr "Étendre le nom du morceau" + +#: src/FLTK/flgui.cpp:4645 +msgid "Prefix:" +msgstr "Préfixe :" + +#: src/FLTK/flgui.cpp:4650 +msgid "Suffix:" +msgstr "Suffixe :" + +#: src/FLTK/flgui.cpp:4660 src/FLTK/flgui.cpp:4789 +msgid "Start if signal is present for" +msgstr "Démarrer si signal présent pdt." + +#: src/FLTK/flgui.cpp:4661 +msgid "" +"Start streaming if the audio level exceeds the \"Signal present\" level set " +"in the \"Audio\" tab" +msgstr "" + +#: src/FLTK/flgui.cpp:4670 src/FLTK/flgui.cpp:4683 src/FLTK/flgui.cpp:4702 +#: src/FLTK/flgui.cpp:4799 src/FLTK/flgui.cpp:4812 src/FLTK/flgui.cpp:5499 +msgid "seconds" +msgstr "secondes" + +#: src/FLTK/flgui.cpp:4673 src/FLTK/flgui.cpp:4802 +msgid "Stop if signal is absent for" +msgstr "Arrêter si signal absent pdt." + +#: src/FLTK/flgui.cpp:4674 +msgid "" +"Stop streaming if the audio level falls below the \"Signal absent level set " +"in the \"Audio\" tab" +msgstr "" + +#: src/FLTK/flgui.cpp:4686 +msgid "Start streaming after launch" +msgstr "Commencer la diffusion au démarrage" + +#: src/FLTK/flgui.cpp:4687 +msgid "Connect automatically to a server after launch" +msgstr "Se connecter automatiquement au serveur après le démarrage" + +#: src/FLTK/flgui.cpp:4691 +msgid "Force reconnecting" +msgstr "Forcer la reconnexion" + +#: src/FLTK/flgui.cpp:4692 +msgid "If enabled butt keeps reconnecting regardless of the error message" +msgstr "Si activé butt se reconnecte sans tenir compte du message d'erreur" + +#: src/FLTK/flgui.cpp:4696 +msgid "Reconnect delay:" +msgstr "" + +#: src/FLTK/flgui.cpp:4707 +#, fuzzy +msgid "Update song name from URL" +msgstr "Mettre à jour le titre du morceau depuis un fichier" + +#: src/FLTK/flgui.cpp:4711 +#, fuzzy +msgid "URL to get song name from" +msgstr "Mettre à jour le titre du morceau depuis un fichier" + +#: src/FLTK/flgui.cpp:4716 +#, fuzzy +msgid "Update interval" +msgstr "Mises à jour:" + +#: src/FLTK/flgui.cpp:4717 +msgid "Update interval in seconds" +msgstr "" + +#: src/FLTK/flgui.cpp:4732 +msgid "Record" +msgstr "Enregistr." + +#: src/FLTK/flgui.cpp:4734 +msgid "Record File Name:" +msgstr "Nom du fichier de l'enregistrement :" + +#: src/FLTK/flgui.cpp:4735 +msgid "Record file name" +msgstr "Nom du fichier de l'enregistrement" + +#: src/FLTK/flgui.cpp:4740 +msgid "Record Directory:" +msgstr "Répertoire de l'enregistrement :" + +#: src/FLTK/flgui.cpp:4741 +msgid "Directory of recordings" +msgstr "Répertoire des enregistrements" + +#: src/FLTK/flgui.cpp:4747 +msgid "Select recording directory" +msgstr "Sélectionnez le répertoire d'enregistrement" + +#: src/FLTK/flgui.cpp:4752 +msgid "Split file" +msgstr "Scinder le fichier" + +#: src/FLTK/flgui.cpp:4755 +msgid "every" +msgstr "chaque" + +#: src/FLTK/flgui.cpp:4758 +msgid "minutes" +msgstr "minutes" + +#: src/FLTK/flgui.cpp:4760 src/FLTK/flgui.cpp:4761 +msgid "Sync to full hour" +msgstr "Synchroniser aux heures pleines" + +#: src/FLTK/flgui.cpp:4765 +msgid "Split now" +msgstr "Scinder" + +#: src/FLTK/flgui.cpp:4774 src/FLTK/flgui.cpp:4775 +msgid "Start recording when connected" +msgstr "Démarrer l'enregistrement une fois connecté" + +#: src/FLTK/flgui.cpp:4779 +msgid "Stop recording when disconnected" +msgstr "Arrêter l'enregistrement à la déconnexion" + +#: src/FLTK/flgui.cpp:4780 +msgid "Start recording when disconnected" +msgstr "Démarrer l'enregistrement à la déconnexion" + +#: src/FLTK/flgui.cpp:4784 src/FLTK/flgui.cpp:4785 +msgid "Start recording after launch" +msgstr "Démarrer l'enregistrement au lancement" + +#: src/FLTK/flgui.cpp:4790 +msgid "" +"Start recording if the audio level exceeds the \"Signal present\" level set " +"in the \"Audio\" tab" +msgstr "" + +#: src/FLTK/flgui.cpp:4803 +msgid "" +"Stop recording if the audio level falls below the \"Signal absent level set " +"in the \"Audio\" tab" +msgstr "" + +#: src/FLTK/flgui.cpp:4815 +msgid "Overwrite existing files" +msgstr "" + +#: src/FLTK/flgui.cpp:4823 +msgid "DSP" +msgstr "DSP" + +#: src/FLTK/flgui.cpp:4825 src/FLTK/flgui.cpp:5076 src/FLTK/flgui.cpp:6478 +msgid "Reset" +msgstr "Réinit." + +#: src/FLTK/flgui.cpp:4830 +msgid "Equalizer" +msgstr "Égaliseur" + +#: src/FLTK/flgui.cpp:4837 src/FLTK/flgui.cpp:5088 +msgid "Rec" +msgstr "" + +#: src/FLTK/flgui.cpp:4842 +msgid "Equalizer Preset" +msgstr "Présélection de l'égaliseur" + +#: src/FLTK/flgui.cpp:4854 src/FLTK/flgui.cpp:4876 src/FLTK/flgui.cpp:4898 +#: src/FLTK/flgui.cpp:4920 src/FLTK/flgui.cpp:4942 src/FLTK/flgui.cpp:4964 +#: src/FLTK/flgui.cpp:4986 src/FLTK/flgui.cpp:5008 src/FLTK/flgui.cpp:5030 +#: src/FLTK/flgui.cpp:5052 src/FLTK/flgui.cpp:5096 src/FLTK/flgui.cpp:5118 +#: src/FLTK/flgui.cpp:5186 +msgid "+0.0" +msgstr "+0.0" + +#: src/FLTK/flgui.cpp:4858 +msgid "32Hz" +msgstr "32Hz" + +#: src/FLTK/flgui.cpp:4880 +msgid "64Hz" +msgstr "64Hz" + +#: src/FLTK/flgui.cpp:4902 +msgid "125Hz" +msgstr "125Hz" + +#: src/FLTK/flgui.cpp:4924 +msgid "250Hz" +msgstr "250Hz" + +#: src/FLTK/flgui.cpp:4946 +msgid "500Hz" +msgstr "500Hz" + +#: src/FLTK/flgui.cpp:4968 +msgid "1kHz" +msgstr "1kHz" + +#: src/FLTK/flgui.cpp:4990 +msgid "2kHz" +msgstr "2KHz" + +#: src/FLTK/flgui.cpp:5012 +msgid "4kHz" +msgstr "4kHz" + +#: src/FLTK/flgui.cpp:5034 +msgid "8kHz" +msgstr "8kHz" + +#: src/FLTK/flgui.cpp:5056 +msgid "16kHz" +msgstr "16kHz" + +#: src/FLTK/flgui.cpp:5081 +msgid "Dynamic Range Compressor" +msgstr "Compresseur" + +#: src/FLTK/flgui.cpp:5092 +msgid "Aggressive Mode" +msgstr "Mode agressif" + +#: src/FLTK/flgui.cpp:5100 +msgid "Threshold" +msgstr "Seuil" + +#: src/FLTK/flgui.cpp:5122 +msgid "Ratio" +msgstr "Ratio" + +#: src/FLTK/flgui.cpp:5140 src/FLTK/flgui.cpp:5163 +msgid "+0.00" +msgstr "+0.00" + +#: src/FLTK/flgui.cpp:5144 +msgid "Attack" +msgstr "Attaque" + +#: src/FLTK/flgui.cpp:5167 +msgid "Release" +msgstr "Relâche" + +#: src/FLTK/flgui.cpp:5190 +msgid "MakeupGain" +msgstr "MakeupGain" + +#: src/FLTK/flgui.cpp:5224 src/FLTK/flgui.cpp:5237 +msgid "MIDI" +msgstr "" + +#: src/FLTK/flgui.cpp:5226 +msgid "MIDI Device" +msgstr "" + +#: src/FLTK/flgui.cpp:5227 +msgid "Select your MIDI device" +msgstr "" + +#: src/FLTK/flgui.cpp:5232 +msgid "Rescan" +msgstr "" + +#: src/FLTK/flgui.cpp:5233 +msgid "Rescan MIDI devices" +msgstr "" + +#: src/FLTK/flgui.cpp:5238 +msgid "MIDI signal indicator" +msgstr "" + +#: src/FLTK/flgui.cpp:5250 +msgid "MIDI Commands" +msgstr "" + +#: src/FLTK/flgui.cpp:5255 +msgid "Enable" +msgstr "" + +#: src/FLTK/flgui.cpp:5256 +msgid "Enable/Disable the selected MIDI command" +msgstr "" + +#: src/FLTK/flgui.cpp:5262 +msgid "Channel" +msgstr "" + +#: src/FLTK/flgui.cpp:5263 +msgid "Select MIDI channel" +msgstr "" + +#: src/FLTK/flgui.cpp:5277 +msgid "CC" +msgstr "CC" + +#: src/FLTK/flgui.cpp:5278 +msgid "Select CC number" +msgstr "" + +#: src/FLTK/flgui.cpp:5283 src/FLTK/fl_callbacks.cpp:6425 +msgid "Learn" +msgstr "" + +#: src/FLTK/flgui.cpp:5284 +msgid "Activate to auto detect the channel and CC number" +msgstr "" + +#: src/FLTK/flgui.cpp:5289 +msgid "CC Mode" +msgstr "" + +#: src/FLTK/flgui.cpp:5290 +msgid "Select CC mode" +msgstr "" + +#: src/FLTK/flgui.cpp:5304 +msgid "Soft takeover" +msgstr "" + +#: src/FLTK/flgui.cpp:5305 +msgid "Prevents jumps when controlling a slider in absolute mode" +msgstr "" + +#: src/FLTK/flgui.cpp:5313 +msgid "TLS" +msgstr "TLS" + +#: src/FLTK/flgui.cpp:5315 src/FLTK/flgui.cpp:5619 +msgid "SSL/TLS" +msgstr "SSL/TLS" + +#: src/FLTK/flgui.cpp:5318 +msgid "" +"If your server uses a certificate from\n" +"Let's Encrypt or another well known\n" +"CA, you can leave these fields blank." +msgstr "" +"Si votre serveur utilise un certificat\n" +"Let's Encrypt ou d'une autre CA bien connue,\n" +"vous pouvez laisser ces champs vides." + +#: src/FLTK/flgui.cpp:5322 +msgid "CA Certificate File:" +msgstr "Fichier du Certificat d'Autorité (CA) :" + +#: src/FLTK/flgui.cpp:5323 +msgid "Certificate file" +msgstr "Fichier du certificat" + +#: src/FLTK/flgui.cpp:5329 +msgid "Select certificate file" +msgstr "Sélectionnez le fichier du certificat" + +#: src/FLTK/flgui.cpp:5334 +msgid "CA Certificate Directory:" +msgstr "Répertoire du Certificat d'Autorité :" + +#: src/FLTK/flgui.cpp:5335 +msgid "Certificate directory" +msgstr "Répertoire du certificat" + +#: src/FLTK/flgui.cpp:5341 +msgid "Select certificate directory" +msgstr "Sélectionnez le répertoire du certificat" + +#: src/FLTK/flgui.cpp:5350 +msgid "GUI" +msgstr "GUI" + +#: src/FLTK/flgui.cpp:5352 +msgid "Language" +msgstr "Langue" + +#: src/FLTK/flgui.cpp:5369 +msgid "Display Color" +msgstr "Couleurs d'affichage" + +#: src/FLTK/flgui.cpp:5372 +msgid "Text" +msgstr "" + +#: src/FLTK/flgui.cpp:5373 +msgid "Select text color" +msgstr "Sélectionnez la couleur du texte" + +#: src/FLTK/flgui.cpp:5379 +msgid "Background" +msgstr "" + +#: src/FLTK/flgui.cpp:5380 +msgid "Select background color" +msgstr "Sélectionnez la couleur du fond" + +#: src/FLTK/flgui.cpp:5388 +msgid "VU meter" +msgstr "VU mètre" + +#: src/FLTK/flgui.cpp:5391 +msgid "Gradient colors" +msgstr "Couleurs du dégradé" + +#: src/FLTK/flgui.cpp:5396 +msgid "Solid colors" +msgstr "Couleurs solides" + +#: src/FLTK/flgui.cpp:5401 +msgid "Always show tabs" +msgstr "" + +#: src/FLTK/flgui.cpp:5406 +msgid "Select lower range color" +msgstr "" + +#: src/FLTK/flgui.cpp:5413 +msgid "Select mid range color" +msgstr "" + +#: src/FLTK/flgui.cpp:5420 +msgid "Select high range color" +msgstr "" + +#: src/FLTK/flgui.cpp:5427 +msgid "Low range start value (dB)" +msgstr "" + +#: src/FLTK/flgui.cpp:5431 +msgid "Mid range start value (dB)" +msgstr "" + +#: src/FLTK/flgui.cpp:5440 +msgid "High range start value (dB)" +msgstr "" + +#: src/FLTK/flgui.cpp:5450 +msgid "Misc" +msgstr "Divers" + +#: src/FLTK/flgui.cpp:5453 +msgid "Attach settings window to main window" +msgstr "Lier la fenêtre de paramètres à la principale" + +#: src/FLTK/flgui.cpp:5454 +msgid "Attach this window to the butt window" +msgstr "Lier cette fenêtre à la fenêtre butt" + +#: src/FLTK/flgui.cpp:5458 src/FLTK/flgui.cpp:5459 +msgid "Stay always on top" +msgstr "Rester toujours au dessus" + +#: src/FLTK/flgui.cpp:5463 src/FLTK/flgui.cpp:5464 +msgid "Remember main window position" +msgstr "Se souvenir de la position de la fenêtre principale" + +#: src/FLTK/flgui.cpp:5468 src/FLTK/flgui.cpp:5469 +msgid "Hide log window after start up" +msgstr "Masquer la fenêtre des journaux au démarrage" + +#: src/FLTK/flgui.cpp:5473 src/FLTK/flgui.cpp:5474 +msgid "Change display mode every 5 seconds" +msgstr "Changer le mode d'affichage toutes les 5 secs" + +#: src/FLTK/flgui.cpp:5478 +msgid "Start minimized" +msgstr "Démarrer réduit" + +#: src/FLTK/flgui.cpp:5479 +msgid "Minimize butt at startup" +msgstr "Réduire butt au démarrage" + +#: src/FLTK/flgui.cpp:5483 +msgid "Disable gain control" +msgstr "Désactiver le contrôle du gain" + +#: src/FLTK/flgui.cpp:5489 +msgid "Show listeners" +msgstr "Afficher le nombre d'auditeurs" + +#: src/FLTK/flgui.cpp:5490 +msgid "Show current listeners in the display (not always available)" +msgstr "" +"Afficher le nombre actuel d'auditeurs sur l'écran (pas toujours possible)" + +#: src/FLTK/flgui.cpp:5494 +msgid "Update rate:" +msgstr "Mises à jour:" + +#: src/FLTK/flgui.cpp:5504 +msgid "Custom window title:" +msgstr "" + +#: src/FLTK/flgui.cpp:5505 +msgid "Define a custom window title" +msgstr "" + +#: src/FLTK/flgui.cpp:5515 +msgid "Donate" +msgstr "Don" + +#: src/FLTK/flgui.cpp:5517 +msgid "Donation" +msgstr "Faire un don" + +#: src/FLTK/flgui.cpp:5520 +msgid "" +"Keeping this software up to date, adding\n" +"new features and answering support mails\n" +"takes a lot of time and effort. If you can\n" +"afford it, please consider supporting this\n" +"project.\n" +"\n" +"Thank you!" +msgstr "" +"Maintenir ce logiciel à jour, ajouter des nouvelles\n" +"fonctionnalités et répondre aux emails demande\n" +"beaucoup de temps et d'efforts. Si vous pouvez\n" +"vous le permettre, merci d'envisager de soutenir\n" +"ce projet.\n" +"\n" +"Merci !" + +#: src/FLTK/flgui.cpp:5525 +msgid "&Donate via PayPal" +msgstr "&Donner via PayPal" + +#: src/FLTK/flgui.cpp:5529 +msgid "Become a &patron" +msgstr "Devenir un &patron" + +#: src/FLTK/flgui.cpp:5533 +msgid "&Apple Pay, Google Pay, CC and more" +msgstr "&Apple Pay, Google Pay, CC et plus" + +#: src/FLTK/flgui.cpp:5537 +msgid "&Bitcoin && Co" +msgstr "&Bitcoin && Co" + +#: src/FLTK/flgui.cpp:5552 src/FLTK/flgui.cpp:5673 +msgid "Name:" +msgstr "Nom :" + +#: src/FLTK/flgui.cpp:5556 +msgid "Address:" +msgstr "Adresse :" + +#: src/FLTK/flgui.cpp:5560 +msgid "Port:" +msgstr "Port :" + +#: src/FLTK/flgui.cpp:5564 +msgid "Password:" +msgstr "Mot de passe :" + +#: src/FLTK/flgui.cpp:5569 +msgid "Icecast mountpoint:" +msgstr "Point de montage Icecast :" + +#: src/FLTK/flgui.cpp:5573 +msgid "Icecast user:" +msgstr "Utilisateur Icecast :" + +#: src/FLTK/flgui.cpp:5577 src/FLTK/fl_callbacks.cpp:1136 +#: src/FLTK/fl_callbacks.cpp:1215 src/FLTK/fl_callbacks.cpp:1623 +msgid "Show" +msgstr "Afficher" + +#: src/FLTK/flgui.cpp:5578 +msgid "show/hide password" +msgstr "afficher/masquer le mot de passe" + +#: src/FLTK/flgui.cpp:5582 +msgid "Type" +msgstr "Type" + +#: src/FLTK/flgui.cpp:5585 +msgid "Shoutcast" +msgstr "Shoutcast" + +#: src/FLTK/flgui.cpp:5590 +msgid "Icecast" +msgstr "Icecast" + +#: src/FLTK/flgui.cpp:5595 +msgid "WebRTC" +msgstr "" + +#: src/FLTK/flgui.cpp:5600 +msgid "Radio.co" +msgstr "Radio.co" + +#: src/FLTK/flgui.cpp:5607 src/FLTK/flgui.cpp:5709 +msgid "&Cancel" +msgstr "Annuler" + +#: src/FLTK/flgui.cpp:5611 src/FLTK/flgui.cpp:5713 +msgid "&ADD" +msgstr "&Ajouter" + +#: src/FLTK/flgui.cpp:5622 +msgid "Use SSL/TLS" +msgstr "Utiliser SSL/TLS" + +#: src/FLTK/flgui.cpp:5625 +msgid "Revoke certificate trust" +msgstr "Révoquer la confiance" + +#: src/FLTK/flgui.cpp:5631 +msgid "Radio.co Stations" +msgstr "Radio.co Stations" + +#: src/FLTK/flgui.cpp:5634 +msgid "Get Stations" +msgstr "Obtenir stations" + +#: src/FLTK/flgui.cpp:5638 +msgid "Select all" +msgstr "Tous" + +#: src/FLTK/flgui.cpp:5642 +msgid "Deselect all" +msgstr "Rien" + +#: src/FLTK/flgui.cpp:5646 +msgid "Use legacy Icecast protocol" +msgstr "" + +#: src/FLTK/flgui.cpp:5647 +msgid "" +"Activate this if you want to use the older SOURCE protocol instead of the " +"newer PUT protocol" +msgstr "" + +#: src/FLTK/flgui.cpp:5651 +msgid "ICE server (optional):" +msgstr "" + +#: src/FLTK/flgui.cpp:5654 +msgid "WebRTC (WHIP) URL:" +msgstr "" + +#: src/FLTK/flgui.cpp:5657 +msgid "Bearer token (optional):" +msgstr "" + +#: src/FLTK/flgui.cpp:5660 +msgid "Custom listener URL (optional):" +msgstr "" + +#: src/FLTK/flgui.cpp:5664 +msgid "Custom listener mountpoint (optional):" +msgstr "" + +#: src/FLTK/flgui.cpp:5674 +msgid "The name of your new ICY-entrie" +msgstr "Le nom de votre ICY-entrie" + +#: src/FLTK/flgui.cpp:5678 +msgid "Description:" +msgstr "Description :" + +#: src/FLTK/flgui.cpp:5682 +msgid "Genre:" +msgstr "Genre :" + +#: src/FLTK/flgui.cpp:5686 +msgid "URL:" +msgstr "URL :" + +#: src/FLTK/flgui.cpp:5690 +msgid "ICQ:" +msgstr "ICQ :" + +#: src/FLTK/flgui.cpp:5694 +msgid "IRC:" +msgstr "IRC :" + +#: src/FLTK/flgui.cpp:5698 +msgid "AIM:" +msgstr "AIM :" + +#: src/FLTK/flgui.cpp:5702 +msgid "Make server public" +msgstr "Rendre le serveur public" + +#: src/FLTK/flgui.cpp:5705 +msgid "Expand variables" +msgstr "" + +#: src/FLTK/flgui.cpp:5706 +msgid "Activate to expand date variables in name and description" +msgstr "" + +#: src/FLTK/flgui.cpp:5736 +msgid "Donate Cryptocurrency" +msgstr "Donner par crypto-monnaie" + +#: src/FLTK/flgui.cpp:5747 +msgid "Bitcoin" +msgstr "Bitcoin" + +#: src/FLTK/flgui.cpp:5752 src/FLTK/flgui.cpp:5761 src/FLTK/flgui.cpp:5770 +msgid "Copy" +msgstr "Copier" + +#: src/FLTK/flgui.cpp:5756 +msgid "Litecoin" +msgstr "Litecoin" + +#: src/FLTK/flgui.cpp:5765 +msgid "Monero" +msgstr "Monero" + +#: src/FLTK/flgui.cpp:5774 src/FLTK/flgui.cpp:6106 src/FLTK/flgui.cpp:6461 +#: src/FLTK/flgui.cpp:6669 +msgid "&Close" +msgstr "Fermer" + +#: src/FLTK/flgui.cpp:5780 +msgid "Streaming Codec Settings" +msgstr "Paramètres du codec de flux" + +#: src/FLTK/flgui.cpp:5792 src/FLTK/flgui.cpp:6124 +msgid "MP3" +msgstr "MP3" + +#: src/FLTK/flgui.cpp:5793 src/FLTK/flgui.cpp:6125 +msgid "Encoding Quality" +msgstr "Qualité d'encodage" + +#: src/FLTK/flgui.cpp:5806 src/FLTK/flgui.cpp:6138 +msgid "Stereo Mode" +msgstr "Mode stéréo" + +#: src/FLTK/flgui.cpp:5819 src/FLTK/flgui.cpp:5949 src/FLTK/flgui.cpp:6015 +#: src/FLTK/flgui.cpp:6071 src/FLTK/flgui.cpp:6151 src/FLTK/flgui.cpp:6281 +#: src/FLTK/flgui.cpp:6334 src/FLTK/flgui.cpp:6403 +msgid "Bitrate Mode" +msgstr "Mode débit binaire" + +#: src/FLTK/flgui.cpp:5832 src/FLTK/flgui.cpp:6164 +msgid "VBR" +msgstr "" + +#: src/FLTK/flgui.cpp:5835 src/FLTK/flgui.cpp:5989 src/FLTK/flgui.cpp:6167 +#: src/FLTK/flgui.cpp:6347 +msgid "Quality" +msgstr "Qualité" + +#: src/FLTK/flgui.cpp:5848 src/FLTK/flgui.cpp:6180 +msgid "Min. Bitrate" +msgstr "" + +#: src/FLTK/flgui.cpp:5861 src/FLTK/flgui.cpp:6193 +msgid "Max. Bitrate" +msgstr "" + +#: src/FLTK/flgui.cpp:5874 src/FLTK/flgui.cpp:6206 +msgid "Force" +msgstr "" + +#: src/FLTK/flgui.cpp:5875 src/FLTK/flgui.cpp:6207 +msgid "Strictly enforce mininum Bitrate (-F option of the lame encoder)" +msgstr "" + +#: src/FLTK/flgui.cpp:5881 src/FLTK/flgui.cpp:6227 +msgid "Lowpass (kHz)" +msgstr "" + +#: src/FLTK/flgui.cpp:5884 src/FLTK/flgui.cpp:5909 src/FLTK/flgui.cpp:6230 +#: src/FLTK/flgui.cpp:6255 +msgid "Frequency" +msgstr "" + +#: src/FLTK/flgui.cpp:5890 src/FLTK/flgui.cpp:5915 src/FLTK/flgui.cpp:6236 +#: src/FLTK/flgui.cpp:6261 +msgid "Width" +msgstr "" + +#: src/FLTK/flgui.cpp:5906 src/FLTK/flgui.cpp:6252 +msgid "Highpass (kHz)" +msgstr "" + +#: src/FLTK/flgui.cpp:5931 src/FLTK/flgui.cpp:6213 +msgid "Resampling" +msgstr "" + +#: src/FLTK/flgui.cpp:5932 src/FLTK/flgui.cpp:6214 +msgid "Resample to the selected sample rate" +msgstr "" + +#: src/FLTK/flgui.cpp:5947 src/FLTK/flgui.cpp:6279 +msgid "OGG" +msgstr "OGG" + +#: src/FLTK/flgui.cpp:5962 src/FLTK/flgui.cpp:6294 +msgid "VBR Quality" +msgstr "Qualité VBR" + +#: src/FLTK/flgui.cpp:5975 src/FLTK/flgui.cpp:6307 +msgid "VBR min. Bitrate" +msgstr "Qualité VBR min" + +#: src/FLTK/flgui.cpp:5980 src/FLTK/flgui.cpp:6312 +msgid "VBR max. Bitrate" +msgstr "Qualité VBR max" + +#: src/FLTK/flgui.cpp:5987 src/FLTK/flgui.cpp:6319 +msgid "OPUS" +msgstr "OPUS" + +#: src/FLTK/flgui.cpp:6002 src/FLTK/flgui.cpp:6321 +msgid "Optimize for" +msgstr "Optimiser pour" + +#: src/FLTK/flgui.cpp:6028 src/FLTK/flgui.cpp:6360 +msgid "Max. Bandwidth" +msgstr "Bande passante max" + +#: src/FLTK/flgui.cpp:6043 src/FLTK/flgui.cpp:6375 +msgid "AAC" +msgstr "AAC" + +#: src/FLTK/flgui.cpp:6045 src/FLTK/flgui.cpp:6377 +msgid "Profile" +msgstr "Profil" + +#: src/FLTK/flgui.cpp:6058 src/FLTK/flgui.cpp:6390 +msgid "Afterburner" +msgstr "Afterburner" + +#: src/FLTK/flgui.cpp:6086 src/FLTK/flgui.cpp:6418 +msgid "FLAC" +msgstr "FLAC" + +#: src/FLTK/flgui.cpp:6088 src/FLTK/flgui.cpp:6420 src/FLTK/flgui.cpp:6438 +msgid "Bit depth" +msgstr "Profondeur de bit" + +#: src/FLTK/flgui.cpp:6090 src/FLTK/flgui.cpp:6422 src/FLTK/flgui.cpp:6440 +msgid "16 bit" +msgstr "16 bit" + +#: src/FLTK/flgui.cpp:6095 src/FLTK/flgui.cpp:6427 src/FLTK/flgui.cpp:6450 +msgid "24 bit" +msgstr "24 bit" + +#: src/FLTK/flgui.cpp:6112 +msgid "Recording Codec Settings" +msgstr "Enregistrer les paramètres" + +#: src/FLTK/flgui.cpp:6436 +msgid "WAV" +msgstr "WAV" + +#: src/FLTK/flgui.cpp:6445 +msgid "32 bit" +msgstr "32 bit" + +#: src/FLTK/flgui.cpp:6467 +msgid "butt audio mixer" +msgstr "" + +#: src/FLTK/flgui.cpp:6483 +msgid "Audio Mixer" +msgstr "" + +#: src/FLTK/flgui.cpp:6486 src/FLTK/flgui.cpp:6516 src/FLTK/flgui.cpp:6546 +#: src/FLTK/flgui.cpp:6569 src/FLTK/flgui.cpp:6592 +msgid "+0.0 dB" +msgstr "+0.0 dB" + +#: src/FLTK/flgui.cpp:6491 src/FLTK/flgui.cpp:6634 +msgid "" +"Primary\n" +"Device" +msgstr "" + +#: src/FLTK/flgui.cpp:6509 src/FLTK/flgui.cpp:6510 src/FLTK/flgui.cpp:6539 +#: src/FLTK/flgui.cpp:6540 +msgid "Mute" +msgstr "" + +#: src/FLTK/flgui.cpp:6521 src/FLTK/flgui.cpp:6642 +msgid "" +"Secondary\n" +"Device" +msgstr "" + +#: src/FLTK/flgui.cpp:6551 +msgid "" +"Streaming\n" +"Gain" +msgstr "" + +#: src/FLTK/flgui.cpp:6574 +msgid "" +"Recording\n" +"Gain" +msgstr "" + +#: src/FLTK/flgui.cpp:6597 +msgid "" +"Master\n" +"Gain" +msgstr "" +"Master\n" +"Gain" + +#: src/FLTK/flgui.cpp:6615 +msgid "" +"\n" +"Cross Fader" +msgstr "" + +#: src/FLTK/flgui.cpp:6638 +msgid "|" +msgstr "" + +#: src/FLTK/flgui.cpp:6650 +msgid "Alert" +msgstr "" + +#: src/FLTK/flgui.cpp:6661 +msgid "&Open the manual" +msgstr "" + +#: src/FLTK/flgui.cpp:6665 +#, fuzzy +msgid "" +"Could not find aac library.\n" +"\n" +"Please follow the instructions in the manual\n" +"for adding aac support." +msgstr "" +"Impossible de trouver la bibliothèque AAC\n" +"Veuillez suivre les instructions du manuel pour ajouter la gestion de AAC." + +#: src/FLTK/fl_timer_funcs.cpp:318 +#, c-format +msgid "" +"stream sent\n" +"%0.2lfMB" +msgstr "" +"Flux emis\n" +"%0.2lfMB" + +#: src/FLTK/fl_timer_funcs.cpp:323 +#, c-format +msgid "" +"stream time\n" +"%s" +msgstr "" +"Duree du flux\n" +"%s" + +#: src/FLTK/fl_timer_funcs.cpp:330 +#, fuzzy, c-format +msgid "" +"On Air\n" +"Listeners %5d" +msgstr "Auditeurs : %d\n" + +#: src/FLTK/fl_timer_funcs.cpp:333 +#, fuzzy, c-format +msgid "" +"On Air\n" +"Listeners>%5d" +msgstr "Auditeurs" + +#: src/FLTK/fl_timer_funcs.cpp:337 +#, c-format +msgid "On Air" +msgstr "" + +#: src/FLTK/fl_timer_funcs.cpp:343 +#, c-format +msgid "" +"record time\n" +"%s" +msgstr "" +"record duree\n" +"%s" + +#: src/FLTK/fl_timer_funcs.cpp:348 +#, c-format +msgid "" +"record size\n" +"%0.2lfMB" +msgstr "" +"record taille\n" +"%0.2lfMB" + +#: src/FLTK/fl_timer_funcs.cpp:479 +#, c-format +msgid "" +"ERROR: Connection lost\n" +"reconnecting in %d seconds..." +msgstr "" +"ERREUR : Connexion perdue\n" +"reconnexion in %d secondes..." + +#: src/FLTK/fl_timer_funcs.cpp:483 +msgid "" +"ERROR: Connection lost\n" +"reconnecting..." +msgstr "" +"ERREUR : Connexion perdue\n" +"reconnexion…" + +#: src/FLTK/fl_timer_funcs.cpp:608 +msgid "Listeners" +msgstr "Auditeurs" + +#: src/FLTK/fl_timer_funcs.cpp:674 +msgid "" +"Could not find a file extension in current filename\n" +"Automatic file splitting is deactivated" +msgstr "" +"Aucune extension de fichier trouvée dans le nom actuel\n" +"Le découpage automatique du fichier est désactivé" + +#: src/FLTK/fl_timer_funcs.cpp:704 +msgid "" +"Could not find a valid filename for next file\n" +"butt keeps recording to current file" +msgstr "" +"Aucun nom de fichier valide trouvé pour le prochain fichier\n" +"butt continue d'enregistrer dans le fichier actuel" + +#: src/FLTK/fl_timer_funcs.cpp:717 src/FLTK/fl_callbacks.cpp:1033 +#, c-format +msgid "" +"Could not open:\n" +"%s" +msgstr "" +"N'a pas pu ouvrir :\n" +"%s" + +#: src/FLTK/fl_timer_funcs.cpp:721 src/port_audio.cpp:938 +msgid "Recording to:" +msgstr "Enregistrement vers :" + +#: src/FLTK/fl_timer_funcs.cpp:964 +#, c-format +msgid "" +"Warning\n" +"Could not open: %s.\n" +"Will retry in 5 seconds" +msgstr "" +"Attention\n" +"Impossible d'ouvrir : %s.\n" +"Nouvel essai dans 5 secondes" + +#: src/FLTK/fl_callbacks.cpp:145 +msgid "connecting" +msgstr "se connecte" + +#: src/FLTK/fl_callbacks.cpp:187 +msgid "" +"Error: No server entry found.\n" +"Please add a server in the settings-window." +msgstr "" +"Erreur : Pas d'entrée serveur trouvée.\n" +"Veuillez ajouter un serveur dans la fenêtre des paramètres." + +#: src/FLTK/fl_callbacks.cpp:192 +msgid "" +"Error: ogg vorbis encoder doesn't support bitrates\n" +"lower than 48kbit" +msgstr "" +"Erreur: l'encodeur ogg vorbis ne gère pas les bitrates\n" +"inférieurs à 48kbit" + +#: src/FLTK/fl_callbacks.cpp:200 +#, c-format +msgid "Warning: %s is not supported by every Shoutcast version" +msgstr "Attention : %s n'est pas géré par toutes les versions de Shoutcast" + +#: src/FLTK/fl_callbacks.cpp:204 +msgid "Error: FLAC is not supported by ShoutCast" +msgstr "Erreur : FLAC n'est pas géré par ShoutCast" + +#: src/FLTK/fl_callbacks.cpp:211 +#, c-format +msgid "Error: Radio.co supports only mp3 and aac" +msgstr "Erreur : Radio.co ne supporte que les mp3 et les aac" + +#: src/FLTK/fl_callbacks.cpp:219 +#, c-format +msgid "Error: WebRTC only supports opus" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:226 +#, c-format +msgid "Connecting to %s via %s ..." +msgstr "Connexion à %s via %s …" + +#: src/FLTK/fl_callbacks.cpp:229 +#, c-format +msgid "Connecting to %s:%u ..." +msgstr "Connexion à %s:%u…" + +#: src/FLTK/fl_callbacks.cpp:232 +#, c-format +msgid "Connecting to %s:%u (%u) ..." +msgstr "Connexion à %s:%u (%u)…" + +#: src/FLTK/fl_callbacks.cpp:328 +msgid "Connection established" +msgstr "Connexion établie" + +#: src/FLTK/fl_callbacks.cpp:342 src/FLTK/fl_callbacks.cpp:4275 +#: src/FLTK/fl_callbacks.cpp:4281 +msgid "no" +msgstr "non" + +#: src/FLTK/fl_callbacks.cpp:342 src/FLTK/fl_callbacks.cpp:4275 +#: src/FLTK/fl_callbacks.cpp:4281 +msgid "yes" +msgstr "oui" + +#: src/FLTK/fl_callbacks.cpp:344 +#, c-format +msgid "Device 1:\t%s\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:345 +#, c-format +msgid "Device 2:\t%s\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:396 +#, c-format +msgid "Connected to: %s" +msgstr "Connecté à : %s" + +#: src/FLTK/fl_callbacks.cpp:567 src/FLTK/fl_callbacks.cpp:1669 +msgid "The custom listener URL must start with http:// or https://" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:574 src/FLTK/fl_callbacks.cpp:1676 +msgid "" +"No mountpoint specified\n" +"Setting mountpoint to \"stream\"" +msgstr "" +"Aucun point de montage spécifié\n" +"Utilisation du point de montage \"stream\"" + +#: src/FLTK/fl_callbacks.cpp:578 src/FLTK/fl_callbacks.cpp:1680 +msgid "" +"No user specified\n" +"Setting user to \"source\"" +msgstr "" +"Aucun utilisateur spécifié\n" +"Utilisation de l'utilisateur \"source\"" + +#: src/FLTK/fl_callbacks.cpp:586 src/FLTK/fl_callbacks.cpp:1688 +msgid "" +"Unsupported listener URL.\n" +"The listener URL must end with status-json.xsl, 7.xsl, 7.html or contain " +"stats?sid" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:592 src/FLTK/fl_callbacks.cpp:1694 +#: src/FLTK/fl_callbacks.cpp:1857 src/FLTK/fl_callbacks.cpp:2545 +msgid "No name specified" +msgstr "Aucun nom spécifié" + +#: src/FLTK/fl_callbacks.cpp:597 src/FLTK/fl_callbacks.cpp:1699 +msgid "" +"The number of characters of all your server names exeeds 1000\n" +"Please reduce the number of characters of each server name" +msgstr "" +"Le nombre de caractères de l'ensemble des noms de votre serveur\n" +"excède 1000. Veuillez raccourcir le nom de chaque serveur" + +#: src/FLTK/fl_callbacks.cpp:603 src/FLTK/fl_callbacks.cpp:1705 +msgid "Newline characters and [];/\\ are not allowed within the server name" +msgstr "" +"Les caractères nouvelle ligne et [];/\\ ne sont pas autorisés dans le champ " +"nom" + +#: src/FLTK/fl_callbacks.cpp:609 src/FLTK/fl_callbacks.cpp:1710 +msgid "No address specified" +msgstr "Pas d'adresse spécifiée" + +#: src/FLTK/fl_callbacks.cpp:613 src/FLTK/fl_callbacks.cpp:1714 +msgid "No password specified" +msgstr "Pas de mot de passe spécifié" + +#: src/FLTK/fl_callbacks.cpp:617 src/FLTK/fl_callbacks.cpp:1718 +msgid "No port specified" +msgstr "Pas de port spécifié" + +#: src/FLTK/fl_callbacks.cpp:621 src/FLTK/fl_callbacks.cpp:1722 +msgid "" +"Invalid port number\n" +"The port number must be between 1 and 65535" +msgstr "" +"Numéro de port invalide\n" +"Le numéro de port doit être compris entre 1 et 65535" + +#: src/FLTK/fl_callbacks.cpp:628 src/FLTK/fl_callbacks.cpp:1729 +msgid "No WHIP URL specified" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:637 src/FLTK/fl_callbacks.cpp:1740 +#: src/FLTK/fl_callbacks.cpp:2564 +msgid "Server name already exist!" +msgstr "Le nom du serveur existe déjà !" + +#: src/FLTK/fl_callbacks.cpp:966 +msgid "stop recording?" +msgstr "arrêter l'enregistrement ?" + +#: src/FLTK/fl_callbacks.cpp:966 src/FLTK/fl_funcs.cpp:1462 +msgid "No" +msgstr "Non" + +#: src/FLTK/fl_callbacks.cpp:966 +msgid "Yes" +msgstr "Oui" + +#: src/FLTK/fl_callbacks.cpp:1005 +msgid "No recording filename specified" +msgstr "Pas de nom de fichier d'enregistrement spécifié" + +#: src/FLTK/fl_callbacks.cpp:1015 +#, c-format +msgid "%s already exists!" +msgstr "%s existe déjà !" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "overwrite" +msgstr "écraser" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "cancel" +msgstr "annuler" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "append" +msgstr "compléter" + +#: src/FLTK/fl_callbacks.cpp:1021 +#, fuzzy +msgid "Recording canceled" +msgstr "Enregistrement" + +#: src/FLTK/fl_callbacks.cpp:1090 src/FLTK/fl_funcs.cpp:1308 +msgid "Hide log" +msgstr "Journal" + +#: src/FLTK/fl_callbacks.cpp:1123 +msgid "Add Server" +msgstr "Ajouter un serveur" + +#: src/FLTK/fl_callbacks.cpp:1176 +msgid "Edit Server" +msgstr "Modifier un serveur" + +#: src/FLTK/fl_callbacks.cpp:1181 +msgid "Radio.co stations cannot be edited." +msgstr "Les stations de Radio.co ne peuvent pas être éditées." + +#: src/FLTK/fl_callbacks.cpp:1267 +msgid "Add Server Infos" +msgstr "Ajouter des informations du serveur" + +#: src/FLTK/fl_callbacks.cpp:1302 +msgid "Song update failed: WebRTC does not support song names" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:1345 +#, c-format +msgid "" +"Updated songname to:\n" +"%s\n" +msgstr "" +"Nom du morceau mis à jour pour :\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:1354 +msgid "Updating songname failed" +msgstr "Impossible de mettre à jour le nom du morceau" + +#: src/FLTK/fl_callbacks.cpp:1428 +#, c-format +msgid "Audio buffer has been set to %d ms" +msgstr "Le tampon audio a été réglé sur %d ms" + +#: src/FLTK/fl_callbacks.cpp:1592 +msgid "" +"butt will open Radio.co in a new browser window.\n" +"\n" +"Login to Radio.co and allow butt access to your account." +msgstr "" +"butt ouvrira Radio.co dans une nouvelle fenêtre du navigateur.\n" +"\n" +"Connectez-vous à Radio.co et autorisez butt à accéder à votre compte." + +#: src/FLTK/fl_callbacks.cpp:1618 +msgid "Hide" +msgstr "Masquer" + +#: src/FLTK/fl_callbacks.cpp:1638 +msgid "Could not revoke trust for certificate" +msgstr "Impossible de révoquer la confiance du certificat" + +#: src/FLTK/fl_callbacks.cpp:1862 +msgid "" +"The number of characters of all your icy names exeeds 1000\n" +"Please reduce the count of characters of each icy name" +msgstr "" +"Le nombre de caractères de tous les noms icy excède 1000\n" +"Veuillez réduire le nombre de caractères de chaque nom icy" + +#: src/FLTK/fl_callbacks.cpp:1868 src/FLTK/fl_callbacks.cpp:2557 +msgid "Newline characters and [];/\\ are not allowed within the icy name" +msgstr "" +"Les caractères nouvelle ligne et [];/\\ ne sont pas autorisés dans le champ " +"nom" + +#: src/FLTK/fl_callbacks.cpp:1877 +msgid "Icy name already exist!" +msgstr "Le nom icy existe déjà !" + +#: src/FLTK/fl_callbacks.cpp:2002 src/FLTK/fl_callbacks.cpp:2015 +#: src/FLTK/fl_callbacks.cpp:2029 src/FLTK/fl_callbacks.cpp:2044 +#: src/FLTK/fl_callbacks.cpp:2233 src/FLTK/fl_callbacks.cpp:2246 +#: src/FLTK/fl_callbacks.cpp:2260 src/FLTK/fl_callbacks.cpp:2275 +#: src/FLTK/fl_callbacks.cpp:2290 +msgid "" +"Warning:\n" +"The stream Sample-/Bitrate combination is invalid" +msgstr "" +"Attention :\n" +"La combinaison Sample-/Bitrate du flux est invalide" + +#: src/FLTK/fl_callbacks.cpp:2008 src/FLTK/fl_callbacks.cpp:2021 +#: src/FLTK/fl_callbacks.cpp:2035 src/FLTK/fl_callbacks.cpp:2050 +msgid "The previous values have been set\n" +msgstr "Les valeurs antérieures ont été restaurées\n" + +#: src/FLTK/fl_callbacks.cpp:2056 +#, c-format +msgid "Stream bitrate set to: %dk" +msgstr "Bitrate du flux réglé sur : %dk" + +#: src/FLTK/fl_callbacks.cpp:2142 src/FLTK/fl_callbacks.cpp:2155 +#: src/FLTK/fl_callbacks.cpp:2169 src/FLTK/fl_callbacks.cpp:2184 +#: src/FLTK/fl_callbacks.cpp:2313 src/FLTK/fl_callbacks.cpp:2326 +#: src/FLTK/fl_callbacks.cpp:2340 src/FLTK/fl_callbacks.cpp:2355 +#: src/FLTK/fl_callbacks.cpp:2369 +msgid "" +"Warning:\n" +"The record Sample-/Bitrate combination is invalid" +msgstr "" +"Attention :\n" +"La combinaison Sample-/Bitrate de l'enregistrement est invalide" + +#: src/FLTK/fl_callbacks.cpp:2148 src/FLTK/fl_callbacks.cpp:2161 +#: src/FLTK/fl_callbacks.cpp:2175 src/FLTK/fl_callbacks.cpp:2190 +#: src/FLTK/fl_callbacks.cpp:2239 src/FLTK/fl_callbacks.cpp:2252 +#: src/FLTK/fl_callbacks.cpp:2266 src/FLTK/fl_callbacks.cpp:2281 +#: src/FLTK/fl_callbacks.cpp:2296 src/FLTK/fl_callbacks.cpp:2319 +#: src/FLTK/fl_callbacks.cpp:2332 src/FLTK/fl_callbacks.cpp:2346 +#: src/FLTK/fl_callbacks.cpp:2361 src/FLTK/fl_callbacks.cpp:2375 +msgid "The previous values have been set" +msgstr "Les valeurs antérieures ont été restaurées" + +#: src/FLTK/fl_callbacks.cpp:2196 +#, c-format +msgid "Record bitrate set to: %dk" +msgstr "Bitrate de l'enregistrement réglé sur : %dk" + +#: src/FLTK/fl_callbacks.cpp:2383 +#, c-format +msgid "Samplerate set to: %dHz" +msgstr "Taux d'échantillonnage réglé sur : %dHz" + +#: src/FLTK/fl_callbacks.cpp:2449 +msgid "Channels set to: stereo" +msgstr "Canaux réglés sur : stéréo" + +#: src/FLTK/fl_callbacks.cpp:2512 +msgid "Channels set to: mono" +msgstr "Canaux réglés sur : mono" + +#: src/FLTK/fl_callbacks.cpp:2551 +msgid "" +"The number of characters of all your icy names exeeds 1000\n" +"Please reduce the number of characters of each icy name" +msgstr "" +"Le nombre de caractères des noms icy excède 1000\n" +"Veuillez réduire le nombre de caractères pour chaque nom icy" + +#: src/FLTK/fl_callbacks.cpp:2659 +msgid "Edit Server Infos" +msgstr "Modifier les informations du serveur" + +#: src/FLTK/fl_callbacks.cpp:2696 src/FLTK/fl_callbacks.cpp:2749 +msgid "" +"Primary and secondary audio device are both ASIO devices.\n" +"You can not use two ASIO devices at the same time.\n" +"Please select a different device.\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2717 src/FLTK/fl_callbacks.cpp:4155 +msgid "" +"butt could not open selected audio device.\n" +"Please try another device.\n" +msgstr "" +"butt n'a pas pu ouvrir le périphérique audio sélectionné.\n" +"Veuillez essayer un autre appareil.\n" + +#: src/FLTK/fl_callbacks.cpp:2732 +#, c-format +msgid "" +"Primary device:\n" +"%s\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2769 +msgid "" +"butt could not open secondary audio device.\n" +"Please try another device.\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2783 +#, c-format +msgid "" +"Secondary device:\n" +"%s\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:2894 src/FLTK/fl_callbacks.cpp:3072 +msgid "" +"MP3 encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"L'encodeur MP3 ne gère pas la combinaison\n" +"Sample-/Bitrate actuelle" + +#: src/FLTK/fl_callbacks.cpp:2915 +msgid "Stream codec set to mp3" +msgstr "Codec du flux réglé sur mp3" + +#: src/FLTK/fl_callbacks.cpp:2927 src/FLTK/fl_callbacks.cpp:3112 +msgid "" +"OGG Vorbis encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"L'encodeur OGG Vorbis ne gère pas la combinaison\n" +"Sample-/Bitrate actuelle" + +#: src/FLTK/fl_callbacks.cpp:2948 +msgid "Stream codec set to ogg/vorbis" +msgstr "Codec du flux réglé sur ogg/vorbis" + +#: src/FLTK/fl_callbacks.cpp:2959 src/FLTK/fl_callbacks.cpp:3151 +msgid "" +"Opus encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"L'encodeur Opus ne gère pas la combinaison\n" +"Sample-/Bitrate actuelle" + +#: src/FLTK/fl_callbacks.cpp:2979 +msgid "Stream codec set to opus" +msgstr "Codec du flux réglé sur opus" + +#: src/FLTK/fl_callbacks.cpp:3011 src/FLTK/fl_callbacks.cpp:3213 +msgid "" +"AAC encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"L'encodeur AAC ne gère pas la combinaison\n" +"Sample-/Bitrate actuelle" + +#: src/FLTK/fl_callbacks.cpp:3032 +msgid "Stream codec set to aac" +msgstr "Codec du flux réglée sur aac" + +#: src/FLTK/fl_callbacks.cpp:3042 src/FLTK/fl_callbacks.cpp:3252 +msgid "ERROR: While initializing flac settings" +msgstr "ERREUR : Lors de l'initialisation des paramètres de FLAC" + +#: src/FLTK/fl_callbacks.cpp:3060 +msgid "Stream codec set to flac" +msgstr "Codec du flux réglé sur flac" + +#: src/FLTK/fl_callbacks.cpp:3101 +msgid "Record codec set to mp3" +msgstr "Codec de l'enregistrement réglé sur mp3" + +#: src/FLTK/fl_callbacks.cpp:3140 +msgid "Record codec set to ogg/vorbis" +msgstr "Codec de l'enregistrement réglé sur ogg/vorbis" + +#: src/FLTK/fl_callbacks.cpp:3179 +msgid "Record codec set to opus" +msgstr "Codec de l'enregistrement réglé sur opus" + +#: src/FLTK/fl_callbacks.cpp:3242 +msgid "Record codec set to aac" +msgstr "Codec de l'enregistrement réglé sur aac" + +#: src/FLTK/fl_callbacks.cpp:3278 +msgid "Record codec set to flac" +msgstr "Codec de l'enregistrement réglé sur flac" + +#: src/FLTK/fl_callbacks.cpp:3294 +msgid "Record codec set to wav" +msgstr "Codec de l'enregistrement réglé sur wav" + +#: src/FLTK/fl_callbacks.cpp:3329 +msgid "Select certificate file..." +msgstr "Sélectionnez le fichier du certificat…" + +#: src/FLTK/fl_callbacks.cpp:3334 src/FLTK/fl_callbacks.cpp:3355 +#: src/FLTK/fl_callbacks.cpp:3466 src/FLTK/fl_callbacks.cpp:3556 +#: src/FLTK/fl_callbacks.cpp:4109 src/FLTK/fl_callbacks.cpp:4133 +#: src/FLTK/fl_callbacks.cpp:4257 +#, c-format +msgid "ERROR: %s" +msgstr "ERREUR : %s" + +#: src/FLTK/fl_callbacks.cpp:3347 +msgid "Select certificate directory..." +msgstr "Sélectionnez le répertoire du certificat…" + +#: src/FLTK/fl_callbacks.cpp:3458 +msgid "Record to..." +msgstr "Enregistrer vers…" + +#: src/FLTK/fl_callbacks.cpp:3483 +msgid "File splitting only works if recording is active." +msgstr "" +"La scission du fichier ne fonctionne que si l'enregistrement est activé." + +#: src/FLTK/fl_callbacks.cpp:3552 +msgid "Select Songfile" +msgstr "Choisissez le fichier du morceau" + +#: src/FLTK/fl_callbacks.cpp:3657 +msgid "Gain control is disabled. Enable in Settings->GUI" +msgstr "Le contrôle du gain est désactivé. Activer dans les paramètres->GUI" + +#: src/FLTK/fl_callbacks.cpp:3718 +msgid "select background color" +msgstr "Choisissez la couleur de fond" + +#: src/FLTK/fl_callbacks.cpp:3728 +msgid "select text color" +msgstr "Choisissez la couleur du texte" + +#: src/FLTK/fl_callbacks.cpp:3761 src/FLTK/fl_callbacks.cpp:3765 +#: src/FLTK/fl_callbacks.cpp:3774 src/FLTK/fl_callbacks.cpp:3778 +msgid "Value must be a number between -54 and 0" +msgstr "La valeur doit être comprise entre -54 et 0" + +#: src/FLTK/fl_callbacks.cpp:3788 +msgid "Please restart butt to apply new language." +msgstr "Veuillez redémarrer butt pour appliquer le changement de langue." + +#: src/FLTK/fl_callbacks.cpp:3867 src/FLTK/fl_callbacks.cpp:3872 +#: src/FLTK/fl_callbacks.cpp:3882 src/FLTK/fl_callbacks.cpp:3887 +msgid "Value must be a number between -90.0 and 0" +msgstr "La valeur doit être comprise entre -90 et 0" + +#: src/FLTK/fl_callbacks.cpp:4082 +msgid "Recording volume" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:4103 +msgid "Export to..." +msgstr "Exporter vers…" + +#: src/FLTK/fl_callbacks.cpp:4146 +#, c-format +msgid "Could not import config %s" +msgstr "Impossible d'importer la configuration %s" + +#: src/FLTK/fl_callbacks.cpp:4160 +#, c-format +msgid "Config imported %s" +msgstr "Configuration %s importée" + +#: src/FLTK/fl_callbacks.cpp:4234 +msgid "" +"Could not get update information.\n" +"Reason: Network error" +msgstr "" +"Impossible d'obtenir les informations de mise à jour.\n" +"Raison : Erreur de réseau" + +#: src/FLTK/fl_callbacks.cpp:4237 +msgid "" +"Could not get update information.\n" +"Reason: Unknown answer from server" +msgstr "" +"Impossible d'obtenir les informations de mise à jour.\n" +"Raison : Réponse du serveur inconnue" + +#: src/FLTK/fl_callbacks.cpp:4240 +msgid "You have the latest version!" +msgstr "Vous avez la dernière version !" + +#: src/FLTK/fl_callbacks.cpp:4243 +msgid "" +"Could not get update information.\n" +"Reason: Unknown" +msgstr "" +"Impossible d'obtenir les informations de mise à jour.\n" +"Raison : Inconnue" + +#: src/FLTK/fl_callbacks.cpp:4251 +msgid "Select logfile..." +msgstr "Choisissez le fichier du journal…" + +#: src/FLTK/fl_callbacks.cpp:4273 +msgid "" +"butt is currently streaming.\n" +"Do you really want to close butt now?" +msgstr "" +"butt est en train de diffuser.\n" +"Souhaitez-vous vraiment fermer butt maintenant ?" + +#: src/FLTK/fl_callbacks.cpp:4279 +msgid "" +"butt is currently recording.\n" +"Do you really want to close butt now?" +msgstr "" +"butt est en train d'enregistrer.\n" +"Souhaitez-vous vraiment fermer butt maintenant ?" + +#: src/FLTK/fl_callbacks.cpp:4354 +msgid "The URL must start with either http:// or https://" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:4366 +#, fuzzy +msgid "Value must be a number between 1 and 1000" +msgstr "La valeur doit être comprise entre -54 et 0" + +#: src/FLTK/fl_callbacks.cpp:5228 src/FLTK/fl_callbacks.cpp:5263 +#: src/FLTK/fl_callbacks.cpp:5298 src/FLTK/fl_callbacks.cpp:5333 +#: src/FLTK/fl_callbacks.cpp:5368 src/FLTK/fl_callbacks.cpp:5859 +#: src/FLTK/fl_callbacks.cpp:5894 src/FLTK/fl_callbacks.cpp:5929 +#: src/FLTK/fl_callbacks.cpp:5964 src/FLTK/fl_callbacks.cpp:5999 +msgid "The encoder could not be initialized with the provided parameters." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:5246 src/FLTK/fl_callbacks.cpp:5877 +msgid "The value must be between 0.001 kHz and 50 kHz" +msgstr "La valeur doit être comprise entre 0.001 kHz et 50 kHz" + +#: src/FLTK/fl_callbacks.cpp:5281 src/FLTK/fl_callbacks.cpp:5316 +#: src/FLTK/fl_callbacks.cpp:5351 src/FLTK/fl_callbacks.cpp:5912 +#: src/FLTK/fl_callbacks.cpp:5947 src/FLTK/fl_callbacks.cpp:5982 +msgid "The value must be between 0.001 kHz and 16 kHz" +msgstr "La valeur doit être comprise entre 0.001 kHz et 50 kHz" + +#: src/FLTK/fl_callbacks.cpp:6328 +msgid "MIDI device could not be opened." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:6334 +#, c-format +msgid "" +"MIDI device:\n" +"%s\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:6339 +msgid "MIDI device could not be started." +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:6344 +msgid "MIDI support disabled\n" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:6406 +msgid "The CC value must be between 0 and 127" +msgstr "" + +#: src/FLTK/fl_callbacks.cpp:6429 +msgid "Waiting..." +msgstr "" + +#: src/FLTK/fl_funcs.cpp:193 +msgid "Disabled" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:335 +#, c-format +msgid "%d seconds" +msgstr "%d secondes" + +#: src/FLTK/fl_funcs.cpp:386 +msgid "Not supported on Windows" +msgstr "Non géré sous Windows" + +#: src/FLTK/fl_funcs.cpp:808 +msgid "Start/Stop broadcasting" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:809 +msgid "Start/Stop recording" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:811 +msgid "Streaming Gain" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:812 +msgid "Recording Gain" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:813 +msgid "Primary Device Gain" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:814 +msgid "Secondary Device Gain" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:815 +msgid "Cross fader" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:816 +msgid "Mute/Unmute Primary Device" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:817 +msgid "Mute/Unmute Secondary Device" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:818 +msgid "Start broadcasting" +msgstr "" + +#: src/FLTK/fl_funcs.cpp:819 +#, fuzzy +msgid "Stop broadcasting" +msgstr "arrêter l'enregistrement ?" + +#: src/FLTK/fl_funcs.cpp:820 +#, fuzzy +msgid "Start recording" +msgstr "démarrer/arrêter l'enregistrement" + +#: src/FLTK/fl_funcs.cpp:821 +#, fuzzy +msgid "Stop recording" +msgstr "arrêter l'enregistrement ?" + +#: src/FLTK/fl_funcs.cpp:870 +msgid "dev. not supported" +msgstr "L'appareil n'est pas supporté" + +#: src/FLTK/fl_funcs.cpp:1087 +#, c-format +msgid "" +"Could not create recording folder:\n" +"%s\n" +"Please make sure the folder contains only valid format specifiers." +msgstr "" +"Impossible de créer le dossier d'enregistrement:\n" +"%s\n" +"Veuillez vous assurer que le dossier ne contient que des spécificateurs de " +"format valides." + +#: src/FLTK/fl_funcs.cpp:1102 +#, c-format +msgid "Could not create recording folder %s\n" +msgstr "Impossible d'écrire dans le fichier : %s\n" + +#: src/FLTK/fl_funcs.cpp:1111 +#, c-format +msgid "" +"Could not create recording file:\n" +"%s\n" +"Please make sure the filename contains only valid format specifiers." +msgstr "" +"Impossible de créer le fichier d'enregistrement :\n" +"%s\n" +"Veuillez vous assurer que le nom du fichier ne contient que des " +"spécificateurs de format valides." + +#: src/FLTK/fl_funcs.cpp:1157 +msgid "Could not find a valid filename" +msgstr "Aucun nom de fichier valide trouvé" + +#: src/FLTK/fl_funcs.cpp:1462 +msgid "TRUST" +msgstr "CONFIANCE" + +#: src/icecast.cpp:90 +msgid "" +"\n" +"connect: Could not create network socket" +msgstr "" +"\n" +"connexion : Impossible de créer le socket réseau" + +#: src/icecast.cpp:102 +msgid "" +"\n" +"connect: Error resolving server address" +msgstr "" +"\n" +"connexion : Erreur de résolution de l'adresse du serveur" + +#: src/icecast.cpp:142 +msgid "" +"\n" +"connect: SSL connection timed out. Trying again..." +msgstr "" +"\n" +"connexion : La connexion SSL n'a pas abouti. Nouvel essai…" + +#: src/icecast.cpp:149 +#, c-format +msgid "" +"SSL/TLS certificate verification failed\n" +"Reason: %s\n" +"\n" +"Do you still want to trust this certificate?\n" +"Trusting will be permanent and can be revoked\n" +"in the server settings." +msgstr "" +"La vérification du certificat SSL/TLS a échoué\n" +"Raison : %s\n" +"\n" +"Voulez-vous toujours faire confiance à ce certificat ?\n" +"La confiance est permanente et peut être révoquée\n" +"dans les paramètres du serveur." + +#: src/icecast.cpp:164 +#, c-format +msgid "" +"\n" +"connect: SSL connection failed\n" +"Reason: %s" +msgstr "" +"\n" +"connexion : la connexion SSL a échoué\n" +"Raison : %s" + +#: src/icecast.cpp:320 +msgid "" +"\n" +"connect: connection timed out. Trying again..." +msgstr "" +"\n" +"connexion : la connexion n'a pas abouti. Nouvel essai…" + +#: src/icecast.cpp:373 +msgid "" +"\n" +"connect: server answered with 400!\n" +msgstr "" +"\n" +"connexion : le serveur a renvoyé un code d'erreur 400!\n" + +#: src/icecast.cpp:379 +msgid "" +"\n" +"connect: invalid user/password!\n" +msgstr "" +"\n" +"connexion : couple utilisateur/mot de passe invalide !\n" + +#: src/icecast.cpp:402 +msgid "" +"\n" +"connect: server answered with 404!\n" +msgstr "" +"\n" +"connexion : le serveur a renvoyé un code d'erreur 404 !\n" + +#: src/icecast.cpp:409 +#, c-format +msgid "" +"\n" +"connect: server answered with %d!\n" +msgstr "" +"\n" +"connexion : le serveur a répondu avec %d !\n" + +#: src/icecast.cpp:434 +msgid "" +"\n" +"ERROR: Opus is not supported by your\n" +"Icecast server (>=1.4.0 required)!\n" +msgstr "" +"\n" +"ERREUR : Opus non géré par la version du\n" +"serveur Icecast (>=1.4.0 requise) !\n" + +#: src/icecast.cpp:507 +msgid "" +"\n" +"update_song: could not create network socket" +msgstr "" +"\n" +"update_song : Impossible de créer le socket réseau" + +#: src/icecast.cpp:511 +msgid "" +"\n" +"update_song: error resolving server address" +msgstr "" +"\n" +"update_song : erreur de résolution d'adresse serveur" + +#: src/lame_encode.cpp:74 +#, c-format +msgid "unable to init lame params %d" +msgstr "échec d'initialisation des paramètres de lame %d" + +#: src/port_audio.cpp:131 +#, c-format +msgid "" +"PortAudio init failed:\n" +"%s\n" +msgstr "" +"L'initialisation de PortAudio a échoué :\n" +"%s\n" + +#: src/port_audio.cpp:180 +msgid "ERROR: no sound device with input channels found" +msgstr "ERREUR : aucun périphérique son avec canaux d'entrée trouvé" + +#: src/port_audio.cpp:198 src/port_audio.cpp:289 src/port_audio.cpp:1331 +#: src/port_midi.cpp:177 +#, c-format +msgid "Error getting device Info (%d)" +msgstr "Erreur d'obtention des informations du périphérique (%d)" + +#: src/port_audio.cpp:241 +#, c-format +msgid "" +"Samplerate not supported: %dHz\n" +"Using default samplerate: %dHz" +msgstr "" +"Taux d'échantillonnage non géré : %dHz\n" +"Utilisation du taux d'échantillonnage par défaut : %dHz" + +#: src/port_audio.cpp:258 src/port_audio.cpp:360 +#, c-format +msgid "PA: Format not supported: %s\n" +msgstr "PortAudio : Format non géré : %s\n" + +#: src/port_audio.cpp:268 +#, c-format +msgid "error opening sound device: %s" +msgstr "" + +#: src/port_audio.cpp:326 +msgid "The selected secondary audio device can not be used" +msgstr "" + +#: src/port_audio.cpp:343 src/port_audio.cpp:1452 src/port_audio.cpp:1469 +msgid "ERROR: Could not initialize samplerate converter" +msgstr "" +"ERREUR : Impossible d'initialiser le convertisseur de taux d'échantillonnage" + +#: src/port_audio.cpp:354 +#, c-format +msgid "Samplerate of secondary device is resampled from %dHz to %dHz\n" +msgstr "" + +#: src/port_audio.cpp:381 +#, c-format +msgid "error opening secondary sound device: %s" +msgstr "" + +#: src/port_audio.cpp:921 +msgid "disconnected\n" +msgstr "déconnecté\n" + +#: src/port_audio.cpp:949 +msgid "recording stopped" +msgstr "enregistrement arrêté" + +#: src/port_midi.cpp:152 src/port_midi.cpp:211 src/port_midi.cpp:233 +#: src/port_midi.cpp:255 src/port_midi.cpp:282 src/port_midi.cpp:301 +#: src/port_midi.cpp:316 src/port_midi.cpp:341 src/port_midi.cpp:352 +msgid "Error: PortMidi was not initialized." +msgstr "" + +#: src/port_midi.cpp:262 +#, c-format +msgid "" +"Error: MIDI device %s could not be opened because no MIDI devices were found." +msgstr "" + +#: src/port_midi.cpp:269 +#, c-format +msgid "Error: MIDI device %s could not be found." +msgstr "" + +#: src/port_midi.cpp:286 +msgid "Error: MIDI thread already active." +msgstr "" + +#: src/port_midi.cpp:291 +msgid "Error: Could not start MIDI thread." +msgstr "" + +#: src/shoutcast.cpp:80 +msgid "" +"\n" +"Connect: Could not create network socket" +msgstr "" +"\n" +"Connexion : Impossible de créer le socket réseau" + +#: src/shoutcast.cpp:92 +msgid "" +"\n" +"Connect: Error resolving server address" +msgstr "" +"\n" +"Connexion : Erreur de résolution d'adresse du serveur" + +#: src/shoutcast.cpp:172 +msgid "" +"\n" +"connect: connection timed out. Trying again...\n" +msgstr "" +"\n" +"connexion : la connexion n'a pas abouti. Nouvel essai…\n" + +#: src/shoutcast.cpp:189 +msgid "" +"\n" +"Connect: Invalid password!\n" +msgstr "" +"\n" +"Connexion : Mot de passe invalide\n" + +#: src/shoutcast.cpp:238 +msgid "" +"\n" +"Update song: Could not create network socket" +msgstr "" +"\n" +"Update song : Impossible de créer le socket réseau" + +#: src/shoutcast.cpp:242 +msgid "" +"\n" +"Update song: Error resolving server address" +msgstr "" +"\n" +"Update song : Erreur de résolution de l'adresse du serveur" + +#: src/tls.cpp:159 +msgid "check_host: could not read host name from cert" +msgstr "check_host : Impossible de lire le nom d'hôte depuis le certificat" + +#: src/tls.cpp:194 +msgid "check_cert: No peer certificate available" +msgstr "check_cert : Pas de certificat pair disponible" + +#: src/tls.cpp:207 +msgid "check_cert: X509_check_host failed" +msgstr "check_cert : X509_check_host a échoué" + +#: src/tls.cpp:213 +msgid "check_cert: check_host failed" +msgstr "check_cert : check_host a échoué" + +#: src/tls.cpp:229 +msgid "calc_cert_hash: No peer certificate available" +msgstr "calc_cert_hash : Pas de certificat pair disponible" + +#: src/tls.cpp:236 +msgid "calc_cert_hash: Hash calculation failed" +msgstr "calc_cert_hash : Le calcul de l'empreinte a échoué" + +#: src/tls.cpp:305 +msgid "tls_setup: Could not set cipher list" +msgstr "" +"tls_setup : Impossible de définir la liste des algorithmes de chiffrement" + +#: src/tls.cpp:318 +msgid "tls_setup: SSL_new failed" +msgstr "tls_setup : SSL_new a échoué" + +#: src/tls.cpp:324 +msgid "tls_setup: Could not bind socket to SSL" +msgstr "tls_setup : Impossible de lier le socket à SSL" + +#: src/tls.cpp:338 +msgid "tls_setup: SSL_connect read timeout" +msgstr "tls_setup : délais de lecture SSL_connect dépassé" + +#: src/tls.cpp:344 +msgid "tls_setup: SSL_connect write timeout" +msgstr "tls_setup : délais d'écriture SSL_connect dépassé" + +#: src/tls.cpp:361 +msgid "tls_setup: Cert hash could not be calculated" +msgstr "tls_setup : Impossible de calculer l'empreinte du certificat" + +#: src/tls.cpp:385 +msgid "tls_send: read timeout" +msgstr "tls_send : délais de lecture dépassé" + +#: src/tls.cpp:392 +msgid "tls_send: write timeout" +msgstr "tls_send : délais d'écriture dépassé" + +#: src/tls.cpp:418 +msgid "tls_recv: read timeout" +msgstr "tls_recv : délais de lecture dépassé" + +#: src/tls.cpp:425 +msgid "tls_recv: write timeout" +msgstr "tls_recv : délais d'écriture dépassé" + +#~ msgid "Listeners: 99999" +#~ msgstr "Auditeurs: 99999" + +#, fuzzy +#~ msgid "Resample output" +#~ msgstr "Qualité du rééchantillonnage" + +#, fuzzy +#~ msgid "Resample output to selected sample rate" +#~ msgstr "Sélectionnez le taux d'échantillonnage de l'entrée" + +#, fuzzy, c-format +#~ msgid "" +#~ "error while parsing config. Missing WebRTC WHIP URL entry for server " +#~ "\"%s\".\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "erreur de lecture de la configuration. Le type du serveur \"%s\" est " +#~ "manquant.\n" +#~ "butt va fermer maintenant" + +#~ msgid "Preset " +#~ msgstr "Préréglage " + +#~ msgid "Text color" +#~ msgstr "Couleur du texte" + +#~ msgid "" +#~ "error while parsing config. Illegal value (-1) for num_of_srv.\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "erreur de lecture de la configuration. Valeur incorrecte (-1) pour " +#~ "num_of_srv.\n" +#~ "butt va fermer maintenant" + +#~ msgid "" +#~ "error while parsing config. Illegal value (-1) for num_of_icy.\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "erreur de lecture de la configuration. Valeur incorrecte (-1) pour " +#~ "num_of_icy.\n" +#~ "butt va fermer maintenant" + +#~ msgid "Dash address has been copied to clipboard." +#~ msgstr "L'adresse Dash a été copiée dans le presse papier." + +#~ msgid "Dash" +#~ msgstr "Dash" + +#~ msgid "recording to:" +#~ msgstr "enregistre vers :" + +#~ msgid "Convert Mono to Stereo" +#~ msgstr "Convertir du Mono vers Stéréo" + +#~ msgid "Copies a mono channel to both stereo channels" +#~ msgstr "Copie un canal mono vers chaque canal stéréo" + +#~ msgid "IceCast" +#~ msgstr "IceCast" + +#~ msgid "3.5kHz" +#~ msgstr "3.5kHz" + +#~ msgid "10kHz" +#~ msgstr "10kHz" + +#~ msgid "hello\n" +#~ msgstr "salut\n" + +#~ msgid "More @2<" +#~ msgstr "Plus @2<" diff --git a/po/insert-header.sin b/po/insert-header.sin new file mode 100644 index 0000000..b26de01 --- /dev/null +++ b/po/insert-header.sin @@ -0,0 +1,23 @@ +# Sed script that inserts the file called HEADER before the header entry. +# +# At each occurrence of a line starting with "msgid ", we execute the following +# commands. At the first occurrence, insert the file. At the following +# occurrences, do nothing. The distinction between the first and the following +# occurrences is achieved by looking at the hold space. +/^msgid /{ +x +# Test if the hold space is empty. +s/m/m/ +ta +# Yes it was empty. First occurrence. Read the file. +r HEADER +# Output the file's contents by reading the next line. But don't lose the +# current line while doing this. +g +N +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/po/nl.gmo b/po/nl.gmo new file mode 100644 index 0000000..64a2576 Binary files /dev/null and b/po/nl.gmo differ diff --git a/po/nl.po b/po/nl.po new file mode 100644 index 0000000..d6156ce --- /dev/null +++ b/po/nl.po @@ -0,0 +1,3207 @@ +# Dutch translation for butt-0.1.41 package. +# Copyright (C) 2024 Daniel Nöthen +# This file is distributed under the same license as the butt package. +# Timothy Wildschut , 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: butt 1.45.0\n" +"Report-Msgid-Bugs-To: butt@danielnoethen.de\n" +"POT-Creation-Date: 2025-04-19 14:55+0200\n" +"PO-Revision-Date: 2025-04-19 15:08+0200\n" +"Last-Translator: Timothy Wildschut \n" +"Language-Team: Dutch\n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.0.1\n" + +#: src/AskForMicPermission.m:20 +msgid "Microphone access" +msgstr "Microfoon toegang" + +#: src/AskForMicPermission.m:21 +msgid "" +"butt needs access to your microphone.\n" +"\n" +"Please go to\n" +"System Preferences->Privacy & Security->Microphone\n" +"and activate the check mark next to the butt entry." +msgstr "" +"butt heeft toegang tot je microfoon nodig.\n" +"Ga naar\n" +"Systeemvoorkeuren->Veiligheid en privacy->Privacy->Microfoon\n" +"en activeer het vinkje naast de butt-vermelding." + +#: src/butt.cpp:219 +msgid "No home-directory found" +msgstr "Geen thuismap gevonden" + +#: src/butt.cpp:230 +#, c-format +msgid "" +"The shift key was held down during startup.\n" +"Do you want to start butt with a new configuration file?\n" +"This will overwrite your existing configuration file at\n" +"%s" +msgstr "" +"Shift werd ingedrukt tijdens het opstarten.\n" +"Wil je butt starten met een nieuw configuratiebestand?\n" +"Dit overschrijft je bestaande configuratiebestand op\n" +"%s" + +#: src/butt.cpp:233 +msgid "Start with old" +msgstr "Begin met oud" + +#: src/butt.cpp:233 +msgid "Start with new" +msgstr "Begin met nieuw" + +#: src/butt.cpp:236 src/butt.cpp:253 +#, c-format +msgid "" +"Could not create config %s\n" +"butt is going to close now" +msgstr "" +"Kon config niet maken %s\n" +"butt zal nu afsluiten" + +#: src/butt.cpp:242 +#, c-format +msgid "Reading config %s\n" +msgstr "Config lezen %s\n" + +#: src/butt.cpp:250 +#, c-format +msgid "Could not find config %s\n" +msgstr "Kon config %s niet vinden\n" + +#: src/butt.cpp:257 +#, c-format +msgid "" +"butt created a default config at\n" +"%s\n" +msgstr "" +"butt heeft een standaard config gemaakt op\n" +"%s\n" + +#: src/butt.cpp:265 +msgid "" +"Could not find any audio device with input channels.\n" +"butt requires at least one audio device with input channels in order to " +"work.\n" +"This can either be a built-in audio device, an external audio device or a " +"virtual audio device.\n" +"\n" +"butt is going to close now." +msgstr "" +"Kon geen audioapparaat met ingangskanalen vinden.\n" +"butt vereist minstens één audioapparaat met ingangskanalen om te kunnen " +"werken.\n" +"Dit kan een ingebouwd, een extern of een virtueel audioapparaat zijn.\n" +"\n" +"butt zal nu afsluiten." + +#: src/butt.cpp:358 +#, c-format +msgid "Illegal argument: Threshold must be a non-negative number\n" +msgstr "Illegaal argument: Drempelwaarde moet een niet-negatief getal zijn\n" + +#: src/butt.cpp:382 +#, c-format +msgid "%c threshold set to %0.1f\n" +msgstr "%c Drempel ingesteld op %0.1f\n" + +#: src/butt.cpp:464 +#, c-format +msgid "Illegal argument: Port must be a number between 1023 and 65535\n" +msgstr "Illegaal argument: Poort moet een getal zijn tussen 1023 en 65535\n" + +#: src/butt.cpp:472 src/butt.cpp:482 src/butt.cpp:489 src/butt.cpp:496 +#: src/butt.cpp:503 src/butt.cpp:510 src/butt.cpp:521 src/butt.cpp:540 +#: src/butt.cpp:550 src/butt.cpp:597 +#, c-format +msgid "" +"Warning: You may only pass one control option. Option -%c has been ignored.\n" +msgstr "" +"Waarschuwing: Je mag slechts één besturingsoptie doorgeven. Optie -%c is " +"genegeerd.\n" + +#: src/butt.cpp:559 +#, c-format +msgid "" +"\n" +"Options:\n" +"-h\tPrint this help text\n" +"-v\tPrint version information\n" +msgstr "" +"\n" +"Opties:\n" +"-h\tPrint deze helptekst\n" +"-v\tPrint versie informatie\n" + +#: src/butt.cpp:563 +#, c-format +msgid "" +"\n" +"Options for operating mode:\n" +"-c\tPath to configuration file\n" +"-L\tPrint available audio devices\n" +"-A\tCommand server will be accessible from your network/internet (default: " +"localhost only)\n" +"-U\tCommand server will use UDP instead of TCP\n" +"-x\tDo not start a command server\n" +"-p\tPort where the command server shall listen to (default: 1256)\n" +msgstr "" +"\n" +"Opties voor modus:\n" +"-c\tPad naar configuratiebestand\n" +"-L\tBeschikbare audioapparaten afdrukken\n" +"-A\tCommandoserver zal toegankelijk zijn vanaf jouw netwerk/internet " +"(standaard: alleen localhost)\n" +"-U\tCommandoserver zal UDP in plaats van TCP gebruiken\n" +"-x\tStart geen commandoserver\n" +"-p\tPoort waar de commandoserver naar zal luisteren (standaard: 1256)\n" + +#: src/butt.cpp:572 +#, c-format +msgid "" +"\n" +"Options for control mode:\n" +"-s\tConnect to streaming server\n" +"-d\tDisconnect from streaming server\n" +"-r\tStart recording\n" +"-t\tStop recording\n" +"-n\tSplit recording\n" +"-q\tQuit butt\n" +"-u\tupdate song name\n" +"-S\tRequest status\n" +"-M\tSet streaming signal threshold (seconds)\n" +"-m\tSet streaming silence threshold (seconds)\n" +"-O\tSet recording signal threshold (seconds)\n" +"-o\tSet recording silence threshold (seconds)\n" +"-U\tConnect via UDP instead of TCP\n" +"-a\tAddress of the butt instance to be controlled (default: 127.0.0.1)\n" +"-p\tPort of the butt instance to be controlled (default: 1256)\n" +msgstr "" +"\n" +"Opties voor besturingsmodus:\n" +"-s\tVerbinding maken met de streamingserver\n" +"-d\tVerbinding met de streamingserver afsluiten\n" +"-r\tStart opname\n" +"-t\tStop opname\n" +"-n\tOpsplitsen van opname\n" +"-q\tSluiten van butt\n" +"-u\tUpdate Artiest - Titel\n" +"-S\tStatus opvragen\n" +"-M\tInstellen van de streaming-signaaldrempel (seconden)\n" +"-m\tInstellen van de streaming-stilte-drempel (seconden)\n" +"-O\tInstellen van de opname-signaaldrempel (seconden)\n" +"-o\tInstellen van de opname-stilte-drempel (seconden)\n" +"-U\tVerbinden via UDP in plaats van TCP\n" +"-a\tAdres van de te besturen butt-instantie (standaard: 127.0.0.1)\n" +"-p\tPoort van de te besturen butt-instantie (standaard: 1256)\n" + +#: src/butt.cpp:591 +#, c-format +msgid "" +"Illegal option -%c.\n" +"Type butt -h to get a list of supported options.\n" +msgstr "" +"Illegale optie -%c.\n" +"Typ butt -h voor een lijst met ondersteunde opties.\n" + +#: src/butt.cpp:603 +#, c-format +msgid "Option -%c requires an argument\n" +msgstr "Optie -%c vereist een argument\n" + +#: src/butt.cpp:607 +#, c-format +msgid "Command line parsing failed\n" +msgstr "Parsen van opdrachtregel mislukt\n" + +#: src/butt.cpp:630 +#, c-format +msgid "No butt instance running on %s at port %d\n" +msgstr "Geen actieve butt-instantie op %s op poort %d\n" + +#: src/butt.cpp:635 +#, c-format +msgid "Error while sending command\n" +msgstr "Fout bij verzenden van opdracht\n" + +#: src/butt.cpp:640 +#, c-format +msgid "Error: Did not receive response packet\n" +msgstr "Fout: Geen responspakket ontvangen\n" + +#: src/butt.cpp:653 +#, c-format +msgid "Error: You may only request one status packet per second\n" +msgstr "Fout: Je mag slechts één statuspakket per seconde aanvragen\n" + +#: src/butt.cpp:657 +#, c-format +msgid "Error: Did not receive status packet (UDP server not running?)\n" +msgstr "Fout: Geen statuspakket ontvangen (UDP-server niet actief?)\n" + +#: src/butt.cpp:661 +#, c-format +msgid "Network error while receiving status packet: %d\n" +msgstr "Netwerkfout bij ontvangst van statuspakket: %d\n" + +#: src/butt.cpp:665 +#, c-format +msgid "Error: Client and server versions do not match\n" +msgstr "Fout: Verschil in versies tussen client en server\n" + +#: src/butt.cpp:676 +#, c-format +msgid "" +"connected: %d\n" +"connecting: %d\n" +"recording: %d\n" +"signal present: %d\n" +"signal absent: %d\n" +msgstr "" +"verbonden: %d\n" +"verbinden: %d\n" +"opnemen: %d\n" +"signaal aanwezig: %d\n" +"signaal afwezig: %d\n" + +#: src/butt.cpp:681 +#, c-format +msgid "stream seconds: %lu\n" +msgstr "stream seconden: %lu\n" + +#: src/butt.cpp:682 +#, c-format +msgid "stream kBytes: %lu\n" +msgstr "stream kBytes: %lu\n" + +#: src/butt.cpp:683 +#, c-format +msgid "record seconds: %lu\n" +msgstr "opname seconden %lu\n" + +#: src/butt.cpp:684 +#, c-format +msgid "record kBytes: %lu\n" +msgstr "opname kBytes: %lu\n" + +#: src/butt.cpp:685 +#, c-format +msgid "volume left: %0.1f\n" +msgstr "volume links: %0.1f\n" + +#: src/butt.cpp:686 +#, c-format +msgid "volume right: %0.1f\n" +msgstr "volume rechts: %0.1f\n" + +#: src/butt.cpp:687 +#, c-format +msgid "song: %s\n" +msgstr "nummer: %s\n" + +#: src/butt.cpp:688 +#, c-format +msgid "record path: %s\n" +msgstr "opnamepad: %s\n" + +#: src/butt.cpp:689 +#, c-format +msgid "listeners: %d\n" +msgstr "ingelogd: %d\n" + +#: src/butt.cpp:703 +msgid "" +"The control key was held down during startup.\n" +"butt will start without opening an audio device.\n" +"Please select your preferred audio device in settings->audio" +msgstr "" +"De CTRL-toets was ingedrukt tijdens het opstarten.\n" +"butt zal starten zonder een audioapparaat te openen.\n" +"Selecteer je audioapparaat in Instellingen -> Audio" + +#: src/butt.cpp:712 +msgid "" +"PortAudio init failed\n" +"butt is going to close now" +msgstr "" +"PortAudio-initiatie mislukt\n" +"butt zal nu afsluiten" + +#: src/butt.cpp:747 src/FLTK/fl_timer_funcs.cpp:476 +#: src/FLTK/fl_callbacks.cpp:123 src/FLTK/fl_callbacks.cpp:899 +#: src/FLTK/fl_callbacks.cpp:977 src/FLTK/fl_funcs.cpp:1047 +msgid "idle" +msgstr "inactief" + +#: src/butt.cpp:780 +#, c-format +msgid "" +"Starting %s\n" +"Written by Daniel Nöthen\n" +"iPhone/iPad client: https://izicast.de\n" +"Donate: paypal@danielnoethen.de\n" +msgstr "" +"Opstarten van %s\n" +"Geschreven door Daniel Nöthen\n" +"iPhone/iPad-client: https://izicast.de\n" +"Doneren: paypal@danielnoethen.de\n" + +#: src/butt.cpp:792 src/butt.cpp:793 src/cfg.cpp:577 src/port_audio.cpp:1314 +#: src/port_audio.cpp:1315 +msgid "Default PCM device (default)" +msgstr "Standaard PCM-apparaat (standaard)" + +#: src/butt.cpp:796 src/butt.cpp:797 src/cfg.cpp:578 +#: src/FLTK/fl_callbacks.cpp:2820 src/FLTK/fl_funcs.cpp:227 +msgid "None" +msgstr "Geen" + +#: src/butt.cpp:800 +msgid "" +"Could not open audio device.\n" +"Please select your preferred audio device in settings->audio" +msgstr "" +"Kan het audioapparaat niet openen.\n" +"Selecteer je voorkeursaudioapparaat in Instellingen -> Audio" + +#: src/butt.cpp:803 +msgid "" +"butt could not open previously used audio device.\n" +"The system default audio device will be used.\n" +msgstr "" +"butt kon het eerder gebruikte audioapparaat niet openen.\n" +"Het standaard audioapparaat van het systeem zal worden gebruikt.\n" + +#: src/butt.cpp:830 +#, c-format +msgid "Command server listening on port %d\n" +msgstr "Commandoserver luistert op poort %d\n" + +#: src/butt.cpp:837 +#, c-format +msgid "Warning: could not start command server on port %d\n" +msgstr "Waarschuwing: kon commandoserver niet starten op poort %d\n" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:4225 +#, c-format +msgid "" +"New version available: %s\n" +"You have version %s" +msgstr "" +"Nieuwe versie beschikbaar: %s\n" +"Jij hebt versie %s" + +#: src/butt.cpp:853 +msgid "Don't ask again" +msgstr "Niet opnieuw vragen" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:1594 +#: src/FLTK/fl_callbacks.cpp:4225 +msgid "Cancel" +msgstr "Annuleer" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:4225 +msgid "Get new version" +msgstr "Verkrijg nieuwe versie" + +#: src/butt.cpp:874 +#, c-format +msgid "Could not initialize PortMidi: %s" +msgstr "Kon PortMidi %s niet initialiseren" + +#: src/butt.cpp:902 +msgid "butt was built without WebRTC support" +msgstr "butt is ontwikkeld zonder WebRTC-ondersteuning" + +#: src/cfg.cpp:55 +#, c-format +msgid "Could not write to file: %s" +msgstr "Kon niet schrijven naar bestand: %s" + +#: src/cfg.cpp:550 +#, c-format +msgid "Config written to %s" +msgstr "Config opgeslagen naar %s" + +#: src/cfg.cpp:674 +msgid "" +"error while parsing config. Missing main/server entry.\n" +"butt will start with default settings" +msgstr "" +"fout bij het parsen van de configuratie. Ontbrekende hoofd-/serverinvoer.\n" +"butt zal starten met de standaardinstellingen" + +#: src/cfg.cpp:680 +msgid "" +"error while parsing config. Missing main/srv_ent entry.\n" +"butt will start with default settings" +msgstr "" +"fout bij het parsen van de configuratie. Ontbrekende hoofd-/srv_ent-invoer.\n" +"butt zal starten met de standaardinstellingen" + +#: src/cfg.cpp:699 +#, c-format +msgid "" +"error while parsing config. Missing type entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"fout bij het parsen van de configuratie. Ontbrekende type-invoer voor server " +"\"%s\".\n" +"butt zal starten met de standaardinstellingen" + +#: src/cfg.cpp:707 +#, c-format +msgid "" +"error while parsing config. Missing address entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"fout bij het parsen van de configuratie. Ontbrekende adresinvoer voor server " +"\"%s\".\n" +"butt zal starten met de standaardinstellingen" + +#: src/cfg.cpp:716 +#, c-format +msgid "" +"error while parsing config. Missing port entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"fout bij het parsen van de configuratie. Ontbrekende poortinvoer voor server " +"\"%s\".\n" +"butt zal starten met de standaardinstellingen" + +#: src/cfg.cpp:725 +#, c-format +msgid "" +"error while parsing config. Missing password entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"fout bij het parsen van de configuratie. Ontbrekende wachtwoordinvoer voor " +"server \"%s\".\n" +"butt zal starten met de standaardinstellingen" + +#: src/cfg.cpp:734 +#, c-format +msgid "" +"error while parsing config. Missing mount entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"fout bij het parsen van de configuratie. Ontbrekende mount-invoer voor " +"server \"%s\".\n" +"butt zal starten met de standaardinstellingen" + +#: src/cfg.cpp:790 +msgid "" +"error while parsing config. Missing main/icy entry.\n" +"butt will start with default settings" +msgstr "" +"fout bij het parsen van de configuratie. Ontbrekende hoofd-/icy-invoer.\n" +"butt zal starten met de standaardinstellingen" + +#: src/cfg.cpp:795 +msgid "" +"error while parsing config. Missing main/icy_ent entry.\n" +"butt will start with default settings" +msgstr "" +"fout bij het parsen van de configuratie. Ontbrekende hoofd-/icy_ent-invoer.\n" +"butt zal starten met de standaardinstellingen" + +#: src/cfg.cpp:821 +#, c-format +msgid "" +"error while parsing config. Missing pub entry for icy \"%s\".\n" +"butt will start with default settings" +msgstr "" +"fout bij het parsen van de configuratie. Ontbrekende pub-invoer voor icy " +"\"%s\".\n" +"butt zal starten met de standaardinstellingen" + +#: src/FLTK/flgui.cpp:3088 +msgid "Bitcoin address has been copied to clipboard." +msgstr "Bitcoin-adres gekopieerd naar het klembord." + +#: src/FLTK/flgui.cpp:3099 +msgid "Litecoin address has been copied to clipboard." +msgstr "Litecoin-adres gekopieerd naar het klembord." + +#: src/FLTK/flgui.cpp:3110 +msgid "Monero address has been copied to clipboard." +msgstr "Monero-adres gekopieerd naar het klembord." + +#: src/FLTK/flgui.cpp:4041 +msgid "press left mouse to toggle lcd info" +msgstr "linker muisknop om lcd-info te wisselen" + +#: src/FLTK/flgui.cpp:4053 src/FLTK/fl_callbacks.cpp:4078 +msgid "Streaming volume" +msgstr "Stream volume" + +#: src/FLTK/flgui.cpp:4057 +msgid "Mixer" +msgstr "Mixer" + +#: src/FLTK/flgui.cpp:4058 +msgid "show/hide mixer window" +msgstr "toon/verberg mixer" + +#: src/FLTK/flgui.cpp:4065 +msgid "@circle" +msgstr "@circle" + +#: src/FLTK/flgui.cpp:4066 +msgid "start/stop recording" +msgstr "start/stop opname" + +#: src/FLTK/flgui.cpp:4077 +msgid "@square" +msgstr "@square" + +#: src/FLTK/flgui.cpp:4078 +msgid "disconnect from server" +msgstr "ontkoppelen van server" + +#: src/FLTK/flgui.cpp:4089 +msgid "@>" +msgstr "@>" + +#: src/FLTK/flgui.cpp:4090 +msgid "connect to server" +msgstr "verbind met server" + +#: src/FLTK/flgui.cpp:4106 src/FLTK/flgui.cpp:4438 src/FLTK/flgui.cpp:4657 +#: src/FLTK/fl_callbacks.cpp:4077 +msgid "Streaming" +msgstr "Streamen" + +#: src/FLTK/flgui.cpp:4110 src/FLTK/flgui.cpp:4469 src/FLTK/flgui.cpp:4771 +msgid "Recording" +msgstr "Opname" + +#: src/FLTK/flgui.cpp:4140 +msgid "Settings" +msgstr "Instellingen" + +#: src/FLTK/flgui.cpp:4141 +msgid "show/hide config window" +msgstr "toon/verberg configuratievenster" + +#: src/FLTK/flgui.cpp:4148 src/FLTK/fl_callbacks.cpp:1098 +msgid "Show log" +msgstr "Bekijk log" + +#: src/FLTK/flgui.cpp:4149 +msgid "show/hide info window" +msgstr "toon/verberg infovenster" + +#: src/FLTK/flgui.cpp:4156 +msgid "-24 dB" +msgstr "-24 dB" + +#: src/FLTK/flgui.cpp:4159 +msgid "Gain" +msgstr "Gain" + +#: src/FLTK/flgui.cpp:4160 src/FLTK/fl_callbacks.cpp:3663 +#: src/FLTK/fl_funcs.cpp:810 +msgid "Master Gain" +msgstr "Master Gain" + +#: src/FLTK/flgui.cpp:4178 +msgid "+24 dB" +msgstr "+24 dB" + +#: src/FLTK/flgui.cpp:4185 +msgid "Listeners: 0" +msgstr "Ingelogd: 0" + +#: src/FLTK/flgui.cpp:4200 +msgid "butt settings" +msgstr "butt instellingen" + +#: src/FLTK/flgui.cpp:4213 +msgid "Main" +msgstr "Hoofd" + +#: src/FLTK/flgui.cpp:4215 +msgid "Server Settings" +msgstr "Server Instellingen" + +#: src/FLTK/flgui.cpp:4218 +msgid "Server" +msgstr "Server" + +#: src/FLTK/flgui.cpp:4219 +msgid "Server to connect to" +msgstr "Server om mee te verbinden" + +#: src/FLTK/flgui.cpp:4224 src/FLTK/flgui.cpp:4245 +msgid "ADD" +msgstr "Voeg toe" + +#: src/FLTK/flgui.cpp:4225 src/FLTK/flgui.cpp:5550 +msgid "Add server" +msgstr "Voeg server toe" + +#: src/FLTK/flgui.cpp:4229 src/FLTK/flgui.cpp:4250 +msgid "EDIT" +msgstr "Bewerk" + +#: src/FLTK/flgui.cpp:4230 +msgid "Edit selected server" +msgstr "Bewerk geselecteerde server" + +#: src/FLTK/flgui.cpp:4234 src/FLTK/flgui.cpp:4255 +msgid "DEL" +msgstr "Wis" + +#: src/FLTK/flgui.cpp:4235 +msgid "Delete selected server" +msgstr "Verwijder geselecteerde server" + +#: src/FLTK/flgui.cpp:4239 +msgid "Stream Infos" +msgstr "StreamInformatie" + +#: src/FLTK/flgui.cpp:4240 +msgid "Stream info that shall be used" +msgstr "Streaminfo die gebruikt zal worden" + +#: src/FLTK/flgui.cpp:4246 src/FLTK/flgui.cpp:5671 +msgid "Add stream info" +msgstr "Voeg streaminfo toe" + +#: src/FLTK/flgui.cpp:4251 +msgid "Edit stream info" +msgstr "Bewerk streaminfo" + +#: src/FLTK/flgui.cpp:4256 +msgid "Delete stream info" +msgstr "Verwijder streaminfo" + +#: src/FLTK/flgui.cpp:4262 +msgid "Log File" +msgstr "Logbestand" + +#: src/FLTK/flgui.cpp:4266 +msgid "Log file path" +msgstr "Pad logbestand" + +#: src/FLTK/flgui.cpp:4271 +msgid "Select log file" +msgstr "Selecteer logbestand" + +#: src/FLTK/flgui.cpp:4278 +msgid "Configuration" +msgstr "Configuratie" + +#: src/FLTK/flgui.cpp:4281 src/FLTK/fl_callbacks.cpp:4128 +msgid "Import..." +msgstr "Import..." + +#: src/FLTK/flgui.cpp:4282 +msgid "Import settings from config file" +msgstr "Importeer instellingen van configuratiebestand" + +#: src/FLTK/flgui.cpp:4286 src/FLTK/flgui.cpp:5615 src/FLTK/flgui.cpp:5717 +msgid "&Save" +msgstr "&Opslaan" + +#: src/FLTK/flgui.cpp:4287 +msgid "Save settings" +msgstr "Instellingen opslaan" + +#: src/FLTK/flgui.cpp:4291 +msgid "Export..." +msgstr "Export..." + +#: src/FLTK/flgui.cpp:4292 +msgid "export settings" +msgstr "exporteer instellingen" + +#: src/FLTK/flgui.cpp:4298 +msgid "Butt Agent" +msgstr "Butt Agent" + +#: src/FLTK/flgui.cpp:4301 +msgid "Start agent at startup" +msgstr "Start agent bij opstarten" + +#: src/FLTK/flgui.cpp:4302 +msgid "Start the butt agent when butt starts" +msgstr "Start de butt agent als butt opstart" + +#: src/FLTK/flgui.cpp:4306 src/FLTK/flgui.cpp:4307 +msgid "Minimize butt to tray" +msgstr "Minimaliseer (systeemvak)" + +#: src/FLTK/flgui.cpp:4311 +msgid "Start Agent" +msgstr "Start Agent" + +#: src/FLTK/flgui.cpp:4312 +msgid "Start the butt agent now" +msgstr "Start de butt agent nu" + +#: src/FLTK/flgui.cpp:4316 +msgid "Stop Agent" +msgstr "Stop Agent" + +#: src/FLTK/flgui.cpp:4317 +msgid "Stop the butt agent" +msgstr "Stop de butt agent" + +#: src/FLTK/flgui.cpp:4323 +msgid "Updates" +msgstr "Updates" + +#: src/FLTK/flgui.cpp:4326 +msgid "Check at startup" +msgstr "Controleer tijdens opstarten" + +#: src/FLTK/flgui.cpp:4327 +msgid "Check for updates at start" +msgstr "Controleer op updates tijdens opstarten" + +#: src/FLTK/flgui.cpp:4331 +msgid "Check now" +msgstr "Nu controleren" + +#: src/FLTK/flgui.cpp:4332 +msgid "Check if a new version is available" +msgstr "Controleer beschikbaarheid nieuwe versie" + +#: src/FLTK/flgui.cpp:4338 +msgid "Help" +msgstr "Help" + +#: src/FLTK/flgui.cpp:4341 +msgid "Manual" +msgstr "Handleiding" + +#: src/FLTK/flgui.cpp:4345 +msgid " YouTube" +msgstr " Youtube" + +#: src/FLTK/flgui.cpp:4355 +msgid "Audio" +msgstr "Audio" + +#: src/FLTK/flgui.cpp:4357 +msgid "Main Audio Settings" +msgstr "Audio Instellingen" + +#: src/FLTK/flgui.cpp:4360 +msgid "Channel mode" +msgstr "Kanaalmode" + +#: src/FLTK/flgui.cpp:4361 +msgid "Select input channel" +msgstr "Selecteer ingangskanaal" + +#: src/FLTK/flgui.cpp:4374 +msgid "Samplerate" +msgstr "Samplerate" + +#: src/FLTK/flgui.cpp:4375 +msgid "Select input sample rate" +msgstr "Selecteer ingang samplerate" + +#: src/FLTK/flgui.cpp:4380 +msgid "Remember Device by" +msgstr "Onthoud apparaat op" + +#: src/FLTK/flgui.cpp:4383 +msgid "ID" +msgstr "ID" + +#: src/FLTK/flgui.cpp:4388 +msgid "Name" +msgstr "Naam" + +#: src/FLTK/flgui.cpp:4395 +msgid "Update devices" +msgstr "Werk apparaten bij" + +#: src/FLTK/flgui.cpp:4396 +msgid "Rescan audio devices" +msgstr "Herscan audioapparaten" + +#: src/FLTK/flgui.cpp:4400 +msgid "Primary Audio Device" +msgstr "Primair Audioapparaat" + +#: src/FLTK/flgui.cpp:4401 +msgid "Select your primary sound card device" +msgstr "Selecteer primair audioapparaat" + +#: src/FLTK/flgui.cpp:4406 src/FLTK/flgui.cpp:4424 +msgid "Left" +msgstr "Links" + +#: src/FLTK/flgui.cpp:4407 src/FLTK/flgui.cpp:4425 +msgid "Select left audio channel" +msgstr "Selecteer linker audiokanaal" + +#: src/FLTK/flgui.cpp:4412 src/FLTK/flgui.cpp:4430 +msgid "Right" +msgstr "Rechts" + +#: src/FLTK/flgui.cpp:4413 src/FLTK/flgui.cpp:4431 +msgid "Select right audio channel" +msgstr "Selecteer rechter audiokanaal" + +#: src/FLTK/flgui.cpp:4418 +msgid "Secondary Audio Device" +msgstr "Secundair Audioapparaat" + +#: src/FLTK/flgui.cpp:4419 +msgid "Select your secondary sound card device" +msgstr "Selecteer secundair audioapparaat" + +#: src/FLTK/flgui.cpp:4441 src/FLTK/flgui.cpp:4472 +msgid "Codec" +msgstr "Codec" + +#: src/FLTK/flgui.cpp:4442 +msgid "Select streaming codec" +msgstr "Selecteer stream codec" + +#: src/FLTK/flgui.cpp:4455 src/FLTK/flgui.cpp:4486 +msgid "Bitrate" +msgstr "Bitrate" + +#: src/FLTK/flgui.cpp:4456 +msgid "Select streaming bitrate" +msgstr "Selecteer stream bitrate" + +#: src/FLTK/flgui.cpp:4473 +msgid "Select recording codec" +msgstr "Selecteer opname codec" + +#: src/FLTK/flgui.cpp:4487 +msgid "Select recording bitrate" +msgstr "Selecteer opname bitrate" + +#: src/FLTK/flgui.cpp:4499 +msgid "Advanced..." +msgstr "Geavanceerd..." + +#: src/FLTK/flgui.cpp:4505 +msgid "Buffer (ms)" +msgstr "Buffer (ms)" + +#: src/FLTK/flgui.cpp:4514 +msgid "Resample Quality" +msgstr "Hersample kwaliteit" + +#: src/FLTK/flgui.cpp:4529 +msgid "Signal detection levels" +msgstr "Signaal detectieniveaus" + +#: src/FLTK/flgui.cpp:4532 +msgid "Signal present" +msgstr "Signaal aanwezig" + +#: src/FLTK/flgui.cpp:4539 src/FLTK/flgui.cpp:4549 +msgid "dB" +msgstr "dB" + +#: src/FLTK/flgui.cpp:4542 +msgid "Signal absent" +msgstr "Signaal afwezig" + +#: src/FLTK/flgui.cpp:4556 src/FLTK/flgui.cpp:4833 src/FLTK/flgui.cpp:5084 +msgid "Stream" +msgstr "Stream" + +#: src/FLTK/flgui.cpp:4558 +msgid "Update song name from file" +msgstr "Artiest - Titel bijwerken vanuit bestand" + +#: src/FLTK/flgui.cpp:4562 +msgid "Filename that holds the current song name" +msgstr "Bestandsnaam die huidig Artiest - Titel bevat" + +#: src/FLTK/flgui.cpp:4568 +msgid "Select file that holds the current song name" +msgstr "Selecteer bestand die huidig Artiest - Titel bevat" + +#: src/FLTK/flgui.cpp:4573 src/FLTK/flgui.cpp:4606 src/FLTK/flgui.cpp:4724 +msgid "Activate" +msgstr "Activeer" + +#: src/FLTK/flgui.cpp:4574 src/FLTK/flgui.cpp:4579 +msgid "Activate auto update song name from file" +msgstr "Activeer automatische verversing Artiest - Titel vanuit bestand" + +#: src/FLTK/flgui.cpp:4578 +msgid "Read last line instead of first" +msgstr "Laatste regel gebruiken" + +#: src/FLTK/flgui.cpp:4585 +msgid "Update song name from application" +msgstr "Artiest - Titel bijwerken vanuit een programma" + +#: src/FLTK/flgui.cpp:4589 +msgid "Changes the song through an running application" +msgstr "Past Artiest - Titel aan middels een lopend programma" + +#: src/FLTK/flgui.cpp:4594 +msgid "Title - Artist" +msgstr "Titel - Artiest" + +#: src/FLTK/flgui.cpp:4599 +msgid "Artist - Title" +msgstr "Artiest - Titel" + +#: src/FLTK/flgui.cpp:4612 +msgid "Update song name manually" +msgstr "Artiest - Titel handmatig bijwerken" + +#: src/FLTK/flgui.cpp:4616 +msgid "Current song name" +msgstr "Huidige Artiest - Titel" + +#: src/FLTK/flgui.cpp:4622 src/FLTK/fl_callbacks.cpp:1594 +msgid "OK" +msgstr "OK" + +#: src/FLTK/flgui.cpp:4623 +msgid "Send current song name to the server" +msgstr "Stuur huidig Artiest - Titel naar de server" + +#: src/FLTK/flgui.cpp:4631 +msgid "Update song name delay" +msgstr "Vertraging bij bijwerken Artiest - Titel" + +#: src/FLTK/flgui.cpp:4635 +msgid "Introduces a delay until the song name is actually updated" +msgstr "" +"Voeg een vertraging toe voordat Artiest - Titel daadwerkelijk wordt " +"bijgewerkt" + +#: src/FLTK/flgui.cpp:4642 +msgid "Extend song name" +msgstr "Uitbreiden Artiest - Titel (voor- achtervoegsel)" + +#: src/FLTK/flgui.cpp:4645 +msgid "Prefix:" +msgstr "Voor:" + +#: src/FLTK/flgui.cpp:4650 +msgid "Suffix:" +msgstr "Achter:" + +#: src/FLTK/flgui.cpp:4660 src/FLTK/flgui.cpp:4789 +msgid "Start if signal is present for" +msgstr "Start bij signaal voor" + +#: src/FLTK/flgui.cpp:4661 +msgid "" +"Start streaming if the audio level exceeds the \"Signal present\" level set " +"in the \"Audio\" tab" +msgstr "" +"Start stream als het audioniveau de \"Signaal aanwezig\"-drempel " +"overschrijdt, zoals ingesteld op het tabblad \"Audio\"" + +#: src/FLTK/flgui.cpp:4670 src/FLTK/flgui.cpp:4683 src/FLTK/flgui.cpp:4702 +#: src/FLTK/flgui.cpp:4799 src/FLTK/flgui.cpp:4812 src/FLTK/flgui.cpp:5499 +msgid "seconds" +msgstr "seconden" + +#: src/FLTK/flgui.cpp:4673 src/FLTK/flgui.cpp:4802 +msgid "Stop if signal is absent for" +msgstr "Stop bij geen signaal voor" + +#: src/FLTK/flgui.cpp:4674 +msgid "" +"Stop streaming if the audio level falls below the \"Signal absent level set " +"in the \"Audio\" tab" +msgstr "" +"Stop stream als het audioniveau onder de \"Signaal afwezig\"-drempel komt, " +"zoals ingesteld op het tabblad \"Audio\"" + +#: src/FLTK/flgui.cpp:4686 +msgid "Start streaming after launch" +msgstr "Start streamen na opstarten" + +#: src/FLTK/flgui.cpp:4687 +msgid "Connect automatically to a server after launch" +msgstr "Verbind automatisch met een server na opstarten" + +#: src/FLTK/flgui.cpp:4691 +msgid "Force reconnecting" +msgstr "Forceer herverbinden" + +#: src/FLTK/flgui.cpp:4692 +msgid "If enabled butt keeps reconnecting regardless of the error message" +msgstr "Indien ingeschakeld zal butt blijven verbinden ongeacht foutmeldingen" + +#: src/FLTK/flgui.cpp:4696 +msgid "Reconnect delay:" +msgstr "Herverbind vertraging:" + +#: src/FLTK/flgui.cpp:4707 +msgid "Update song name from URL" +msgstr "Update Artiest - Titel vanaf URL" + +#: src/FLTK/flgui.cpp:4711 +msgid "URL to get song name from" +msgstr "Update Artiest - Titel vanaf" + +#: src/FLTK/flgui.cpp:4716 +msgid "Update interval" +msgstr "Update snelheid" + +#: src/FLTK/flgui.cpp:4717 +msgid "Update interval in seconds" +msgstr "Update-interval in seconden" + +#: src/FLTK/flgui.cpp:4732 +msgid "Record" +msgstr "Opname" + +#: src/FLTK/flgui.cpp:4734 +msgid "Record File Name:" +msgstr "Opname bestandsnaam:" + +#: src/FLTK/flgui.cpp:4735 +msgid "Record file name" +msgstr "Opname bestandsnaam" + +#: src/FLTK/flgui.cpp:4740 +msgid "Record Directory:" +msgstr "Opname Map:" + +#: src/FLTK/flgui.cpp:4741 +msgid "Directory of recordings" +msgstr "Map met opnames" + +#: src/FLTK/flgui.cpp:4747 +msgid "Select recording directory" +msgstr "Selecteer opnamemap" + +#: src/FLTK/flgui.cpp:4752 +msgid "Split file" +msgstr "Splits bestand" + +#: src/FLTK/flgui.cpp:4755 +msgid "every" +msgstr "elke" + +#: src/FLTK/flgui.cpp:4758 +msgid "minutes" +msgstr "minuten" + +#: src/FLTK/flgui.cpp:4760 src/FLTK/flgui.cpp:4761 +msgid "Sync to full hour" +msgstr "Sync tot vol uur" + +#: src/FLTK/flgui.cpp:4765 +msgid "Split now" +msgstr "Splits nu" + +#: src/FLTK/flgui.cpp:4774 src/FLTK/flgui.cpp:4775 +msgid "Start recording when connected" +msgstr "Start opname bij verbinding" + +#: src/FLTK/flgui.cpp:4779 +msgid "Stop recording when disconnected" +msgstr "Stop opname bij verbreking van de verbinding" + +#: src/FLTK/flgui.cpp:4780 +msgid "Start recording when disconnected" +msgstr "Start opname bij verbreking verbinding" + +#: src/FLTK/flgui.cpp:4784 src/FLTK/flgui.cpp:4785 +msgid "Start recording after launch" +msgstr "Start opname na opstarten van butt" + +#: src/FLTK/flgui.cpp:4790 +msgid "" +"Start recording if the audio level exceeds the \"Signal present\" level set " +"in the \"Audio\" tab" +msgstr "" +"Start opname als het audioniveau de \"Signaal aanwezig\"-drempel " +"overschrijdt, zoals ingesteld op het tabblad \"Audio\"" + +#: src/FLTK/flgui.cpp:4803 +msgid "" +"Stop recording if the audio level falls below the \"Signal absent level set " +"in the \"Audio\" tab" +msgstr "" +"Stop opname als het audioniveau de \"Signaal aanwezig\"-drempel " +"overschrijdt, zoals ingesteld op het tabblad \"Audio\"" + +#: src/FLTK/flgui.cpp:4815 +msgid "Overwrite existing files" +msgstr "Overschrijf bestaande bestanden" + +#: src/FLTK/flgui.cpp:4823 +msgid "DSP" +msgstr "DSP" + +#: src/FLTK/flgui.cpp:4825 src/FLTK/flgui.cpp:5076 src/FLTK/flgui.cpp:6478 +msgid "Reset" +msgstr "Reset" + +#: src/FLTK/flgui.cpp:4830 +msgid "Equalizer" +msgstr "Equalizer" + +#: src/FLTK/flgui.cpp:4837 src/FLTK/flgui.cpp:5088 +msgid "Rec" +msgstr "Opname" + +#: src/FLTK/flgui.cpp:4842 +msgid "Equalizer Preset" +msgstr "Equalizer Preset" + +#: src/FLTK/flgui.cpp:4854 src/FLTK/flgui.cpp:4876 src/FLTK/flgui.cpp:4898 +#: src/FLTK/flgui.cpp:4920 src/FLTK/flgui.cpp:4942 src/FLTK/flgui.cpp:4964 +#: src/FLTK/flgui.cpp:4986 src/FLTK/flgui.cpp:5008 src/FLTK/flgui.cpp:5030 +#: src/FLTK/flgui.cpp:5052 src/FLTK/flgui.cpp:5096 src/FLTK/flgui.cpp:5118 +#: src/FLTK/flgui.cpp:5186 +msgid "+0.0" +msgstr "+0.0" + +#: src/FLTK/flgui.cpp:4858 +msgid "32Hz" +msgstr "32Hz" + +#: src/FLTK/flgui.cpp:4880 +msgid "64Hz" +msgstr "64Hz" + +#: src/FLTK/flgui.cpp:4902 +msgid "125Hz" +msgstr "125Hz" + +#: src/FLTK/flgui.cpp:4924 +msgid "250Hz" +msgstr "250Hz" + +#: src/FLTK/flgui.cpp:4946 +msgid "500Hz" +msgstr "500Hz" + +#: src/FLTK/flgui.cpp:4968 +msgid "1kHz" +msgstr "1kHz" + +#: src/FLTK/flgui.cpp:4990 +msgid "2kHz" +msgstr "2kHz" + +#: src/FLTK/flgui.cpp:5012 +msgid "4kHz" +msgstr "4kHz" + +#: src/FLTK/flgui.cpp:5034 +msgid "8kHz" +msgstr "8kHz" + +#: src/FLTK/flgui.cpp:5056 +msgid "16kHz" +msgstr "16kHz" + +#: src/FLTK/flgui.cpp:5081 +msgid "Dynamic Range Compressor" +msgstr "Dynamisch bereikprocessor" + +#: src/FLTK/flgui.cpp:5092 +msgid "Aggressive Mode" +msgstr "Aggressive Mode" + +#: src/FLTK/flgui.cpp:5100 +msgid "Threshold" +msgstr "Drempel" + +#: src/FLTK/flgui.cpp:5122 +msgid "Ratio" +msgstr "Ratio" + +#: src/FLTK/flgui.cpp:5140 src/FLTK/flgui.cpp:5163 +msgid "+0.00" +msgstr "+0.00" + +#: src/FLTK/flgui.cpp:5144 +msgid "Attack" +msgstr "Attack" + +#: src/FLTK/flgui.cpp:5167 +msgid "Release" +msgstr "Release" + +#: src/FLTK/flgui.cpp:5190 +msgid "MakeupGain" +msgstr "MakeupGain" + +#: src/FLTK/flgui.cpp:5224 src/FLTK/flgui.cpp:5237 +msgid "MIDI" +msgstr "MIDI" + +#: src/FLTK/flgui.cpp:5226 +msgid "MIDI Device" +msgstr "MIDI apparaat" + +#: src/FLTK/flgui.cpp:5227 +msgid "Select your MIDI device" +msgstr "Selecteer je MIDI apparaat" + +#: src/FLTK/flgui.cpp:5232 +msgid "Rescan" +msgstr "Opnieuw scannen" + +#: src/FLTK/flgui.cpp:5233 +msgid "Rescan MIDI devices" +msgstr "Opnieuw scannen MIDI apparaten" + +#: src/FLTK/flgui.cpp:5238 +msgid "MIDI signal indicator" +msgstr "MIDI signaal indicator" + +#: src/FLTK/flgui.cpp:5250 +msgid "MIDI Commands" +msgstr "MIDI Commando's" + +#: src/FLTK/flgui.cpp:5255 +msgid "Enable" +msgstr "Inschakelen" + +#: src/FLTK/flgui.cpp:5256 +msgid "Enable/Disable the selected MIDI command" +msgstr "In-/uitschakelen geselecteerd MIDI commando" + +#: src/FLTK/flgui.cpp:5262 +msgid "Channel" +msgstr "Kanaal" + +#: src/FLTK/flgui.cpp:5263 +msgid "Select MIDI channel" +msgstr "Selecteer MIDI kanaal" + +#: src/FLTK/flgui.cpp:5277 +msgid "CC" +msgstr "CC" + +#: src/FLTK/flgui.cpp:5278 +msgid "Select CC number" +msgstr "Selecteer CC nummer" + +#: src/FLTK/flgui.cpp:5283 src/FLTK/fl_callbacks.cpp:6425 +msgid "Learn" +msgstr "Leer" + +#: src/FLTK/flgui.cpp:5284 +msgid "Activate to auto detect the channel and CC number" +msgstr "Activeer autodetectie kanaal en CC nummer" + +#: src/FLTK/flgui.cpp:5289 +msgid "CC Mode" +msgstr "CC Mode" + +#: src/FLTK/flgui.cpp:5290 +msgid "Select CC mode" +msgstr "Selecteer CC mode" + +#: src/FLTK/flgui.cpp:5304 +msgid "Soft takeover" +msgstr "Soft takeover" + +#: src/FLTK/flgui.cpp:5305 +msgid "Prevents jumps when controlling a slider in absolute mode" +msgstr "" +"Voorkomt verspringen bij het bedienen van een schuifregelaar in absolute " +"modus" + +#: src/FLTK/flgui.cpp:5313 +msgid "TLS" +msgstr "TLS" + +#: src/FLTK/flgui.cpp:5315 src/FLTK/flgui.cpp:5619 +msgid "SSL/TLS" +msgstr "SSL/TLS" + +#: src/FLTK/flgui.cpp:5318 +msgid "" +"If your server uses a certificate from\n" +"Let's Encrypt or another well known\n" +"CA, you can leave these fields blank." +msgstr "" +"Als je server een certificaat gebruikt van\n" +"Let's Encrypt of een andere bekende\n" +"CA, dan kun je deze velden leeg laten." + +#: src/FLTK/flgui.cpp:5322 +msgid "CA Certificate File:" +msgstr "CA Certificaat bestand:" + +#: src/FLTK/flgui.cpp:5323 +msgid "Certificate file" +msgstr "Certificaat bestand" + +#: src/FLTK/flgui.cpp:5329 +msgid "Select certificate file" +msgstr "Selecteer certificaat-bestand" + +#: src/FLTK/flgui.cpp:5334 +msgid "CA Certificate Directory:" +msgstr "CA Certificaat map:" + +#: src/FLTK/flgui.cpp:5335 +msgid "Certificate directory" +msgstr "Certificaatmap" + +#: src/FLTK/flgui.cpp:5341 +msgid "Select certificate directory" +msgstr "Selecteer certificaatmap" + +#: src/FLTK/flgui.cpp:5350 +msgid "GUI" +msgstr "GUI" + +#: src/FLTK/flgui.cpp:5352 +msgid "Language" +msgstr "Taal" + +#: src/FLTK/flgui.cpp:5369 +msgid "Display Color" +msgstr "Weergavekleur" + +#: src/FLTK/flgui.cpp:5372 +msgid "Text" +msgstr "Tekst" + +#: src/FLTK/flgui.cpp:5373 +msgid "Select text color" +msgstr "Selecteer tekstkleur" + +#: src/FLTK/flgui.cpp:5379 +msgid "Background" +msgstr "Achtergrond" + +#: src/FLTK/flgui.cpp:5380 +msgid "Select background color" +msgstr "Selecteer achtergrondkleur" + +#: src/FLTK/flgui.cpp:5388 +msgid "VU meter" +msgstr "VU meter" + +#: src/FLTK/flgui.cpp:5391 +msgid "Gradient colors" +msgstr "Gradientkleuren" + +#: src/FLTK/flgui.cpp:5396 +msgid "Solid colors" +msgstr "Solide kleuren" + +#: src/FLTK/flgui.cpp:5401 +msgid "Always show tabs" +msgstr "Altijd tabbladen tonen" + +#: src/FLTK/flgui.cpp:5406 +msgid "Select lower range color" +msgstr "Kies de kleur van het lagere bereik" + +#: src/FLTK/flgui.cpp:5413 +msgid "Select mid range color" +msgstr "Kies de kleur van het middensegment" + +#: src/FLTK/flgui.cpp:5420 +msgid "Select high range color" +msgstr "Kies de kleur van het hogere bereik" + +#: src/FLTK/flgui.cpp:5427 +msgid "Low range start value (dB)" +msgstr "Startwaarde laag bereik (dB)" + +#: src/FLTK/flgui.cpp:5431 +msgid "Mid range start value (dB)" +msgstr "Startwaarde midden bereik (dB)" + +#: src/FLTK/flgui.cpp:5440 +msgid "High range start value (dB)" +msgstr "Startwaarde hoog bereik (dB)" + +#: src/FLTK/flgui.cpp:5450 +msgid "Misc" +msgstr "Misc" + +#: src/FLTK/flgui.cpp:5453 +msgid "Attach settings window to main window" +msgstr "Instellingenvenster koppelen aan hoofdvenster" + +#: src/FLTK/flgui.cpp:5454 +msgid "Attach this window to the butt window" +msgstr "Koppel dit venster aan het butt-venster" + +#: src/FLTK/flgui.cpp:5458 src/FLTK/flgui.cpp:5459 +msgid "Stay always on top" +msgstr "Altijd bovenaan blijven" + +#: src/FLTK/flgui.cpp:5463 src/FLTK/flgui.cpp:5464 +msgid "Remember main window position" +msgstr "Onthoud positie hoofdvenster" + +#: src/FLTK/flgui.cpp:5468 src/FLTK/flgui.cpp:5469 +msgid "Hide log window after start up" +msgstr "Verberg logvenster bij opstarten" + +#: src/FLTK/flgui.cpp:5473 src/FLTK/flgui.cpp:5474 +msgid "Change display mode every 5 seconds" +msgstr "Verander weergavemodus elke 5 seconden" + +#: src/FLTK/flgui.cpp:5478 +msgid "Start minimized" +msgstr "Start geminimaliseerd" + +#: src/FLTK/flgui.cpp:5479 +msgid "Minimize butt at startup" +msgstr "Minimaliseer butt bij opstarten" + +#: src/FLTK/flgui.cpp:5483 +msgid "Disable gain control" +msgstr "Uitschakelen van gain-control" + +#: src/FLTK/flgui.cpp:5489 +msgid "Show listeners" +msgstr "Toon Ingelogd" + +#: src/FLTK/flgui.cpp:5490 +msgid "Show current listeners in the display (not always available)" +msgstr "Toon huidige Ingelogd in het display (niet altijd beschikbaar)" + +#: src/FLTK/flgui.cpp:5494 +msgid "Update rate:" +msgstr "Update snelheid:" + +#: src/FLTK/flgui.cpp:5504 +msgid "Custom window title:" +msgstr "Aangepaste venstertitel:" + +#: src/FLTK/flgui.cpp:5505 +msgid "Define a custom window title" +msgstr "Definieer een aangepaste venstertitel" + +#: src/FLTK/flgui.cpp:5515 +msgid "Donate" +msgstr "Doneer" + +#: src/FLTK/flgui.cpp:5517 +msgid "Donation" +msgstr "Donatie" + +#: src/FLTK/flgui.cpp:5520 +msgid "" +"Keeping this software up to date, adding\n" +"new features and answering support mails\n" +"takes a lot of time and effort. If you can\n" +"afford it, please consider supporting this\n" +"project.\n" +"\n" +"Thank you!" +msgstr "" +"Deze software up-to-date houden, nieuwe\n" +"functies toevoegen en ondersteuningsmails\n" +"beantwoorden vergt veel tijd en inspanning.\n" +"Als je het je kunt veroorloven, overweeg dan\n" +"alsjeblieft dit project te ondersteunen.\n" +"\n" +"Dank je!" + +#: src/FLTK/flgui.cpp:5525 +msgid "&Donate via PayPal" +msgstr "&Doneer met PayPal" + +#: src/FLTK/flgui.cpp:5529 +msgid "Become a &patron" +msgstr "Word een &patron" + +#: src/FLTK/flgui.cpp:5533 +msgid "&Apple Pay, Google Pay, CC and more" +msgstr "&Apple Pay, Google Pay, CC en meer" + +#: src/FLTK/flgui.cpp:5537 +msgid "&Bitcoin && Co" +msgstr "&Bitcoin && Co" + +#: src/FLTK/flgui.cpp:5552 src/FLTK/flgui.cpp:5673 +msgid "Name:" +msgstr "Naam:" + +#: src/FLTK/flgui.cpp:5556 +msgid "Address:" +msgstr "Adres:" + +#: src/FLTK/flgui.cpp:5560 +msgid "Port:" +msgstr "Poort:" + +#: src/FLTK/flgui.cpp:5564 +msgid "Password:" +msgstr "Wachtwoord:" + +#: src/FLTK/flgui.cpp:5569 +msgid "Icecast mountpoint:" +msgstr "Icecast mountpoint:" + +#: src/FLTK/flgui.cpp:5573 +msgid "Icecast user:" +msgstr "Icecast gebruiker:" + +#: src/FLTK/flgui.cpp:5577 src/FLTK/fl_callbacks.cpp:1136 +#: src/FLTK/fl_callbacks.cpp:1215 src/FLTK/fl_callbacks.cpp:1623 +msgid "Show" +msgstr "Toon" + +#: src/FLTK/flgui.cpp:5578 +msgid "show/hide password" +msgstr "toon/verberg wachtwoord" + +#: src/FLTK/flgui.cpp:5582 +msgid "Type" +msgstr "Type" + +#: src/FLTK/flgui.cpp:5585 +msgid "Shoutcast" +msgstr "Shoutcast" + +#: src/FLTK/flgui.cpp:5590 +msgid "Icecast" +msgstr "Icecast" + +#: src/FLTK/flgui.cpp:5595 +msgid "WebRTC" +msgstr "WebRTC" + +#: src/FLTK/flgui.cpp:5600 +msgid "Radio.co" +msgstr "Radio.co" + +#: src/FLTK/flgui.cpp:5607 src/FLTK/flgui.cpp:5709 +msgid "&Cancel" +msgstr "&Annuleer" + +#: src/FLTK/flgui.cpp:5611 src/FLTK/flgui.cpp:5713 +msgid "&ADD" +msgstr "&Voeg toe" + +#: src/FLTK/flgui.cpp:5622 +msgid "Use SSL/TLS" +msgstr "Gebruik SSL/TLS" + +#: src/FLTK/flgui.cpp:5625 +msgid "Revoke certificate trust" +msgstr "Intrekken vertrouwen cert" + +#: src/FLTK/flgui.cpp:5631 +msgid "Radio.co Stations" +msgstr "Radio.co Stations" + +#: src/FLTK/flgui.cpp:5634 +msgid "Get Stations" +msgstr "Krijg Stations" + +#: src/FLTK/flgui.cpp:5638 +msgid "Select all" +msgstr "Selecteer alles" + +#: src/FLTK/flgui.cpp:5642 +msgid "Deselect all" +msgstr "Deselecteer alles" + +#: src/FLTK/flgui.cpp:5646 +msgid "Use legacy Icecast protocol" +msgstr "Gebruik legacy Icecast protocol" + +#: src/FLTK/flgui.cpp:5647 +msgid "" +"Activate this if you want to use the older SOURCE protocol instead of the " +"newer PUT protocol" +msgstr "" +"Activeer dit als je de oudere SOURCE-protocol in plaats van het nieuwere PUT-" +"protocol wilt gebruiken" + +#: src/FLTK/flgui.cpp:5651 +msgid "ICE server (optional):" +msgstr "ICE server (optioneel)" + +#: src/FLTK/flgui.cpp:5654 +msgid "WebRTC (WHIP) URL:" +msgstr "WebRTC (WHIP) URL:" + +#: src/FLTK/flgui.cpp:5657 +msgid "Bearer token (optional):" +msgstr "Bearer-token (optional):" + +#: src/FLTK/flgui.cpp:5660 +msgid "Custom listener URL (optional):" +msgstr "Aangepaste luister-URL (optioneel):" + +#: src/FLTK/flgui.cpp:5664 +msgid "Custom listener mountpoint (optional):" +msgstr "Aangepast luister-koppelpunt (optioneel):" + +#: src/FLTK/flgui.cpp:5674 +msgid "The name of your new ICY-entrie" +msgstr "De naam van je nieuwe ICY-item" + +#: src/FLTK/flgui.cpp:5678 +msgid "Description:" +msgstr "Omschrijving:" + +#: src/FLTK/flgui.cpp:5682 +msgid "Genre:" +msgstr "Genre:" + +#: src/FLTK/flgui.cpp:5686 +msgid "URL:" +msgstr "URL:" + +#: src/FLTK/flgui.cpp:5690 +msgid "ICQ:" +msgstr "ICQ:" + +#: src/FLTK/flgui.cpp:5694 +msgid "IRC:" +msgstr "IRC:" + +#: src/FLTK/flgui.cpp:5698 +msgid "AIM:" +msgstr "AIM:" + +#: src/FLTK/flgui.cpp:5702 +msgid "Make server public" +msgstr "Maak server publiek" + +#: src/FLTK/flgui.cpp:5705 +msgid "Expand variables" +msgstr "Variabelen uitbreiden" + +#: src/FLTK/flgui.cpp:5706 +msgid "Activate to expand date variables in name and description" +msgstr "Activeer om datumvariabelen uit te breiden in naam en beschrijving" + +#: src/FLTK/flgui.cpp:5736 +msgid "Donate Cryptocurrency" +msgstr "Doneer Cryptocurrency" + +#: src/FLTK/flgui.cpp:5747 +msgid "Bitcoin" +msgstr "Bitcoin" + +#: src/FLTK/flgui.cpp:5752 src/FLTK/flgui.cpp:5761 src/FLTK/flgui.cpp:5770 +msgid "Copy" +msgstr "Kopiëren" + +#: src/FLTK/flgui.cpp:5756 +msgid "Litecoin" +msgstr "Litecoin" + +#: src/FLTK/flgui.cpp:5765 +msgid "Monero" +msgstr "Monero" + +#: src/FLTK/flgui.cpp:5774 src/FLTK/flgui.cpp:6106 src/FLTK/flgui.cpp:6461 +#: src/FLTK/flgui.cpp:6669 +msgid "&Close" +msgstr "&Sluit" + +#: src/FLTK/flgui.cpp:5780 +msgid "Streaming Codec Settings" +msgstr "Streaming Codec Instellingen" + +#: src/FLTK/flgui.cpp:5792 src/FLTK/flgui.cpp:6124 +msgid "MP3" +msgstr "MP3" + +#: src/FLTK/flgui.cpp:5793 src/FLTK/flgui.cpp:6125 +msgid "Encoding Quality" +msgstr "Encodeer Kwaliteit" + +#: src/FLTK/flgui.cpp:5806 src/FLTK/flgui.cpp:6138 +msgid "Stereo Mode" +msgstr "Stereo Mode" + +#: src/FLTK/flgui.cpp:5819 src/FLTK/flgui.cpp:5949 src/FLTK/flgui.cpp:6015 +#: src/FLTK/flgui.cpp:6071 src/FLTK/flgui.cpp:6151 src/FLTK/flgui.cpp:6281 +#: src/FLTK/flgui.cpp:6334 src/FLTK/flgui.cpp:6403 +msgid "Bitrate Mode" +msgstr "Bitrate Mode" + +#: src/FLTK/flgui.cpp:5832 src/FLTK/flgui.cpp:6164 +msgid "VBR" +msgstr "VBR" + +#: src/FLTK/flgui.cpp:5835 src/FLTK/flgui.cpp:5989 src/FLTK/flgui.cpp:6167 +#: src/FLTK/flgui.cpp:6347 +msgid "Quality" +msgstr "Kwaliteit" + +#: src/FLTK/flgui.cpp:5848 src/FLTK/flgui.cpp:6180 +msgid "Min. Bitrate" +msgstr "Min. Bitrate" + +#: src/FLTK/flgui.cpp:5861 src/FLTK/flgui.cpp:6193 +msgid "Max. Bitrate" +msgstr "Max. Bitrate" + +#: src/FLTK/flgui.cpp:5874 src/FLTK/flgui.cpp:6206 +msgid "Force" +msgstr "Forceer" + +#: src/FLTK/flgui.cpp:5875 src/FLTK/flgui.cpp:6207 +msgid "Strictly enforce mininum Bitrate (-F option of the lame encoder)" +msgstr "" +"Strikt afdwingen van de minimale bitsnelheid (-F optie van de lame encoder)" + +#: src/FLTK/flgui.cpp:5881 src/FLTK/flgui.cpp:6227 +msgid "Lowpass (kHz)" +msgstr "Lowpass (kHz)" + +#: src/FLTK/flgui.cpp:5884 src/FLTK/flgui.cpp:5909 src/FLTK/flgui.cpp:6230 +#: src/FLTK/flgui.cpp:6255 +msgid "Frequency" +msgstr "Frequentie" + +#: src/FLTK/flgui.cpp:5890 src/FLTK/flgui.cpp:5915 src/FLTK/flgui.cpp:6236 +#: src/FLTK/flgui.cpp:6261 +msgid "Width" +msgstr "Breedte" + +#: src/FLTK/flgui.cpp:5906 src/FLTK/flgui.cpp:6252 +msgid "Highpass (kHz)" +msgstr "Highpass (kHz)" + +#: src/FLTK/flgui.cpp:5931 src/FLTK/flgui.cpp:6213 +msgid "Resampling" +msgstr "Hersamplen" + +#: src/FLTK/flgui.cpp:5932 src/FLTK/flgui.cpp:6214 +msgid "Resample to the selected sample rate" +msgstr "Hersamplen naar de geselecteerde samplefrequentie" + +#: src/FLTK/flgui.cpp:5947 src/FLTK/flgui.cpp:6279 +msgid "OGG" +msgstr "OGG" + +#: src/FLTK/flgui.cpp:5962 src/FLTK/flgui.cpp:6294 +msgid "VBR Quality" +msgstr "VBR Kwaliteit" + +#: src/FLTK/flgui.cpp:5975 src/FLTK/flgui.cpp:6307 +msgid "VBR min. Bitrate" +msgstr "VBR min. Bitrate" + +#: src/FLTK/flgui.cpp:5980 src/FLTK/flgui.cpp:6312 +msgid "VBR max. Bitrate" +msgstr "VBR max. Bitrate" + +#: src/FLTK/flgui.cpp:5987 src/FLTK/flgui.cpp:6319 +msgid "OPUS" +msgstr "OPUS" + +#: src/FLTK/flgui.cpp:6002 src/FLTK/flgui.cpp:6321 +msgid "Optimize for" +msgstr "Optimaliseer voor" + +#: src/FLTK/flgui.cpp:6028 src/FLTK/flgui.cpp:6360 +msgid "Max. Bandwidth" +msgstr "Max. Bandbreedte" + +#: src/FLTK/flgui.cpp:6043 src/FLTK/flgui.cpp:6375 +msgid "AAC" +msgstr "AAC" + +#: src/FLTK/flgui.cpp:6045 src/FLTK/flgui.cpp:6377 +msgid "Profile" +msgstr "Profiel" + +#: src/FLTK/flgui.cpp:6058 src/FLTK/flgui.cpp:6390 +msgid "Afterburner" +msgstr "Afterburner" + +#: src/FLTK/flgui.cpp:6086 src/FLTK/flgui.cpp:6418 +msgid "FLAC" +msgstr "FLAC" + +#: src/FLTK/flgui.cpp:6088 src/FLTK/flgui.cpp:6420 src/FLTK/flgui.cpp:6438 +msgid "Bit depth" +msgstr "Bit diepte" + +#: src/FLTK/flgui.cpp:6090 src/FLTK/flgui.cpp:6422 src/FLTK/flgui.cpp:6440 +msgid "16 bit" +msgstr "16 bit" + +#: src/FLTK/flgui.cpp:6095 src/FLTK/flgui.cpp:6427 src/FLTK/flgui.cpp:6450 +msgid "24 bit" +msgstr "24 bit" + +#: src/FLTK/flgui.cpp:6112 +msgid "Recording Codec Settings" +msgstr "Recording Codec Instellingen" + +#: src/FLTK/flgui.cpp:6436 +msgid "WAV" +msgstr "WAV" + +#: src/FLTK/flgui.cpp:6445 +msgid "32 bit" +msgstr "32 bit" + +#: src/FLTK/flgui.cpp:6467 +msgid "butt audio mixer" +msgstr "butt audio mixer" + +#: src/FLTK/flgui.cpp:6483 +msgid "Audio Mixer" +msgstr "Audio Mixer" + +#: src/FLTK/flgui.cpp:6486 src/FLTK/flgui.cpp:6516 src/FLTK/flgui.cpp:6546 +#: src/FLTK/flgui.cpp:6569 src/FLTK/flgui.cpp:6592 +msgid "+0.0 dB" +msgstr "+0.0 dB" + +#: src/FLTK/flgui.cpp:6491 src/FLTK/flgui.cpp:6634 +msgid "" +"Primary\n" +"Device" +msgstr "" +"Primair\n" +"Apparaat" + +#: src/FLTK/flgui.cpp:6509 src/FLTK/flgui.cpp:6510 src/FLTK/flgui.cpp:6539 +#: src/FLTK/flgui.cpp:6540 +msgid "Mute" +msgstr "Demp" + +#: src/FLTK/flgui.cpp:6521 src/FLTK/flgui.cpp:6642 +msgid "" +"Secondary\n" +"Device" +msgstr "" +"Secundair\n" +"Apparaat" + +#: src/FLTK/flgui.cpp:6551 +msgid "" +"Streaming\n" +"Gain" +msgstr "" +"Streaming\n" +"Gain" + +#: src/FLTK/flgui.cpp:6574 +msgid "" +"Recording\n" +"Gain" +msgstr "" +"Opname\n" +"Gain" + +#: src/FLTK/flgui.cpp:6597 +msgid "" +"Master\n" +"Gain" +msgstr "" +"Master\n" +"Gain" + +#: src/FLTK/flgui.cpp:6615 +msgid "" +"\n" +"Cross Fader" +msgstr "" +"\n" +"Cross Fader" + +#: src/FLTK/flgui.cpp:6638 +msgid "|" +msgstr "|" + +#: src/FLTK/flgui.cpp:6650 +msgid "Alert" +msgstr "Waarschuwing" + +#: src/FLTK/flgui.cpp:6661 +msgid "&Open the manual" +msgstr "&Open de handleiding" + +#: src/FLTK/flgui.cpp:6665 +msgid "" +"Could not find aac library.\n" +"\n" +"Please follow the instructions in the manual\n" +"for adding aac support." +msgstr "" +"Kon de aac library niet vinden.\n" +"\n" +"Bekijk de handleiding voor het\n" +"toevoegen van aac ondersteuning." + +#: src/FLTK/fl_timer_funcs.cpp:318 +#, c-format +msgid "" +"stream sent\n" +"%0.2lfMB" +msgstr "" +"gestreamd\n" +"%0.2lfMB" + +#: src/FLTK/fl_timer_funcs.cpp:323 +#, c-format +msgid "" +"stream time\n" +"%s" +msgstr "" +"streamtijd\n" +"%s" + +# Will be shown in the main display and thus +# may only contain ascii-characters. When +# in doubt just keep "Listeners". Also the +# string length should not exceed 10 +# characters. +#: src/FLTK/fl_timer_funcs.cpp:330 +#, c-format +msgid "" +"On Air\n" +"Listeners %5d" +msgstr "" +"On Air\n" +"Ingelogd %5d" + +# Will be shown in the main display and thus +# may only contain ascii-characters. When +# in doubt just keep "Listeners>". Also the +# string length should not exceed 10 +# characters. +#: src/FLTK/fl_timer_funcs.cpp:333 +#, c-format +msgid "" +"On Air\n" +"Listeners>%5d" +msgstr "" +"On Air\n" +"Ingelogd>%5d" + +# Will be shown in the main display and thus +# may only contain ascii-characters. When +# in doubt just keep "On Air" +#: src/FLTK/fl_timer_funcs.cpp:337 +#, c-format +msgid "On Air" +msgstr "On Air" + +#: src/FLTK/fl_timer_funcs.cpp:343 +#, c-format +msgid "" +"record time\n" +"%s" +msgstr "" +"opnametijd\n" +"%s" + +#: src/FLTK/fl_timer_funcs.cpp:348 +#, c-format +msgid "" +"record size\n" +"%0.2lfMB" +msgstr "" +"opnamegrootte\n" +"%0.2lfMB" + +#: src/FLTK/fl_timer_funcs.cpp:479 +#, c-format +msgid "" +"ERROR: Connection lost\n" +"reconnecting in %d seconds..." +msgstr "" +"FOUT: Verbinding verloren\n" +"Opnieuw verbinden in %d seconden..." + +#: src/FLTK/fl_timer_funcs.cpp:483 +msgid "" +"ERROR: Connection lost\n" +"reconnecting..." +msgstr "" +"FOUT: Verbinding verloren\n" +"Opnieuw verbinden..." + +#: src/FLTK/fl_timer_funcs.cpp:608 +msgid "Listeners" +msgstr "Ingelogd" + +#: src/FLTK/fl_timer_funcs.cpp:674 +msgid "" +"Could not find a file extension in current filename\n" +"Automatic file splitting is deactivated" +msgstr "" +"Kon geen bestandsextensie vinden in de huidige bestandsnaam\n" +"Automatisch splitsen van bestanden is gedeactiveerd" + +#: src/FLTK/fl_timer_funcs.cpp:704 +msgid "" +"Could not find a valid filename for next file\n" +"butt keeps recording to current file" +msgstr "" +"Kon geen geldige bestandsnaam vinden voor het volgende bestand\n" +"butt blijft opnemen naar het huidige bestand" + +#: src/FLTK/fl_timer_funcs.cpp:717 src/FLTK/fl_callbacks.cpp:1033 +#, c-format +msgid "" +"Could not open:\n" +"%s" +msgstr "" +"Kon niet openen:\n" +"%s" + +#: src/FLTK/fl_timer_funcs.cpp:721 src/port_audio.cpp:938 +msgid "Recording to:" +msgstr "Opnemen naar:" + +#: src/FLTK/fl_timer_funcs.cpp:964 +#, c-format +msgid "" +"Warning\n" +"Could not open: %s.\n" +"Will retry in 5 seconds" +msgstr "" +"Waarschuwing\n" +"Kon niet openen: %s.\n" +"nieuwe poging in 5 seconden" + +#: src/FLTK/fl_callbacks.cpp:145 +msgid "connecting" +msgstr "verbinden" + +#: src/FLTK/fl_callbacks.cpp:187 +msgid "" +"Error: No server entry found.\n" +"Please add a server in the settings-window." +msgstr "" +"Fout: Geen serverinvoer gevonden.\n" +"Voeg alsjeblieft een server toe in het instellingenvenster." + +#: src/FLTK/fl_callbacks.cpp:192 +msgid "" +"Error: ogg vorbis encoder doesn't support bitrates\n" +"lower than 48kbit" +msgstr "" +"Fout: de Ogg Vorbis-encoder ondersteunt geen bitrates\n" +"lager dan 48 kbit" + +#: src/FLTK/fl_callbacks.cpp:200 +#, c-format +msgid "Warning: %s is not supported by every Shoutcast version" +msgstr "Waarschuwing: %s wordt niet door elke Shoutcast-versie ondersteund" + +#: src/FLTK/fl_callbacks.cpp:204 +msgid "Error: FLAC is not supported by ShoutCast" +msgstr "Fout: FLAC wordt niet ondersteund door ShoutCast" + +#: src/FLTK/fl_callbacks.cpp:211 +#, c-format +msgid "Error: Radio.co supports only mp3 and aac" +msgstr "Fout: Radio.co ondersteunt alleen mp3 en aac" + +#: src/FLTK/fl_callbacks.cpp:219 +#, c-format +msgid "Error: WebRTC only supports opus" +msgstr "Fout: WebRTC ondersteunt alleen Opus" + +#: src/FLTK/fl_callbacks.cpp:226 +#, c-format +msgid "Connecting to %s via %s ..." +msgstr "Verbinden met %s via %s ..." + +#: src/FLTK/fl_callbacks.cpp:229 +#, c-format +msgid "Connecting to %s:%u ..." +msgstr "Verbinden met %s:%u ..." + +#: src/FLTK/fl_callbacks.cpp:232 +#, c-format +msgid "Connecting to %s:%u (%u) ..." +msgstr "Verbinden met %s:%u (%u) ..." + +#: src/FLTK/fl_callbacks.cpp:328 +msgid "Connection established" +msgstr "Verbinding tot stand gebracht" + +#: src/FLTK/fl_callbacks.cpp:342 src/FLTK/fl_callbacks.cpp:4275 +#: src/FLTK/fl_callbacks.cpp:4281 +msgid "no" +msgstr "nee" + +#: src/FLTK/fl_callbacks.cpp:342 src/FLTK/fl_callbacks.cpp:4275 +#: src/FLTK/fl_callbacks.cpp:4281 +msgid "yes" +msgstr "ja" + +#: src/FLTK/fl_callbacks.cpp:344 +#, c-format +msgid "Device 1:\t%s\n" +msgstr "Apparaat 1:\t%s\n" + +#: src/FLTK/fl_callbacks.cpp:345 +#, c-format +msgid "Device 2:\t%s\n" +msgstr "Apparaat 2:\t%s\n" + +#: src/FLTK/fl_callbacks.cpp:396 +#, c-format +msgid "Connected to: %s" +msgstr "Verbonden met: %s" + +#: src/FLTK/fl_callbacks.cpp:567 src/FLTK/fl_callbacks.cpp:1669 +msgid "The custom listener URL must start with http:// or https://" +msgstr "De URL moet starten met http:// of https://" + +#: src/FLTK/fl_callbacks.cpp:574 src/FLTK/fl_callbacks.cpp:1676 +msgid "" +"No mountpoint specified\n" +"Setting mountpoint to \"stream\"" +msgstr "" +"Geen Mountpoint gespecificeerd\n" +"Mountpoint instellen op \"stream\"" + +#: src/FLTK/fl_callbacks.cpp:578 src/FLTK/fl_callbacks.cpp:1680 +msgid "" +"No user specified\n" +"Setting user to \"source\"" +msgstr "" +"Geen gebruiker gespecificeerd\n" +"Gebruiker ingesteld op \"source\"" + +#: src/FLTK/fl_callbacks.cpp:586 src/FLTK/fl_callbacks.cpp:1688 +msgid "" +"Unsupported listener URL.\n" +"The listener URL must end with status-json.xsl, 7.xsl, 7.html or contain " +"stats?sid" +msgstr "" +"Ongeldige luister-URL.\n" +"De luister-URL moet eindigen op status-json.xsl, 7.xsl, 7.html of stats?sid " +"bevatten" + +#: src/FLTK/fl_callbacks.cpp:592 src/FLTK/fl_callbacks.cpp:1694 +#: src/FLTK/fl_callbacks.cpp:1857 src/FLTK/fl_callbacks.cpp:2545 +msgid "No name specified" +msgstr "Geen naam gespecificeerd" + +#: src/FLTK/fl_callbacks.cpp:597 src/FLTK/fl_callbacks.cpp:1699 +msgid "" +"The number of characters of all your server names exeeds 1000\n" +"Please reduce the number of characters of each server name" +msgstr "" +"Het aantal tekens van al je servernamen overschrijdt 1000.\n" +"Verminder het aantal tekens van elke servernaam" + +#: src/FLTK/fl_callbacks.cpp:603 src/FLTK/fl_callbacks.cpp:1705 +msgid "Newline characters and [];/\\ are not allowed within the server name" +msgstr "Regelovergangs- en [];/\\ tekens zijn niet toegestaan in de servernaam" + +#: src/FLTK/fl_callbacks.cpp:609 src/FLTK/fl_callbacks.cpp:1710 +msgid "No address specified" +msgstr "Geen adres gespecificeerd" + +#: src/FLTK/fl_callbacks.cpp:613 src/FLTK/fl_callbacks.cpp:1714 +msgid "No password specified" +msgstr "Geen wachtwoord gespecificeerd" + +#: src/FLTK/fl_callbacks.cpp:617 src/FLTK/fl_callbacks.cpp:1718 +msgid "No port specified" +msgstr "Geen poort gespecificeerd" + +#: src/FLTK/fl_callbacks.cpp:621 src/FLTK/fl_callbacks.cpp:1722 +msgid "" +"Invalid port number\n" +"The port number must be between 1 and 65535" +msgstr "" +"Ongeldig poortnummer\n" +"Het poortnummer moet tussen 1 en 65535 liggen" + +#: src/FLTK/fl_callbacks.cpp:628 src/FLTK/fl_callbacks.cpp:1729 +msgid "No WHIP URL specified" +msgstr "Geen WHIP-URL opgegeven" + +#: src/FLTK/fl_callbacks.cpp:637 src/FLTK/fl_callbacks.cpp:1740 +#: src/FLTK/fl_callbacks.cpp:2564 +msgid "Server name already exist!" +msgstr "Servernaam bestaat al!" + +#: src/FLTK/fl_callbacks.cpp:966 +msgid "stop recording?" +msgstr "stop opname?" + +#: src/FLTK/fl_callbacks.cpp:966 src/FLTK/fl_funcs.cpp:1462 +msgid "No" +msgstr "Nee" + +#: src/FLTK/fl_callbacks.cpp:966 +msgid "Yes" +msgstr "Ja" + +#: src/FLTK/fl_callbacks.cpp:1005 +msgid "No recording filename specified" +msgstr "Geen opnamebestandsnaam gespecificeerd" + +#: src/FLTK/fl_callbacks.cpp:1015 +#, c-format +msgid "%s already exists!" +msgstr "%s bestaat al!" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "overwrite" +msgstr "overschrijf" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "cancel" +msgstr "annuleer" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "append" +msgstr "toevoegen" + +#: src/FLTK/fl_callbacks.cpp:1021 +msgid "Recording canceled" +msgstr "Opname geannuleerd" + +#: src/FLTK/fl_callbacks.cpp:1090 src/FLTK/fl_funcs.cpp:1308 +msgid "Hide log" +msgstr "Verberg log" + +#: src/FLTK/fl_callbacks.cpp:1123 +msgid "Add Server" +msgstr "Voeg Server toe" + +#: src/FLTK/fl_callbacks.cpp:1176 +msgid "Edit Server" +msgstr "Bewerk Server" + +#: src/FLTK/fl_callbacks.cpp:1181 +msgid "Radio.co stations cannot be edited." +msgstr "Radio.co stations kunnen niet worden bewerkt." + +#: src/FLTK/fl_callbacks.cpp:1267 +msgid "Add Server Infos" +msgstr "Voeg Serverinfo toe" + +#: src/FLTK/fl_callbacks.cpp:1302 +msgid "Song update failed: WebRTC does not support song names" +msgstr "Nummerupdate mislukt: WebRTC ondersteunt geen Artiest - Titel data" + +#: src/FLTK/fl_callbacks.cpp:1345 +#, c-format +msgid "" +"Updated songname to:\n" +"%s\n" +msgstr "" +"Update Artiest - Titel naar:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:1354 +msgid "Updating songname failed" +msgstr "Updaten Artiest - Titel mislukt" + +#: src/FLTK/fl_callbacks.cpp:1428 +#, c-format +msgid "Audio buffer has been set to %d ms" +msgstr "Audio buffer ingesteld op %d ms" + +#: src/FLTK/fl_callbacks.cpp:1592 +msgid "" +"butt will open Radio.co in a new browser window.\n" +"\n" +"Login to Radio.co and allow butt access to your account." +msgstr "" +"butt opent Radio.co in een nieuw browservenster.\n" +"\n" +"Log in op Radio.co en sta butt toe toegang tot je account te krijgen." + +#: src/FLTK/fl_callbacks.cpp:1618 +msgid "Hide" +msgstr "Verberg" + +#: src/FLTK/fl_callbacks.cpp:1638 +msgid "Could not revoke trust for certificate" +msgstr "Kon geen vertrouwen intrekken voor certificaat" + +#: src/FLTK/fl_callbacks.cpp:1862 +msgid "" +"The number of characters of all your icy names exeeds 1000\n" +"Please reduce the count of characters of each icy name" +msgstr "" +"Het aantal tekens van al je ICY-namen overschrijdt 1000\n" +"Verminder alsjeblieft het aantal tekens van elke ICY-naam" + +#: src/FLTK/fl_callbacks.cpp:1868 src/FLTK/fl_callbacks.cpp:2557 +msgid "Newline characters and [];/\\ are not allowed within the icy name" +msgstr "Regelovergangs- en [];/\\ tekens zijn niet toegestaan in de icy-naam" + +#: src/FLTK/fl_callbacks.cpp:1877 +msgid "Icy name already exist!" +msgstr "Icy-naam bestaat al!" + +#: src/FLTK/fl_callbacks.cpp:2002 src/FLTK/fl_callbacks.cpp:2015 +#: src/FLTK/fl_callbacks.cpp:2029 src/FLTK/fl_callbacks.cpp:2044 +#: src/FLTK/fl_callbacks.cpp:2233 src/FLTK/fl_callbacks.cpp:2246 +#: src/FLTK/fl_callbacks.cpp:2260 src/FLTK/fl_callbacks.cpp:2275 +#: src/FLTK/fl_callbacks.cpp:2290 +msgid "" +"Warning:\n" +"The stream Sample-/Bitrate combination is invalid" +msgstr "" +"Waarschuwing:\n" +"De stream Sample-/Bitrate combinatie is ongeldig" + +#: src/FLTK/fl_callbacks.cpp:2008 src/FLTK/fl_callbacks.cpp:2021 +#: src/FLTK/fl_callbacks.cpp:2035 src/FLTK/fl_callbacks.cpp:2050 +msgid "The previous values have been set\n" +msgstr "De vorige waarden zijn ingesteld\n" + +#: src/FLTK/fl_callbacks.cpp:2056 +#, c-format +msgid "Stream bitrate set to: %dk" +msgstr "Stream bitrate ingesteld op: %dk" + +#: src/FLTK/fl_callbacks.cpp:2142 src/FLTK/fl_callbacks.cpp:2155 +#: src/FLTK/fl_callbacks.cpp:2169 src/FLTK/fl_callbacks.cpp:2184 +#: src/FLTK/fl_callbacks.cpp:2313 src/FLTK/fl_callbacks.cpp:2326 +#: src/FLTK/fl_callbacks.cpp:2340 src/FLTK/fl_callbacks.cpp:2355 +#: src/FLTK/fl_callbacks.cpp:2369 +msgid "" +"Warning:\n" +"The record Sample-/Bitrate combination is invalid" +msgstr "" +"Waarschuwing:\n" +"De record Sample-/Bitrate combinatie is ongeldig" + +#: src/FLTK/fl_callbacks.cpp:2148 src/FLTK/fl_callbacks.cpp:2161 +#: src/FLTK/fl_callbacks.cpp:2175 src/FLTK/fl_callbacks.cpp:2190 +#: src/FLTK/fl_callbacks.cpp:2239 src/FLTK/fl_callbacks.cpp:2252 +#: src/FLTK/fl_callbacks.cpp:2266 src/FLTK/fl_callbacks.cpp:2281 +#: src/FLTK/fl_callbacks.cpp:2296 src/FLTK/fl_callbacks.cpp:2319 +#: src/FLTK/fl_callbacks.cpp:2332 src/FLTK/fl_callbacks.cpp:2346 +#: src/FLTK/fl_callbacks.cpp:2361 src/FLTK/fl_callbacks.cpp:2375 +msgid "The previous values have been set" +msgstr "De vorige waarden zijn ingesteld" + +#: src/FLTK/fl_callbacks.cpp:2196 +#, c-format +msgid "Record bitrate set to: %dk" +msgstr "Opname bitrate ingesteld op: %dk" + +#: src/FLTK/fl_callbacks.cpp:2383 +#, c-format +msgid "Samplerate set to: %dHz" +msgstr "Samplerate ingesteld op: %dHz" + +#: src/FLTK/fl_callbacks.cpp:2449 +msgid "Channels set to: stereo" +msgstr "Kanalen ingesteld op: stereo" + +#: src/FLTK/fl_callbacks.cpp:2512 +msgid "Channels set to: mono" +msgstr "Kanalen ingesteld op: mono" + +#: src/FLTK/fl_callbacks.cpp:2551 +msgid "" +"The number of characters of all your icy names exeeds 1000\n" +"Please reduce the number of characters of each icy name" +msgstr "" +"Het aantal tekens van al je ICY-namen overschrijdt 1000\n" +"Verminder alsjeblieft het aantal tekens van elke ICY-naam" + +#: src/FLTK/fl_callbacks.cpp:2659 +msgid "Edit Server Infos" +msgstr "Bewerk Serverinfo" + +#: src/FLTK/fl_callbacks.cpp:2696 src/FLTK/fl_callbacks.cpp:2749 +msgid "" +"Primary and secondary audio device are both ASIO devices.\n" +"You can not use two ASIO devices at the same time.\n" +"Please select a different device.\n" +msgstr "" +"Primair en secundair audiotoestel zijn beide ASIO-apparaten.\n" +"Je kunt niet tegelijkertijd twee ASIO-apparaten gebruiken.\n" +"Selecteer alsjeblieft een ander apparaat.\n" + +#: src/FLTK/fl_callbacks.cpp:2717 src/FLTK/fl_callbacks.cpp:4155 +msgid "" +"butt could not open selected audio device.\n" +"Please try another device.\n" +msgstr "" +"butt kon het geselecteerde audioapparaat niet openen.\n" +"Probeer alsjeblieft een ander apparaat.\n" + +#: src/FLTK/fl_callbacks.cpp:2732 +#, c-format +msgid "" +"Primary device:\n" +"%s\n" +msgstr "" +"Primair apparaat:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:2769 +msgid "" +"butt could not open secondary audio device.\n" +"Please try another device.\n" +msgstr "" +"butt kon het secundaire audioapparaat niet openen.\n" +"Probeer alsjeblieft een ander apparaat.\n" + +#: src/FLTK/fl_callbacks.cpp:2783 +#, c-format +msgid "" +"Secondary device:\n" +"%s\n" +msgstr "" +"Secundair apparaat:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:2894 src/FLTK/fl_callbacks.cpp:3072 +msgid "" +"MP3 encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"MP3 encoder ondersteund de huidige\n" +"Sample-/Bitrate combinatie niet" + +#: src/FLTK/fl_callbacks.cpp:2915 +msgid "Stream codec set to mp3" +msgstr "Stream codec ingesteld op mp3" + +#: src/FLTK/fl_callbacks.cpp:2927 src/FLTK/fl_callbacks.cpp:3112 +msgid "" +"OGG Vorbis encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"OGG Vorbis encoder ondersteund huidige\n" +"Sample-/Bitrate combinatie niet" + +#: src/FLTK/fl_callbacks.cpp:2948 +msgid "Stream codec set to ogg/vorbis" +msgstr "Stream codec ingesteld op ogg/vorbis" + +#: src/FLTK/fl_callbacks.cpp:2959 src/FLTK/fl_callbacks.cpp:3151 +msgid "" +"Opus encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"Opus encoder ondersteund huidige\n" +"Sample-/Bitrate combinatie niet" + +#: src/FLTK/fl_callbacks.cpp:2979 +msgid "Stream codec set to opus" +msgstr "Stream codec ingesteld op opus" + +#: src/FLTK/fl_callbacks.cpp:3011 src/FLTK/fl_callbacks.cpp:3213 +msgid "" +"AAC encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"AAC encoder ondersteund huidige\n" +"Sample-/Bitrate combinatie niet" + +#: src/FLTK/fl_callbacks.cpp:3032 +msgid "Stream codec set to aac" +msgstr "Stream codec ingesteld op aac" + +#: src/FLTK/fl_callbacks.cpp:3042 src/FLTK/fl_callbacks.cpp:3252 +msgid "ERROR: While initializing flac settings" +msgstr "FOUT: Tijdens initialisatie flac instellingen" + +#: src/FLTK/fl_callbacks.cpp:3060 +msgid "Stream codec set to flac" +msgstr "Stream codec ingesteld op flac" + +#: src/FLTK/fl_callbacks.cpp:3101 +msgid "Record codec set to mp3" +msgstr "Opname codec ingesteld op mp3" + +#: src/FLTK/fl_callbacks.cpp:3140 +msgid "Record codec set to ogg/vorbis" +msgstr "Opname codec ingesteld op ogg/vorbis" + +#: src/FLTK/fl_callbacks.cpp:3179 +msgid "Record codec set to opus" +msgstr "Opname codec ingesteld op opus" + +#: src/FLTK/fl_callbacks.cpp:3242 +msgid "Record codec set to aac" +msgstr "Opname codec ingesteld op aac" + +#: src/FLTK/fl_callbacks.cpp:3278 +msgid "Record codec set to flac" +msgstr "Opname codec ingesteld op flac" + +#: src/FLTK/fl_callbacks.cpp:3294 +msgid "Record codec set to wav" +msgstr "Opname codec ingesteld op wav" + +#: src/FLTK/fl_callbacks.cpp:3329 +msgid "Select certificate file..." +msgstr "Selecteer certificaat bestand..." + +#: src/FLTK/fl_callbacks.cpp:3334 src/FLTK/fl_callbacks.cpp:3355 +#: src/FLTK/fl_callbacks.cpp:3466 src/FLTK/fl_callbacks.cpp:3556 +#: src/FLTK/fl_callbacks.cpp:4109 src/FLTK/fl_callbacks.cpp:4133 +#: src/FLTK/fl_callbacks.cpp:4257 +#, c-format +msgid "ERROR: %s" +msgstr "FOUT: %s" + +#: src/FLTK/fl_callbacks.cpp:3347 +msgid "Select certificate directory..." +msgstr "Selecteer certificaat map..." + +#: src/FLTK/fl_callbacks.cpp:3458 +msgid "Record to..." +msgstr "Opname naar..." + +#: src/FLTK/fl_callbacks.cpp:3483 +msgid "File splitting only works if recording is active." +msgstr "Splitten van bestand werkt alleen als opname actief is." + +#: src/FLTK/fl_callbacks.cpp:3552 +msgid "Select Songfile" +msgstr "Selecteer Artiest - Titel bestand" + +#: src/FLTK/fl_callbacks.cpp:3657 +msgid "Gain control is disabled. Enable in Settings->GUI" +msgstr "Gain control is uitgeschakeld. Schakel in in Instellingen->GUI" + +#: src/FLTK/fl_callbacks.cpp:3718 +msgid "select background color" +msgstr "selecteer achtergrondkleur" + +#: src/FLTK/fl_callbacks.cpp:3728 +msgid "select text color" +msgstr "selecteer tekst kleur" + +#: src/FLTK/fl_callbacks.cpp:3761 src/FLTK/fl_callbacks.cpp:3765 +#: src/FLTK/fl_callbacks.cpp:3774 src/FLTK/fl_callbacks.cpp:3778 +msgid "Value must be a number between -54 and 0" +msgstr "Waarde moet een nummer zijn tussen de -54 en 0" + +#: src/FLTK/fl_callbacks.cpp:3788 +msgid "Please restart butt to apply new language." +msgstr "Herstart butt om de nieuwe taal in te stellen." + +#: src/FLTK/fl_callbacks.cpp:3867 src/FLTK/fl_callbacks.cpp:3872 +#: src/FLTK/fl_callbacks.cpp:3882 src/FLTK/fl_callbacks.cpp:3887 +msgid "Value must be a number between -90.0 and 0" +msgstr "Waarde moet een nummer zijn tussen de -90.0 en 0" + +#: src/FLTK/fl_callbacks.cpp:4082 +msgid "Recording volume" +msgstr "Opname volume" + +#: src/FLTK/fl_callbacks.cpp:4103 +msgid "Export to..." +msgstr "Exporteer naar..." + +#: src/FLTK/fl_callbacks.cpp:4146 +#, c-format +msgid "Could not import config %s" +msgstr "Kon config %s niet importeren" + +#: src/FLTK/fl_callbacks.cpp:4160 +#, c-format +msgid "Config imported %s" +msgstr "Config %s geïmporteerd" + +#: src/FLTK/fl_callbacks.cpp:4234 +msgid "" +"Could not get update information.\n" +"Reason: Network error" +msgstr "" +"Kon geen update informatie ontvangen.\n" +"Reden: Netwerk fout" + +#: src/FLTK/fl_callbacks.cpp:4237 +msgid "" +"Could not get update information.\n" +"Reason: Unknown answer from server" +msgstr "" +"Kon geen update informatie ontvangen.\n" +"Reden: Onbekend antwoord van de server" + +#: src/FLTK/fl_callbacks.cpp:4240 +msgid "You have the latest version!" +msgstr "Je hebt de laatste versie!" + +#: src/FLTK/fl_callbacks.cpp:4243 +msgid "" +"Could not get update information.\n" +"Reason: Unknown" +msgstr "" +"Kon geen update informatie ontvangen.\n" +"Reden: Onbekend" + +#: src/FLTK/fl_callbacks.cpp:4251 +msgid "Select logfile..." +msgstr "Selecteer logbestand..." + +#: src/FLTK/fl_callbacks.cpp:4273 +msgid "" +"butt is currently streaming.\n" +"Do you really want to close butt now?" +msgstr "" +"butt is momenteel aan het streamen.\n" +"Weet je zeker dat je butt wil afsluiten?" + +#: src/FLTK/fl_callbacks.cpp:4279 +msgid "" +"butt is currently recording.\n" +"Do you really want to close butt now?" +msgstr "" +"butt is momenteel aan het opnemen.\n" +"Weet je zeker dat je butt wil afsluiten?" + +#: src/FLTK/fl_callbacks.cpp:4354 +msgid "The URL must start with either http:// or https://" +msgstr "De URL moet starten met http:// of https://" + +#: src/FLTK/fl_callbacks.cpp:4366 +msgid "Value must be a number between 1 and 1000" +msgstr "Waarde moet een nummer zijn tussen de 1 en 1000" + +#: src/FLTK/fl_callbacks.cpp:5228 src/FLTK/fl_callbacks.cpp:5263 +#: src/FLTK/fl_callbacks.cpp:5298 src/FLTK/fl_callbacks.cpp:5333 +#: src/FLTK/fl_callbacks.cpp:5368 src/FLTK/fl_callbacks.cpp:5859 +#: src/FLTK/fl_callbacks.cpp:5894 src/FLTK/fl_callbacks.cpp:5929 +#: src/FLTK/fl_callbacks.cpp:5964 src/FLTK/fl_callbacks.cpp:5999 +msgid "The encoder could not be initialized with the provided parameters." +msgstr "" +"De encoder kon niet worden geïnitialiseerd met de opgegeven parameters." + +#: src/FLTK/fl_callbacks.cpp:5246 src/FLTK/fl_callbacks.cpp:5877 +msgid "The value must be between 0.001 kHz and 50 kHz" +msgstr "De waarde moet tussen 0,001 kHz en 50 kHz liggen" + +#: src/FLTK/fl_callbacks.cpp:5281 src/FLTK/fl_callbacks.cpp:5316 +#: src/FLTK/fl_callbacks.cpp:5351 src/FLTK/fl_callbacks.cpp:5912 +#: src/FLTK/fl_callbacks.cpp:5947 src/FLTK/fl_callbacks.cpp:5982 +msgid "The value must be between 0.001 kHz and 16 kHz" +msgstr "De waarde moet tussen 0,001 kHz en 16 kHz liggen" + +#: src/FLTK/fl_callbacks.cpp:6328 +msgid "MIDI device could not be opened." +msgstr "MIDI apparaat kon niet worden geopend." + +#: src/FLTK/fl_callbacks.cpp:6334 +#, c-format +msgid "" +"MIDI device:\n" +"%s\n" +msgstr "" +"MIDI apparaat:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:6339 +msgid "MIDI device could not be started." +msgstr "MIDI apparaat kon niet worden gestart." + +#: src/FLTK/fl_callbacks.cpp:6344 +msgid "MIDI support disabled\n" +msgstr "MIDI ondersteuning uitgeschakeld\n" + +#: src/FLTK/fl_callbacks.cpp:6406 +msgid "The CC value must be between 0 and 127" +msgstr "De CC waarde moet tussen de 0 en 127 zijn" + +#: src/FLTK/fl_callbacks.cpp:6429 +msgid "Waiting..." +msgstr "Wachten..." + +#: src/FLTK/fl_funcs.cpp:193 +msgid "Disabled" +msgstr "Uitgeschakeld" + +#: src/FLTK/fl_funcs.cpp:335 +#, c-format +msgid "%d seconds" +msgstr "%d seconden" + +#: src/FLTK/fl_funcs.cpp:386 +msgid "Not supported on Windows" +msgstr "Niet ondersteund op Windows" + +#: src/FLTK/fl_funcs.cpp:808 +msgid "Start/Stop broadcasting" +msgstr "Start/Stop uitzenden" + +#: src/FLTK/fl_funcs.cpp:809 +msgid "Start/Stop recording" +msgstr "Start/Stop opname" + +#: src/FLTK/fl_funcs.cpp:811 +msgid "Streaming Gain" +msgstr "Streaming Gain" + +#: src/FLTK/fl_funcs.cpp:812 +msgid "Recording Gain" +msgstr "Opname Gain" + +#: src/FLTK/fl_funcs.cpp:813 +msgid "Primary Device Gain" +msgstr "Primair Apparaat Gain" + +#: src/FLTK/fl_funcs.cpp:814 +msgid "Secondary Device Gain" +msgstr "Secundair Apparaat Gain" + +#: src/FLTK/fl_funcs.cpp:815 +msgid "Cross fader" +msgstr "Crossfader" + +#: src/FLTK/fl_funcs.cpp:816 +msgid "Mute/Unmute Primary Device" +msgstr "Mute/Unmute Primair Apparaat" + +#: src/FLTK/fl_funcs.cpp:817 +msgid "Mute/Unmute Secondary Device" +msgstr "Mute/Unmute Secundair Apparaat" + +#: src/FLTK/fl_funcs.cpp:818 +msgid "Start broadcasting" +msgstr "Start uitzenden" + +#: src/FLTK/fl_funcs.cpp:819 +msgid "Stop broadcasting" +msgstr "Stop uitzenden" + +#: src/FLTK/fl_funcs.cpp:820 +msgid "Start recording" +msgstr "Start opname" + +#: src/FLTK/fl_funcs.cpp:821 +msgid "Stop recording" +msgstr "Stop opname" + +#: src/FLTK/fl_funcs.cpp:870 +msgid "dev. not supported" +msgstr "apparaat niet ondersteund" + +#: src/FLTK/fl_funcs.cpp:1087 +#, c-format +msgid "" +"Could not create recording folder:\n" +"%s\n" +"Please make sure the folder contains only valid format specifiers." +msgstr "" +"Kon opnamemap niet maken:\n" +"%s\n" +"Zorg ervoor dat de map alleen geldige formaatspecifiers bevat." + +#: src/FLTK/fl_funcs.cpp:1102 +#, c-format +msgid "Could not create recording folder %s\n" +msgstr "Kon opnamemap niet maken %s\n" + +#: src/FLTK/fl_funcs.cpp:1111 +#, c-format +msgid "" +"Could not create recording file:\n" +"%s\n" +"Please make sure the filename contains only valid format specifiers." +msgstr "" +"Kon opnamebestand niet maken:\n" +"%s\n" +"Zorg ervoor dat het bestand alleen geldige formaatspecifiers bevat." + +#: src/FLTK/fl_funcs.cpp:1157 +msgid "Could not find a valid filename" +msgstr "Kon geen geldige bestandsnaam vinden" + +#: src/FLTK/fl_funcs.cpp:1462 +msgid "TRUST" +msgstr "VERTROUW" + +#: src/icecast.cpp:90 +msgid "" +"\n" +"connect: Could not create network socket" +msgstr "" +"\n" +"Verbinding: Kon geen netwerksocket maken" + +#: src/icecast.cpp:102 +msgid "" +"\n" +"connect: Error resolving server address" +msgstr "" +"\n" +"Verbinding: Fout bij het oplossen van serveradres" + +#: src/icecast.cpp:142 +msgid "" +"\n" +"connect: SSL connection timed out. Trying again..." +msgstr "" +"\n" +"Verbinding: SSL verbindingspoging verlopen. Opnieuw proberen..." + +#: src/icecast.cpp:149 +#, c-format +msgid "" +"SSL/TLS certificate verification failed\n" +"Reason: %s\n" +"\n" +"Do you still want to trust this certificate?\n" +"Trusting will be permanent and can be revoked\n" +"in the server settings." +msgstr "" +"SSL/TLS certificaatverificatie mislukt\n" +"Reden: %s\n" +"\n" +"Wil je dit certificaat nog steeds vertrouwen?\n" +"Vertrouwen is permanent en kan ingetrokken worden\n" +"in de serverinstellingen." + +#: src/icecast.cpp:164 +#, c-format +msgid "" +"\n" +"connect: SSL connection failed\n" +"Reason: %s" +msgstr "" +"\n" +"Verbinding: SSL connectie mislukt\n" +"Reden: %s" + +#: src/icecast.cpp:320 +msgid "" +"\n" +"connect: connection timed out. Trying again..." +msgstr "" +"\n" +"Verbinding: connectie verlopen. Probeer opnieuw..." + +#: src/icecast.cpp:373 +msgid "" +"\n" +"connect: server answered with 400!\n" +msgstr "" +"\n" +"Verbinding: Server antwoorde met 400!\n" + +#: src/icecast.cpp:379 +msgid "" +"\n" +"connect: invalid user/password!\n" +msgstr "" +"\n" +"Verbinding: Ongeldige gebruiker/wachtwoord!\n" + +#: src/icecast.cpp:402 +msgid "" +"\n" +"connect: server answered with 404!\n" +msgstr "" +"\n" +"Verbinding: Server antwoorde met 404!\n" + +#: src/icecast.cpp:409 +#, c-format +msgid "" +"\n" +"connect: server answered with %d!\n" +msgstr "" +"\n" +"Verbinding: Server antworde met %d!\n" + +#: src/icecast.cpp:434 +msgid "" +"\n" +"ERROR: Opus is not supported by your\n" +"Icecast server (>=1.4.0 required)!\n" +msgstr "" +"\n" +"FOUT: Opus wordt niet ondersteund door jouw\n" +"Icecast-server (versie >=1.4.0 vereist)!\n" + +#: src/icecast.cpp:507 +msgid "" +"\n" +"update_song: could not create network socket" +msgstr "" +"\n" +"Update Artiest - Titel: Kon geen netwerksocket maken" + +#: src/icecast.cpp:511 +msgid "" +"\n" +"update_song: error resolving server address" +msgstr "" +"\n" +"Update Artiest - Titel: Fout bij oplossen serveradres" + +#: src/lame_encode.cpp:74 +#, c-format +msgid "unable to init lame params %d" +msgstr "kon lame parameters niet initialiseren %d" + +#: src/port_audio.cpp:131 +#, c-format +msgid "" +"PortAudio init failed:\n" +"%s\n" +msgstr "" +"PortAudio-initiatie mislukt\n" +"%s\n" + +#: src/port_audio.cpp:180 +msgid "ERROR: no sound device with input channels found" +msgstr "FOUT: Geen audioapparaat met ingangskanalen gevonden" + +#: src/port_audio.cpp:198 src/port_audio.cpp:289 src/port_audio.cpp:1331 +#: src/port_midi.cpp:177 +#, c-format +msgid "Error getting device Info (%d)" +msgstr "Fout bij ontvangen apparaat informatie (%d)" + +#: src/port_audio.cpp:241 +#, c-format +msgid "" +"Samplerate not supported: %dHz\n" +"Using default samplerate: %dHz" +msgstr "" +"Samplerate niet ondersteund: %dHz\n" +"Gebruikt standaard samplerate: %dHz" + +#: src/port_audio.cpp:258 src/port_audio.cpp:360 +#, c-format +msgid "PA: Format not supported: %s\n" +msgstr "PA: Formaat niet ondersteund: %s\n" + +#: src/port_audio.cpp:268 +#, c-format +msgid "error opening sound device: %s" +msgstr "fout bij openen audioapparaat: %s" + +#: src/port_audio.cpp:326 +msgid "The selected secondary audio device can not be used" +msgstr "Het geselecteerde secundaire audioapparaat kan niet worden gebruikt" + +#: src/port_audio.cpp:343 src/port_audio.cpp:1452 src/port_audio.cpp:1469 +msgid "ERROR: Could not initialize samplerate converter" +msgstr "FOUT: Kon samplerate converter niet initialiseren" + +#: src/port_audio.cpp:354 +#, c-format +msgid "Samplerate of secondary device is resampled from %dHz to %dHz\n" +msgstr "Samplerate van secundair apparaat is hersampled van %dHz naar %dHz\n" + +#: src/port_audio.cpp:381 +#, c-format +msgid "error opening secondary sound device: %s" +msgstr "fout bij openen secundair audioapparaat: %s" + +#: src/port_audio.cpp:921 +msgid "disconnected\n" +msgstr "verbroken\n" + +#: src/port_audio.cpp:949 +msgid "recording stopped" +msgstr "opname gestopt" + +#: src/port_midi.cpp:152 src/port_midi.cpp:211 src/port_midi.cpp:233 +#: src/port_midi.cpp:255 src/port_midi.cpp:282 src/port_midi.cpp:301 +#: src/port_midi.cpp:316 src/port_midi.cpp:341 src/port_midi.cpp:352 +msgid "Error: PortMidi was not initialized." +msgstr "Fout: PortMidi was niet geïnitialiseerd." + +#: src/port_midi.cpp:262 +#, c-format +msgid "" +"Error: MIDI device %s could not be opened because no MIDI devices were found." +msgstr "" +"Fout: MIDI apparaat %s kon niet worden geopend omdat er geen MIDI apparaten " +"zijn gevonden." + +#: src/port_midi.cpp:269 +#, c-format +msgid "Error: MIDI device %s could not be found." +msgstr "Fout: MIDI apparaat %s kon niet worden gevonden." + +#: src/port_midi.cpp:286 +msgid "Error: MIDI thread already active." +msgstr "Fout: MIDI thread al actief." + +#: src/port_midi.cpp:291 +msgid "Error: Could not start MIDI thread." +msgstr "Fout: Kon de MIDI thread niet starten." + +#: src/shoutcast.cpp:80 +msgid "" +"\n" +"Connect: Could not create network socket" +msgstr "" +"\n" +"Verbinding: Kon geen netwerksocket maken" + +#: src/shoutcast.cpp:92 +msgid "" +"\n" +"Connect: Error resolving server address" +msgstr "" +"\n" +"Verbinding: Fout bij het oplossen van serveradres" + +#: src/shoutcast.cpp:172 +msgid "" +"\n" +"connect: connection timed out. Trying again...\n" +msgstr "" +"\n" +"Verbinding: verbindingspoging verlopen. Opnieuw proberen...\n" + +#: src/shoutcast.cpp:189 +msgid "" +"\n" +"Connect: Invalid password!\n" +msgstr "" +"\n" +"Verbinding: Ongeldig wachtwoord!\n" + +#: src/shoutcast.cpp:238 +msgid "" +"\n" +"Update song: Could not create network socket" +msgstr "" +"\n" +"Update Artiest - Titel: Kon geen netwerksocket maken" + +#: src/shoutcast.cpp:242 +msgid "" +"\n" +"Update song: Error resolving server address" +msgstr "" +"\n" +"Update Artiest - Titel: Fout bij oplossen serveradres" + +#: src/tls.cpp:159 +msgid "check_host: could not read host name from cert" +msgstr "check_host: kon hostnaam niet lezen van cert" + +#: src/tls.cpp:194 +msgid "check_cert: No peer certificate available" +msgstr "check_cert: Geen peer certificaat beschikbaar" + +#: src/tls.cpp:207 +msgid "check_cert: X509_check_host failed" +msgstr "check_cert: X509_check_host mislukt" + +#: src/tls.cpp:213 +msgid "check_cert: check_host failed" +msgstr "check_cert: check_host mislukt" + +#: src/tls.cpp:229 +msgid "calc_cert_hash: No peer certificate available" +msgstr "calc_cert_hash: Geen peer-certificaat beschikbaar" + +#: src/tls.cpp:236 +msgid "calc_cert_hash: Hash calculation failed" +msgstr "calc_cert_hash: Hash calculatie mislukt" + +#: src/tls.cpp:305 +msgid "tls_setup: Could not set cipher list" +msgstr "tls_setup: Kon cipher lijst niet instellen" + +#: src/tls.cpp:318 +msgid "tls_setup: SSL_new failed" +msgstr "tls_setup: SSL_new mislukt" + +#: src/tls.cpp:324 +msgid "tls_setup: Could not bind socket to SSL" +msgstr "tls_setup: Kon socket niet aan SSL binden" + +#: src/tls.cpp:338 +msgid "tls_setup: SSL_connect read timeout" +msgstr "tls_setup: SSL_connectie lees time-out" + +#: src/tls.cpp:344 +msgid "tls_setup: SSL_connect write timeout" +msgstr "tls_setup: SSL_connectie schrijf time-out" + +#: src/tls.cpp:361 +msgid "tls_setup: Cert hash could not be calculated" +msgstr "tls_setup: Cert hash kon niet worden gecalculeerd" + +#: src/tls.cpp:385 +msgid "tls_send: read timeout" +msgstr "tls_send: lees time-out" + +#: src/tls.cpp:392 +msgid "tls_send: write timeout" +msgstr "tls_send: schrijf time-out" + +#: src/tls.cpp:418 +msgid "tls_recv: read timeout" +msgstr "tls_recv: lees time-out" + +#: src/tls.cpp:425 +msgid "tls_recv: write timeout" +msgstr "tls_recv: schrijf time-out" + +#~ msgid "Listeners: 99999" +#~ msgstr "Luisteraars: 99999" + +#, fuzzy +#~ msgid "Resample output" +#~ msgstr "Hersample kwaliteit" + +#, fuzzy +#~ msgid "Resample output to selected sample rate" +#~ msgstr "Selecteer ingang samplerate" + +#, c-format +#~ msgid "" +#~ "error while parsing config. Missing WebRTC WHIP URL entry for server " +#~ "\"%s\".\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "fout bij het parseren van de configuratie. Ontbrekende WebRTC WHIP URL-" +#~ "invoer voor server '%s'.\n" +#~ "butt zal starten met de standaardinstellingen" + +#, fuzzy, c-format +#~ msgid "" +#~ "error while parsing config. Missing WebRTC ICE server entry for server " +#~ "\"%s\".\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "fout bij het parsen van de configuratie. Ontbrekende poortinvoer voor " +#~ "server \"%s\".\n" +#~ "butt zal starten met de standaardinstellingen" + +#, fuzzy +#~ msgid "No ICE server specified" +#~ msgstr "Geen naam gespecificeerd" + +#~ msgid "Text color" +#~ msgstr "Tekstkleur" + +#~ msgid "Preset " +#~ msgstr "Preset " + +#~ msgid "Volume of Primary Device" +#~ msgstr "Volume van Primair Apparaat" + +#~ msgid "Volume of Secondary Device" +#~ msgstr "Volume van Secundair Apparaat" diff --git a/po/pt_BR.gmo b/po/pt_BR.gmo new file mode 100644 index 0000000..543934a Binary files /dev/null and b/po/pt_BR.gmo differ diff --git a/po/pt_BR.po b/po/pt_BR.po new file mode 100644 index 0000000..b51834d --- /dev/null +++ b/po/pt_BR.po @@ -0,0 +1,3232 @@ +# Portuguese Brazilian translation for butt-0.1.41 package. +# Copyright (C) 2022 Daniel Nöthen +# This file is distributed under the same license as the butt package. +# Bruno Di Prinzio de Oliveira , 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: butt 1.44.0\n" +"Report-Msgid-Bugs-To: butt@danielnoethen.de\n" +"POT-Creation-Date: 2025-04-19 14:55+0200\n" +"PO-Revision-Date: 2025-04-19 15:18+0200\n" +"Last-Translator: Bruno Di Prinzio de Oliveira \n" +"Language-Team: Brazilian Portuguese\n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 3.0.1\n" + +#: src/AskForMicPermission.m:20 +msgid "Microphone access" +msgstr "Acesso ao microfone" + +#: src/AskForMicPermission.m:21 +msgid "" +"butt needs access to your microphone.\n" +"\n" +"Please go to\n" +"System Preferences->Privacy & Security->Microphone\n" +"and activate the check mark next to the butt entry." +msgstr "" +"o butt precisa acessar seu microfone\n" +"\n" +"Vá para\n" +"Preferências do Sistema->Segurança e Privacidade->Microfone\n" +"e ative o checkbox próximo ao app butt." + +#: src/butt.cpp:219 +msgid "No home-directory found" +msgstr "Nenhuma pasta home foi encontrada" + +#: src/butt.cpp:230 +#, c-format +msgid "" +"The shift key was held down during startup.\n" +"Do you want to start butt with a new configuration file?\n" +"This will overwrite your existing configuration file at\n" +"%s" +msgstr "" +"A tecla shift foi mantida pressionada durante a inicialização.\n" +"Deseja iniciar o butt com um novo arquivo de configuração?\n" +"Isso irá sobrescrever seu arquivo de configuração atual em\n" +"%s" + +#: src/butt.cpp:233 +msgid "Start with old" +msgstr "Iniciar com antigo" + +#: src/butt.cpp:233 +msgid "Start with new" +msgstr "Iniciar com novo" + +#: src/butt.cpp:236 src/butt.cpp:253 +#, c-format +msgid "" +"Could not create config %s\n" +"butt is going to close now" +msgstr "" +"Impossível criar a configuração %s\n" +"o butt será fechado agora" + +#: src/butt.cpp:242 +#, c-format +msgid "Reading config %s\n" +msgstr "Lendo configuração %s\n" + +#: src/butt.cpp:250 +#, c-format +msgid "Could not find config %s\n" +msgstr "Impossível encontrar a configuração %s\n" + +#: src/butt.cpp:257 +#, c-format +msgid "" +"butt created a default config at\n" +"%s\n" +msgstr "" +"butt criou um arquivo de configuração padrão em\n" +"%s\n" + +#: src/butt.cpp:265 +msgid "" +"Could not find any audio device with input channels.\n" +"butt requires at least one audio device with input channels in order to " +"work.\n" +"This can either be a built-in audio device, an external audio device or a " +"virtual audio device.\n" +"\n" +"butt is going to close now." +msgstr "" +"Não foi possível encontrar um dispositivo de áudio com canais de entrada.\n" +"O butt requer ao menos um dispositivo de áudio com canais de entrada para " +"funcionar.\n" +"Pode ser um dispositivo de áudio integrado, externo ou virtual.\n" +"\n" +"butt irá fechar agora." + +#: src/butt.cpp:358 +#, c-format +msgid "Illegal argument: Threshold must be a non-negative number\n" +msgstr "" +"Argumento inválido: Limiar deve ser um número positivo\n" +"\n" + +#: src/butt.cpp:382 +#, c-format +msgid "%c threshold set to %0.1f\n" +msgstr "%c limiar setado para %0.1f\n" + +#: src/butt.cpp:464 +#, c-format +msgid "Illegal argument: Port must be a number between 1023 and 65535\n" +msgstr "Argumento inválido: Porta deve ser um número entre 1023 e 65535\n" + +#: src/butt.cpp:472 src/butt.cpp:482 src/butt.cpp:489 src/butt.cpp:496 +#: src/butt.cpp:503 src/butt.cpp:510 src/butt.cpp:521 src/butt.cpp:540 +#: src/butt.cpp:550 src/butt.cpp:597 +#, c-format +msgid "" +"Warning: You may only pass one control option. Option -%c has been ignored.\n" +msgstr "" +"Aviso: Deve-se especificar só uma opção de controle. Opção -%c foi " +"ignorada.\n" + +#: src/butt.cpp:559 +#, c-format +msgid "" +"\n" +"Options:\n" +"-h\tPrint this help text\n" +"-v\tPrint version information\n" +msgstr "" +"\n" +"Opções:\n" +"-h\tExibir este texto de ajuda\n" +"-v\tExibir informações da versão\n" + +#: src/butt.cpp:563 +#, c-format +msgid "" +"\n" +"Options for operating mode:\n" +"-c\tPath to configuration file\n" +"-L\tPrint available audio devices\n" +"-A\tCommand server will be accessible from your network/internet (default: " +"localhost only)\n" +"-U\tCommand server will use UDP instead of TCP\n" +"-x\tDo not start a command server\n" +"-p\tPort where the command server shall listen to (default: 1256)\n" +msgstr "" +"\n" +"Opções para modo de operação\n" +"-c\tCaminho para o arquivo de configuração\n" +"-L\tImprimir dispositivos de áudio disponíveis\n" +"-A\tServidor de comando será acessível de sua rede/internet (padrão: somente " +"localhost)\n" +"-U\tServidor de comando usará UDP em vez de TCP\n" +"-x\tNão iniciar um servidor de comando\n" +"-p\tPorta em que o servidor de comando deve ouvir (padrão: 1256)\n" + +#: src/butt.cpp:572 +#, c-format +msgid "" +"\n" +"Options for control mode:\n" +"-s\tConnect to streaming server\n" +"-d\tDisconnect from streaming server\n" +"-r\tStart recording\n" +"-t\tStop recording\n" +"-n\tSplit recording\n" +"-q\tQuit butt\n" +"-u\tupdate song name\n" +"-S\tRequest status\n" +"-M\tSet streaming signal threshold (seconds)\n" +"-m\tSet streaming silence threshold (seconds)\n" +"-O\tSet recording signal threshold (seconds)\n" +"-o\tSet recording silence threshold (seconds)\n" +"-U\tConnect via UDP instead of TCP\n" +"-a\tAddress of the butt instance to be controlled (default: 127.0.0.1)\n" +"-p\tPort of the butt instance to be controlled (default: 1256)\n" +msgstr "" +"\n" +"Opções para o modo de controle:\n" +"-s\tConectar ao servidor de transmissão\n" +"-d\tDesconectar do servidor de transmissão\n" +"-r\tIniciar gravação\n" +"-t\tParar gravação\n" +"-n\tDividir gravação\n" +"-q\tSair do butt\n" +"-u\tAtualizar nome da música\n" +"-S\tSolicitar status\n" +"-M\tDefinir limiar do sinal de transmissão (segundos)\n" +"-m\tDefinir limiar de silêncio da transmissão (segundos)\n" +"-O\tDefinir limiar do sinal de gravação (segundos)\n" +"-o\tDefinir limiar de silêncio da gravação (segundos)\n" +"-U\tConectar via UDP em vez de TCP\n" +"-a\tEndereço da instância do butt a ser controlada (padrão: 127.0.0.1)\n" +"-p\tPorta da instância do butt a ser controlada (padrão: 1256)\n" + +#: src/butt.cpp:591 +#, c-format +msgid "" +"Illegal option -%c.\n" +"Type butt -h to get a list of supported options.\n" +msgstr "" +"Opção inválida -%c.\n" +"Digite butt -h para obter a lista de opções suportada.\n" + +#: src/butt.cpp:603 +#, c-format +msgid "Option -%c requires an argument\n" +msgstr "Opção -%c requer um argumento\n" + +#: src/butt.cpp:607 +#, c-format +msgid "Command line parsing failed\n" +msgstr "Análise de linha de comando falhou\n" + +#: src/butt.cpp:630 +#, c-format +msgid "No butt instance running on %s at port %d\n" +msgstr "Nenhuma instância do butt rodando em %s na porta %d\n" + +#: src/butt.cpp:635 +#, c-format +msgid "Error while sending command\n" +msgstr "Erro ao enviar comando\n" + +#: src/butt.cpp:640 +#, c-format +msgid "Error: Did not receive response packet\n" +msgstr "Erro: Pacote de resposta não recebido\n" + +#: src/butt.cpp:653 +#, c-format +msgid "Error: You may only request one status packet per second\n" +msgstr "Erro: Deve-se solicitar apenas um pacote de status por segundo\n" + +#: src/butt.cpp:657 +#, c-format +msgid "Error: Did not receive status packet (UDP server not running?)\n" +msgstr "Erro: Pacote de status não recebido (O servidor UDP está parado?)\n" + +#: src/butt.cpp:661 +#, c-format +msgid "Network error while receiving status packet: %d\n" +msgstr "Erro de rede ao receber pacote de status %d\n" + +#: src/butt.cpp:665 +#, c-format +msgid "Error: Client and server versions do not match\n" +msgstr "Erro: Versões de cliente e servidor não batem\n" + +#: src/butt.cpp:676 +#, c-format +msgid "" +"connected: %d\n" +"connecting: %d\n" +"recording: %d\n" +"signal present: %d\n" +"signal absent: %d\n" +msgstr "" +"conectado: %d\n" +"conectando: %d\n" +"gravando: %d\n" +"sinal presente: %d\n" +"sinal ausente: %d\n" + +#: src/butt.cpp:681 +#, c-format +msgid "stream seconds: %lu\n" +msgstr "segundos de stream: %lu\n" + +#: src/butt.cpp:682 +#, c-format +msgid "stream kBytes: %lu\n" +msgstr "kBytes de stream: %lu\n" + +#: src/butt.cpp:683 +#, c-format +msgid "record seconds: %lu\n" +msgstr "segundos de gravação: %lu\n" + +#: src/butt.cpp:684 +#, c-format +msgid "record kBytes: %lu\n" +msgstr "kBytes de gravação: %lu\n" + +#: src/butt.cpp:685 +#, c-format +msgid "volume left: %0.1f\n" +msgstr "volume esquerda: %0.1f\n" + +#: src/butt.cpp:686 +#, c-format +msgid "volume right: %0.1f\n" +msgstr "volume direita: %0.1f\n" + +#: src/butt.cpp:687 +#, c-format +msgid "song: %s\n" +msgstr "música: %s\n" + +#: src/butt.cpp:688 +#, c-format +msgid "record path: %s\n" +msgstr "caminho de gravação: %s\n" + +#: src/butt.cpp:689 +#, c-format +msgid "listeners: %d\n" +msgstr "ouvintes: %d\n" + +#: src/butt.cpp:703 +msgid "" +"The control key was held down during startup.\n" +"butt will start without opening an audio device.\n" +"Please select your preferred audio device in settings->audio" +msgstr "" +"A tecla control foi mantida pressionada durante início.\n" +"butt começará sem abrir um dispositivo de áudio.\n" +"Favor selecionar seu dispositivo de áudio preferido em configs->áudio" + +#: src/butt.cpp:712 +msgid "" +"PortAudio init failed\n" +"butt is going to close now" +msgstr "" +"Inicialização do PortAudio falhou\n" +"butt será fechado agora" + +#: src/butt.cpp:747 src/FLTK/fl_timer_funcs.cpp:476 +#: src/FLTK/fl_callbacks.cpp:123 src/FLTK/fl_callbacks.cpp:899 +#: src/FLTK/fl_callbacks.cpp:977 src/FLTK/fl_funcs.cpp:1047 +msgid "idle" +msgstr "ocioso" + +#: src/butt.cpp:780 +#, c-format +msgid "" +"Starting %s\n" +"Written by Daniel Nöthen\n" +"iPhone/iPad client: https://izicast.de\n" +"Donate: paypal@danielnoethen.de\n" +msgstr "" +"Iniciando %s\n" +"Escrito por Daniel Nöthen\n" +"Cliente iPhone/iPad: https://izicast.de\n" +"Doação: paypal@danielnoethen.de\n" + +#: src/butt.cpp:792 src/butt.cpp:793 src/cfg.cpp:577 src/port_audio.cpp:1314 +#: src/port_audio.cpp:1315 +msgid "Default PCM device (default)" +msgstr "Dispositivo PCM padrão (padrão)" + +#: src/butt.cpp:796 src/butt.cpp:797 src/cfg.cpp:578 +#: src/FLTK/fl_callbacks.cpp:2820 src/FLTK/fl_funcs.cpp:227 +msgid "None" +msgstr "Nenhum" + +#: src/butt.cpp:800 +msgid "" +"Could not open audio device.\n" +"Please select your preferred audio device in settings->audio" +msgstr "" +"Impossível abrir o dispositivo de áudio.\n" +"Favor selecionar seu dispositivo de áudio preferido em configs->áudio" + +#: src/butt.cpp:803 +msgid "" +"butt could not open previously used audio device.\n" +"The system default audio device will be used.\n" +msgstr "" +"butt não conseguiu abrir o dispositivo de áudio usado anteriormente.\n" +"O dispositivo de áudio padrão do sistema será usado.\n" + +#: src/butt.cpp:830 +#, c-format +msgid "Command server listening on port %d\n" +msgstr "Servidor de comando ouvindo na porta %d\n" + +#: src/butt.cpp:837 +#, c-format +msgid "Warning: could not start command server on port %d\n" +msgstr "Aviso: impossível iniciar o servidor de comando na porta %d\n" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:4225 +#, c-format +msgid "" +"New version available: %s\n" +"You have version %s" +msgstr "" +"Nova versão disponível: %s\n" +"Você possui a versão %s" + +#: src/butt.cpp:853 +msgid "Don't ask again" +msgstr "Não perguntar novamente" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:1594 +#: src/FLTK/fl_callbacks.cpp:4225 +msgid "Cancel" +msgstr "Cancelar" + +#: src/butt.cpp:853 src/FLTK/fl_callbacks.cpp:4225 +msgid "Get new version" +msgstr "Obter nova versão" + +#: src/butt.cpp:874 +#, c-format +msgid "Could not initialize PortMidi: %s" +msgstr "Impossível iniciar PortMidi: %s" + +#: src/butt.cpp:902 +msgid "butt was built without WebRTC support" +msgstr "butt foi compilado sem suporte ao WebRTC" + +#: src/cfg.cpp:55 +#, c-format +msgid "Could not write to file: %s" +msgstr "Não foi possível escrever no arquivo: %s" + +#: src/cfg.cpp:550 +#, c-format +msgid "Config written to %s" +msgstr "Configuração escrita em %s" + +#: src/cfg.cpp:674 +msgid "" +"error while parsing config. Missing main/server entry.\n" +"butt will start with default settings" +msgstr "" +"erro ao analisar o config. Falta a entrada main/server.\n" +"O butt irá iniciar com as configurações padrão" + +#: src/cfg.cpp:680 +msgid "" +"error while parsing config. Missing main/srv_ent entry.\n" +"butt will start with default settings" +msgstr "" +"erro ao analisar o config. Falta a entrada main/srv_ent.\n" +"O butt irá iniciar com as configurações padrão" + +#: src/cfg.cpp:699 +#, c-format +msgid "" +"error while parsing config. Missing type entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"erro ao analisar o config. Falta a entrada de tipo para o servidor \"%s\".\n" +"O butt irá iniciar com as configurações padrão" + +#: src/cfg.cpp:707 +#, c-format +msgid "" +"error while parsing config. Missing address entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"erro ao analisar o config. Falta a entrada de endereço para o servidor " +"\"%s\".\n" +"O butt irá iniciar com as configurações padrão" + +#: src/cfg.cpp:716 +#, c-format +msgid "" +"error while parsing config. Missing port entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"erro ao analisar o config. Falta a entrada da porta do servidor \"%s\".\n" +"O butt irá iniciar com as configurações padrão" + +#: src/cfg.cpp:725 +#, c-format +msgid "" +"error while parsing config. Missing password entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"erro ao analisar o config. Falta a entrada da senha para o servidor \"%s\".\n" +"O butt irá iniciar com as configurações padrão" + +#: src/cfg.cpp:734 +#, c-format +msgid "" +"error while parsing config. Missing mount entry for server \"%s\".\n" +"butt will start with default settings" +msgstr "" +"erro ao analisar o config. Falta a entrada de montagem para o servidor " +"\"%s\".\n" +"O butt irá iniciar com as configurações padrão" + +#: src/cfg.cpp:790 +msgid "" +"error while parsing config. Missing main/icy entry.\n" +"butt will start with default settings" +msgstr "" +"erro ao analisar o config. Falta a entrada main/icy.\n" +"O butt irá iniciar com as configurações padrão" + +#: src/cfg.cpp:795 +msgid "" +"error while parsing config. Missing main/icy_ent entry.\n" +"butt will start with default settings" +msgstr "" +"erro ao analisar o config. Falta a entrada main/icy_ent.\n" +"O butt irá iniciar com as configurações padrão" + +#: src/cfg.cpp:821 +#, c-format +msgid "" +"error while parsing config. Missing pub entry for icy \"%s\".\n" +"butt will start with default settings" +msgstr "" +"erro ao analisar o config. Falta a entrada pub para o icy \"%s\".\n" +"O butt irá iniciar com as configurações padrão" + +#: src/FLTK/flgui.cpp:3088 +msgid "Bitcoin address has been copied to clipboard." +msgstr "O endereço do Bitcoin foi copiado para a área de transferência." + +#: src/FLTK/flgui.cpp:3099 +msgid "Litecoin address has been copied to clipboard." +msgstr "O endereço do Litecoin foi copiado para a área de transferência." + +#: src/FLTK/flgui.cpp:3110 +msgid "Monero address has been copied to clipboard." +msgstr "O endereço do Monero foi copiado para a área de transferência." + +#: src/FLTK/flgui.cpp:4041 +msgid "press left mouse to toggle lcd info" +msgstr "pressione o botão esquerdo do mouse para trocar a informação do LCD" + +#: src/FLTK/flgui.cpp:4053 src/FLTK/fl_callbacks.cpp:4078 +msgid "Streaming volume" +msgstr "Volume da transmissão" + +#: src/FLTK/flgui.cpp:4057 +msgid "Mixer" +msgstr "Mixer" + +#: src/FLTK/flgui.cpp:4058 +msgid "show/hide mixer window" +msgstr "exibir/ocultar janela de mixagem" + +#: src/FLTK/flgui.cpp:4065 +msgid "@circle" +msgstr "@circle" + +#: src/FLTK/flgui.cpp:4066 +msgid "start/stop recording" +msgstr "iniciar/parar gravação" + +#: src/FLTK/flgui.cpp:4077 +msgid "@square" +msgstr "@square" + +#: src/FLTK/flgui.cpp:4078 +msgid "disconnect from server" +msgstr "desconectar do servidor" + +#: src/FLTK/flgui.cpp:4089 +msgid "@>" +msgstr "@>" + +#: src/FLTK/flgui.cpp:4090 +msgid "connect to server" +msgstr "conectar ao servidor" + +#: src/FLTK/flgui.cpp:4106 src/FLTK/flgui.cpp:4438 src/FLTK/flgui.cpp:4657 +#: src/FLTK/fl_callbacks.cpp:4077 +msgid "Streaming" +msgstr "Transmissão" + +#: src/FLTK/flgui.cpp:4110 src/FLTK/flgui.cpp:4469 src/FLTK/flgui.cpp:4771 +msgid "Recording" +msgstr "Gravação" + +#: src/FLTK/flgui.cpp:4140 +msgid "Settings" +msgstr "Configs" + +#: src/FLTK/flgui.cpp:4141 +msgid "show/hide config window" +msgstr "exibir/ocultar janela de configuração" + +#: src/FLTK/flgui.cpp:4148 src/FLTK/fl_callbacks.cpp:1098 +msgid "Show log" +msgstr "Exibir log" + +#: src/FLTK/flgui.cpp:4149 +msgid "show/hide info window" +msgstr "exibir/ocultar janela de informação" + +#: src/FLTK/flgui.cpp:4156 +msgid "-24 dB" +msgstr "-24 dB" + +#: src/FLTK/flgui.cpp:4159 +msgid "Gain" +msgstr "Ganho" + +#: src/FLTK/flgui.cpp:4160 src/FLTK/fl_callbacks.cpp:3663 +#: src/FLTK/fl_funcs.cpp:810 +msgid "Master Gain" +msgstr "Ganho Principal" + +#: src/FLTK/flgui.cpp:4178 +msgid "+24 dB" +msgstr "+24 dB" + +#: src/FLTK/flgui.cpp:4185 +msgid "Listeners: 0" +msgstr "Ouvintes: 0" + +#: src/FLTK/flgui.cpp:4200 +msgid "butt settings" +msgstr "configurações do butt" + +#: src/FLTK/flgui.cpp:4213 +msgid "Main" +msgstr "Principal" + +#: src/FLTK/flgui.cpp:4215 +msgid "Server Settings" +msgstr "Configurações de Servidor" + +#: src/FLTK/flgui.cpp:4218 +msgid "Server" +msgstr "Servidor" + +#: src/FLTK/flgui.cpp:4219 +msgid "Server to connect to" +msgstr "Servidor a ser conectado" + +#: src/FLTK/flgui.cpp:4224 src/FLTK/flgui.cpp:4245 +msgid "ADD" +msgstr "ADICIONAR" + +#: src/FLTK/flgui.cpp:4225 src/FLTK/flgui.cpp:5550 +msgid "Add server" +msgstr "Adicionar servidor" + +#: src/FLTK/flgui.cpp:4229 src/FLTK/flgui.cpp:4250 +msgid "EDIT" +msgstr "EDITAR" + +#: src/FLTK/flgui.cpp:4230 +msgid "Edit selected server" +msgstr "Editar servidor selecionado" + +#: src/FLTK/flgui.cpp:4234 src/FLTK/flgui.cpp:4255 +msgid "DEL" +msgstr "EXCLUIR" + +#: src/FLTK/flgui.cpp:4235 +msgid "Delete selected server" +msgstr "Apagar servidor selecionado" + +#: src/FLTK/flgui.cpp:4239 +msgid "Stream Infos" +msgstr "Informações de transmissão" + +#: src/FLTK/flgui.cpp:4240 +msgid "Stream info that shall be used" +msgstr "Informações de transmissão que deverão ser utilizadas" + +#: src/FLTK/flgui.cpp:4246 src/FLTK/flgui.cpp:5671 +msgid "Add stream info" +msgstr "Adicionar informações de transmissão" + +#: src/FLTK/flgui.cpp:4251 +msgid "Edit stream info" +msgstr "Editar informações de transmissão" + +#: src/FLTK/flgui.cpp:4256 +msgid "Delete stream info" +msgstr "Apagar informações de transmissão" + +#: src/FLTK/flgui.cpp:4262 +msgid "Log File" +msgstr "Arquivo de Log" + +#: src/FLTK/flgui.cpp:4266 +msgid "Log file path" +msgstr "Caminho do arquivo de Log" + +#: src/FLTK/flgui.cpp:4271 +msgid "Select log file" +msgstr "Escolher arquivo de log" + +#: src/FLTK/flgui.cpp:4278 +msgid "Configuration" +msgstr "Configuração" + +#: src/FLTK/flgui.cpp:4281 src/FLTK/fl_callbacks.cpp:4128 +msgid "Import..." +msgstr "Importar..." + +#: src/FLTK/flgui.cpp:4282 +msgid "Import settings from config file" +msgstr "Importar configurações do arquivo" + +#: src/FLTK/flgui.cpp:4286 src/FLTK/flgui.cpp:5615 src/FLTK/flgui.cpp:5717 +msgid "&Save" +msgstr "&Salvar" + +#: src/FLTK/flgui.cpp:4287 +msgid "Save settings" +msgstr "Salvar configurações" + +#: src/FLTK/flgui.cpp:4291 +msgid "Export..." +msgstr "Exportar..." + +#: src/FLTK/flgui.cpp:4292 +msgid "export settings" +msgstr "exportar configurações" + +#: src/FLTK/flgui.cpp:4298 +msgid "Butt Agent" +msgstr "Agente do Butt" + +#: src/FLTK/flgui.cpp:4301 +msgid "Start agent at startup" +msgstr "Iniciar agente na inicialização" + +#: src/FLTK/flgui.cpp:4302 +msgid "Start the butt agent when butt starts" +msgstr "Inicia o agente ao inicializar o butt" + +#: src/FLTK/flgui.cpp:4306 src/FLTK/flgui.cpp:4307 +msgid "Minimize butt to tray" +msgstr "Minimizar butt na bandeja" + +#: src/FLTK/flgui.cpp:4311 +msgid "Start Agent" +msgstr "Iniciar Agente" + +#: src/FLTK/flgui.cpp:4312 +msgid "Start the butt agent now" +msgstr "Inicia o agente do butt agora" + +#: src/FLTK/flgui.cpp:4316 +msgid "Stop Agent" +msgstr "Parar Agente" + +#: src/FLTK/flgui.cpp:4317 +msgid "Stop the butt agent" +msgstr "Para o agente do butt" + +#: src/FLTK/flgui.cpp:4323 +msgid "Updates" +msgstr "Atualizações" + +#: src/FLTK/flgui.cpp:4326 +msgid "Check at startup" +msgstr "Verificar ao iniciar" + +#: src/FLTK/flgui.cpp:4327 +msgid "Check for updates at start" +msgstr "Buscar atualizações ao iniciar" + +#: src/FLTK/flgui.cpp:4331 +msgid "Check now" +msgstr "Verificar agora" + +#: src/FLTK/flgui.cpp:4332 +msgid "Check if a new version is available" +msgstr "Verificar se nova versão está disponível" + +#: src/FLTK/flgui.cpp:4338 +msgid "Help" +msgstr "Ajuda" + +#: src/FLTK/flgui.cpp:4341 +msgid "Manual" +msgstr "Manual" + +#: src/FLTK/flgui.cpp:4345 +msgid " YouTube" +msgstr " YouTube" + +#: src/FLTK/flgui.cpp:4355 +msgid "Audio" +msgstr "Ãudio" + +#: src/FLTK/flgui.cpp:4357 +msgid "Main Audio Settings" +msgstr "Configurações Principais de Ãudio" + +#: src/FLTK/flgui.cpp:4360 +msgid "Channel mode" +msgstr "Modo do canal" + +#: src/FLTK/flgui.cpp:4361 +msgid "Select input channel" +msgstr "Selecione o canal de entrada" + +#: src/FLTK/flgui.cpp:4374 +msgid "Samplerate" +msgstr "Taxa de sample" + +#: src/FLTK/flgui.cpp:4375 +msgid "Select input sample rate" +msgstr "Selecione a taxa de sample de entrada" + +#: src/FLTK/flgui.cpp:4380 +msgid "Remember Device by" +msgstr "Lembrar Dispositivo por" + +#: src/FLTK/flgui.cpp:4383 +msgid "ID" +msgstr "ID" + +#: src/FLTK/flgui.cpp:4388 +msgid "Name" +msgstr "Nome" + +#: src/FLTK/flgui.cpp:4395 +msgid "Update devices" +msgstr "Atualizar dispositivos" + +#: src/FLTK/flgui.cpp:4396 +msgid "Rescan audio devices" +msgstr "Buscar dispositivos de áudio" + +#: src/FLTK/flgui.cpp:4400 +msgid "Primary Audio Device" +msgstr "Disp. de Ãudio Primário" + +#: src/FLTK/flgui.cpp:4401 +msgid "Select your primary sound card device" +msgstr "Escolha sua placa de som primária" + +#: src/FLTK/flgui.cpp:4406 src/FLTK/flgui.cpp:4424 +msgid "Left" +msgstr "Esquerdo" + +#: src/FLTK/flgui.cpp:4407 src/FLTK/flgui.cpp:4425 +msgid "Select left audio channel" +msgstr "Selecione o canal de áudio esquerdo" + +#: src/FLTK/flgui.cpp:4412 src/FLTK/flgui.cpp:4430 +msgid "Right" +msgstr "Direito" + +#: src/FLTK/flgui.cpp:4413 src/FLTK/flgui.cpp:4431 +msgid "Select right audio channel" +msgstr "Selecione o canal de áudio direito" + +#: src/FLTK/flgui.cpp:4418 +msgid "Secondary Audio Device" +msgstr "Disp. de Ãudio Secundário" + +#: src/FLTK/flgui.cpp:4419 +msgid "Select your secondary sound card device" +msgstr "Escolha sua placa de som secundária" + +#: src/FLTK/flgui.cpp:4441 src/FLTK/flgui.cpp:4472 +msgid "Codec" +msgstr "Codec" + +#: src/FLTK/flgui.cpp:4442 +msgid "Select streaming codec" +msgstr "Selecione o codec de transmissão" + +#: src/FLTK/flgui.cpp:4455 src/FLTK/flgui.cpp:4486 +msgid "Bitrate" +msgstr "Taxa de bits" + +#: src/FLTK/flgui.cpp:4456 +msgid "Select streaming bitrate" +msgstr "Selecione o bitrate da transmissão" + +#: src/FLTK/flgui.cpp:4473 +msgid "Select recording codec" +msgstr "Selecione o codec de gravação" + +#: src/FLTK/flgui.cpp:4487 +msgid "Select recording bitrate" +msgstr "Selecione a taxa de bits para a gravação" + +#: src/FLTK/flgui.cpp:4499 +msgid "Advanced..." +msgstr "Avançado..." + +#: src/FLTK/flgui.cpp:4505 +msgid "Buffer (ms)" +msgstr "Buffer (ms)" + +#: src/FLTK/flgui.cpp:4514 +msgid "Resample Quality" +msgstr "Qualidade de Resample" + +#: src/FLTK/flgui.cpp:4529 +msgid "Signal detection levels" +msgstr "Níveis de detecção de sinal" + +#: src/FLTK/flgui.cpp:4532 +msgid "Signal present" +msgstr "Sinal presente" + +#: src/FLTK/flgui.cpp:4539 src/FLTK/flgui.cpp:4549 +msgid "dB" +msgstr "dB" + +#: src/FLTK/flgui.cpp:4542 +msgid "Signal absent" +msgstr "Sinal ausente" + +#: src/FLTK/flgui.cpp:4556 src/FLTK/flgui.cpp:4833 src/FLTK/flgui.cpp:5084 +msgid "Stream" +msgstr "Trans." + +#: src/FLTK/flgui.cpp:4558 +msgid "Update song name from file" +msgstr "Atualizar o nome da música pelo arquivo" + +#: src/FLTK/flgui.cpp:4562 +msgid "Filename that holds the current song name" +msgstr "Nome do arquivo que contém o nome da música atual" + +#: src/FLTK/flgui.cpp:4568 +msgid "Select file that holds the current song name" +msgstr "Selecione o arquivo que contém o nome da música atual" + +#: src/FLTK/flgui.cpp:4573 src/FLTK/flgui.cpp:4606 src/FLTK/flgui.cpp:4724 +msgid "Activate" +msgstr "Ativar" + +#: src/FLTK/flgui.cpp:4574 src/FLTK/flgui.cpp:4579 +msgid "Activate auto update song name from file" +msgstr "Ativar atualização automática do nome da música por arquivo" + +#: src/FLTK/flgui.cpp:4578 +msgid "Read last line instead of first" +msgstr "Ler última linha ao invés da primeira" + +#: src/FLTK/flgui.cpp:4585 +msgid "Update song name from application" +msgstr "Atualizar o nome da música pela aplicação" + +#: src/FLTK/flgui.cpp:4589 +msgid "Changes the song through an running application" +msgstr "Altera a música através de uma aplicação externa" + +#: src/FLTK/flgui.cpp:4594 +msgid "Title - Artist" +msgstr "Título - Artista" + +#: src/FLTK/flgui.cpp:4599 +msgid "Artist - Title" +msgstr "Artista - Título" + +#: src/FLTK/flgui.cpp:4612 +msgid "Update song name manually" +msgstr "Atualizar o nome da música manualmente" + +#: src/FLTK/flgui.cpp:4616 +msgid "Current song name" +msgstr "Nome da música atual" + +#: src/FLTK/flgui.cpp:4622 src/FLTK/fl_callbacks.cpp:1594 +msgid "OK" +msgstr "OK" + +#: src/FLTK/flgui.cpp:4623 +msgid "Send current song name to the server" +msgstr "Enviar o nome da música atual para o servidor" + +#: src/FLTK/flgui.cpp:4631 +msgid "Update song name delay" +msgstr "Intervalo para atualizar o nome da música" + +#: src/FLTK/flgui.cpp:4635 +msgid "Introduces a delay until the song name is actually updated" +msgstr "Introduz um atraso até que o nome da música seja atualizado" + +#: src/FLTK/flgui.cpp:4642 +msgid "Extend song name" +msgstr "Nome estendido da música" + +#: src/FLTK/flgui.cpp:4645 +msgid "Prefix:" +msgstr "Prefixo:" + +#: src/FLTK/flgui.cpp:4650 +msgid "Suffix:" +msgstr "Sufixo:" + +#: src/FLTK/flgui.cpp:4660 src/FLTK/flgui.cpp:4789 +msgid "Start if signal is present for" +msgstr "Iniciar se houver sinal por" + +#: src/FLTK/flgui.cpp:4661 +msgid "" +"Start streaming if the audio level exceeds the \"Signal present\" level set " +"in the \"Audio\" tab" +msgstr "" +"Iniciar transmissão se o nível de áudio exceder o campo “Sinal Presente†na " +"aba “Ãudioâ€" + +#: src/FLTK/flgui.cpp:4670 src/FLTK/flgui.cpp:4683 src/FLTK/flgui.cpp:4702 +#: src/FLTK/flgui.cpp:4799 src/FLTK/flgui.cpp:4812 src/FLTK/flgui.cpp:5499 +msgid "seconds" +msgstr "segundos" + +#: src/FLTK/flgui.cpp:4673 src/FLTK/flgui.cpp:4802 +msgid "Stop if signal is absent for" +msgstr "Parar se não houver sinal por" + +#: src/FLTK/flgui.cpp:4674 +msgid "" +"Stop streaming if the audio level falls below the \"Signal absent level set " +"in the \"Audio\" tab" +msgstr "" +"Parar transmissão se o nível de áudio ficar abaixo do campo “Sinal Ausente†" +"da aba “Ãudioâ€" + +#: src/FLTK/flgui.cpp:4686 +msgid "Start streaming after launch" +msgstr "Iniciar transmissão após a inicialização" + +#: src/FLTK/flgui.cpp:4687 +msgid "Connect automatically to a server after launch" +msgstr "Conectar automaticamente ao servidor ao inicializar" + +#: src/FLTK/flgui.cpp:4691 +msgid "Force reconnecting" +msgstr "Forçar reconexão" + +#: src/FLTK/flgui.cpp:4692 +msgid "If enabled butt keeps reconnecting regardless of the error message" +msgstr "" +"Se habilitado o butt se mantém reconectando independente da mensagem de erro" + +#: src/FLTK/flgui.cpp:4696 +msgid "Reconnect delay:" +msgstr "Intervalo de reconexão:" + +#: src/FLTK/flgui.cpp:4707 +msgid "Update song name from URL" +msgstr "Atualizar nome da música por URL" + +#: src/FLTK/flgui.cpp:4711 +msgid "URL to get song name from" +msgstr "URL para obter nome da música" + +#: src/FLTK/flgui.cpp:4716 +msgid "Update interval" +msgstr "Intervalo de Atualização" + +#: src/FLTK/flgui.cpp:4717 +msgid "Update interval in seconds" +msgstr "Atualizar intervalo em segundos" + +#: src/FLTK/flgui.cpp:4732 +msgid "Record" +msgstr "Gravar" + +#: src/FLTK/flgui.cpp:4734 +msgid "Record File Name:" +msgstr "Arquivo de Gravação:" + +#: src/FLTK/flgui.cpp:4735 +msgid "Record file name" +msgstr "Arquivo de gravação" + +#: src/FLTK/flgui.cpp:4740 +msgid "Record Directory:" +msgstr "Pasta de Gravação:" + +#: src/FLTK/flgui.cpp:4741 +msgid "Directory of recordings" +msgstr "Pasta das gravações" + +#: src/FLTK/flgui.cpp:4747 +msgid "Select recording directory" +msgstr "Selecionar a pasta de gravação" + +#: src/FLTK/flgui.cpp:4752 +msgid "Split file" +msgstr "Dividir arquivo" + +#: src/FLTK/flgui.cpp:4755 +msgid "every" +msgstr "a cada" + +#: src/FLTK/flgui.cpp:4758 +msgid "minutes" +msgstr "minutos" + +#: src/FLTK/flgui.cpp:4760 src/FLTK/flgui.cpp:4761 +msgid "Sync to full hour" +msgstr "Sincronizar a cada hora cheia" + +#: src/FLTK/flgui.cpp:4765 +msgid "Split now" +msgstr "Dividir já" + +#: src/FLTK/flgui.cpp:4774 src/FLTK/flgui.cpp:4775 +msgid "Start recording when connected" +msgstr "Iniciar gravação ao conectar" + +#: src/FLTK/flgui.cpp:4779 +msgid "Stop recording when disconnected" +msgstr "Parar gravação ao desconectar" + +#: src/FLTK/flgui.cpp:4780 +msgid "Start recording when disconnected" +msgstr "Iniciar gravação ao desconectar" + +#: src/FLTK/flgui.cpp:4784 src/FLTK/flgui.cpp:4785 +msgid "Start recording after launch" +msgstr "Iniciar gravação após iniciar" + +#: src/FLTK/flgui.cpp:4790 +msgid "" +"Start recording if the audio level exceeds the \"Signal present\" level set " +"in the \"Audio\" tab" +msgstr "" +"Iniciar gravação se o nível de áudio exceder o campo “Sinal Presente†da aba " +"“Ãudioâ€" + +#: src/FLTK/flgui.cpp:4803 +msgid "" +"Stop recording if the audio level falls below the \"Signal absent level set " +"in the \"Audio\" tab" +msgstr "" +"Parar gravação se o nível do áudio ficar abaixo do campo “Sinal Ausente†da " +"aba “Ãudioâ€" + +#: src/FLTK/flgui.cpp:4815 +msgid "Overwrite existing files" +msgstr "Sobrescrever arquivos existentes" + +#: src/FLTK/flgui.cpp:4823 +msgid "DSP" +msgstr "DSP" + +#: src/FLTK/flgui.cpp:4825 src/FLTK/flgui.cpp:5076 src/FLTK/flgui.cpp:6478 +msgid "Reset" +msgstr "Redefinir" + +#: src/FLTK/flgui.cpp:4830 +msgid "Equalizer" +msgstr "Equalizador" + +#: src/FLTK/flgui.cpp:4837 src/FLTK/flgui.cpp:5088 +msgid "Rec" +msgstr "Gravar" + +#: src/FLTK/flgui.cpp:4842 +msgid "Equalizer Preset" +msgstr "Predefinições de Equalizador" + +#: src/FLTK/flgui.cpp:4854 src/FLTK/flgui.cpp:4876 src/FLTK/flgui.cpp:4898 +#: src/FLTK/flgui.cpp:4920 src/FLTK/flgui.cpp:4942 src/FLTK/flgui.cpp:4964 +#: src/FLTK/flgui.cpp:4986 src/FLTK/flgui.cpp:5008 src/FLTK/flgui.cpp:5030 +#: src/FLTK/flgui.cpp:5052 src/FLTK/flgui.cpp:5096 src/FLTK/flgui.cpp:5118 +#: src/FLTK/flgui.cpp:5186 +msgid "+0.0" +msgstr "+0.0" + +#: src/FLTK/flgui.cpp:4858 +msgid "32Hz" +msgstr "32Hz" + +#: src/FLTK/flgui.cpp:4880 +msgid "64Hz" +msgstr "64Hz" + +#: src/FLTK/flgui.cpp:4902 +msgid "125Hz" +msgstr "125Hz" + +#: src/FLTK/flgui.cpp:4924 +msgid "250Hz" +msgstr "250Hz" + +#: src/FLTK/flgui.cpp:4946 +msgid "500Hz" +msgstr "500Hz" + +#: src/FLTK/flgui.cpp:4968 +msgid "1kHz" +msgstr "1kHz" + +#: src/FLTK/flgui.cpp:4990 +msgid "2kHz" +msgstr "2kHz" + +#: src/FLTK/flgui.cpp:5012 +msgid "4kHz" +msgstr "4kHz" + +#: src/FLTK/flgui.cpp:5034 +msgid "8kHz" +msgstr "8kHz" + +#: src/FLTK/flgui.cpp:5056 +msgid "16kHz" +msgstr "16kHz" + +#: src/FLTK/flgui.cpp:5081 +msgid "Dynamic Range Compressor" +msgstr "Compressor de Intervalo Dinâmico" + +#: src/FLTK/flgui.cpp:5092 +msgid "Aggressive Mode" +msgstr "Modo Agressivo" + +#: src/FLTK/flgui.cpp:5100 +msgid "Threshold" +msgstr "Limite" + +#: src/FLTK/flgui.cpp:5122 +msgid "Ratio" +msgstr "Taxa" + +#: src/FLTK/flgui.cpp:5140 src/FLTK/flgui.cpp:5163 +msgid "+0.00" +msgstr "+0.00" + +#: src/FLTK/flgui.cpp:5144 +msgid "Attack" +msgstr "Ataque" + +#: src/FLTK/flgui.cpp:5167 +msgid "Release" +msgstr "Soltar" + +#: src/FLTK/flgui.cpp:5190 +msgid "MakeupGain" +msgstr "Ganho" + +#: src/FLTK/flgui.cpp:5224 src/FLTK/flgui.cpp:5237 +msgid "MIDI" +msgstr "MIDI" + +#: src/FLTK/flgui.cpp:5226 +msgid "MIDI Device" +msgstr "Dispositivo MIDI" + +#: src/FLTK/flgui.cpp:5227 +msgid "Select your MIDI device" +msgstr "Selecione seu dispositivo MIDI" + +#: src/FLTK/flgui.cpp:5232 +msgid "Rescan" +msgstr "Buscar" + +#: src/FLTK/flgui.cpp:5233 +msgid "Rescan MIDI devices" +msgstr "Buscar dispositivos MIDI" + +#: src/FLTK/flgui.cpp:5238 +msgid "MIDI signal indicator" +msgstr "Indicador de sinal MIDI" + +#: src/FLTK/flgui.cpp:5250 +msgid "MIDI Commands" +msgstr "Comandos MIDI" + +#: src/FLTK/flgui.cpp:5255 +msgid "Enable" +msgstr "Habilitar" + +#: src/FLTK/flgui.cpp:5256 +msgid "Enable/Disable the selected MIDI command" +msgstr "Habilita/Desabilita o comando MIDI selecionado" + +#: src/FLTK/flgui.cpp:5262 +msgid "Channel" +msgstr "Canal" + +#: src/FLTK/flgui.cpp:5263 +msgid "Select MIDI channel" +msgstr "Selecione o canal MIDI" + +#: src/FLTK/flgui.cpp:5277 +msgid "CC" +msgstr "CC" + +#: src/FLTK/flgui.cpp:5278 +msgid "Select CC number" +msgstr "Selecione o número CC" + +#: src/FLTK/flgui.cpp:5283 src/FLTK/fl_callbacks.cpp:6425 +msgid "Learn" +msgstr "Aprender" + +#: src/FLTK/flgui.cpp:5284 +msgid "Activate to auto detect the channel and CC number" +msgstr "Ative para detectar automaticamente o caham e o número CC" + +#: src/FLTK/flgui.cpp:5289 +msgid "CC Mode" +msgstr "Modo CC" + +#: src/FLTK/flgui.cpp:5290 +msgid "Select CC mode" +msgstr "Selecione o modo CC" + +#: src/FLTK/flgui.cpp:5304 +msgid "Soft takeover" +msgstr "Assumir soft" + +#: src/FLTK/flgui.cpp:5305 +msgid "Prevents jumps when controlling a slider in absolute mode" +msgstr "Previne pulos ao controlar um slider em modo absoluto" + +#: src/FLTK/flgui.cpp:5313 +msgid "TLS" +msgstr "TLS" + +#: src/FLTK/flgui.cpp:5315 src/FLTK/flgui.cpp:5619 +msgid "SSL/TLS" +msgstr "SSL/TLS" + +#: src/FLTK/flgui.cpp:5318 +msgid "" +"If your server uses a certificate from\n" +"Let's Encrypt or another well known\n" +"CA, you can leave these fields blank." +msgstr "" +"Caso seu servidor use um certificado de\n" +"Let's Encrypt ou outro CA conhecido,\n" +"você pode deixar esses campos em branco." + +#: src/FLTK/flgui.cpp:5322 +msgid "CA Certificate File:" +msgstr "Arquivo de Certificado CA:" + +#: src/FLTK/flgui.cpp:5323 +msgid "Certificate file" +msgstr "Arquivo de Certificado" + +#: src/FLTK/flgui.cpp:5329 +msgid "Select certificate file" +msgstr "Selecionar o arquivo de certificado" + +#: src/FLTK/flgui.cpp:5334 +msgid "CA Certificate Directory:" +msgstr "Pasta de Certificado CA:" + +#: src/FLTK/flgui.cpp:5335 +msgid "Certificate directory" +msgstr "Pasta do certificado" + +#: src/FLTK/flgui.cpp:5341 +msgid "Select certificate directory" +msgstr "Selecionar a pasta de certificado" + +#: src/FLTK/flgui.cpp:5350 +msgid "GUI" +msgstr "GUI" + +#: src/FLTK/flgui.cpp:5352 +msgid "Language" +msgstr "Idioma" + +#: src/FLTK/flgui.cpp:5369 +msgid "Display Color" +msgstr "Cor do Display" + +#: src/FLTK/flgui.cpp:5372 +msgid "Text" +msgstr "Texto" + +#: src/FLTK/flgui.cpp:5373 +msgid "Select text color" +msgstr "Selecione a cor do texto" + +#: src/FLTK/flgui.cpp:5379 +msgid "Background" +msgstr "Cor Fundo" + +#: src/FLTK/flgui.cpp:5380 +msgid "Select background color" +msgstr "Selecione a cor de fundo" + +#: src/FLTK/flgui.cpp:5388 +msgid "VU meter" +msgstr "VU meter" + +#: src/FLTK/flgui.cpp:5391 +msgid "Gradient colors" +msgstr "Cores gradientes" + +#: src/FLTK/flgui.cpp:5396 +msgid "Solid colors" +msgstr "Cores sólidas" + +#: src/FLTK/flgui.cpp:5401 +msgid "Always show tabs" +msgstr "Sempre mostrar abas" + +#: src/FLTK/flgui.cpp:5406 +msgid "Select lower range color" +msgstr "Selecione a cor do limite mínimo" + +#: src/FLTK/flgui.cpp:5413 +msgid "Select mid range color" +msgstr "Selecione a cor do limite médio" + +#: src/FLTK/flgui.cpp:5420 +msgid "Select high range color" +msgstr "Selecione a cor do limite alto" + +#: src/FLTK/flgui.cpp:5427 +msgid "Low range start value (dB)" +msgstr "Valor inicial do limite mínimo (dB)" + +#: src/FLTK/flgui.cpp:5431 +msgid "Mid range start value (dB)" +msgstr "Valor inicial do limite médio (dB)" + +#: src/FLTK/flgui.cpp:5440 +msgid "High range start value (dB)" +msgstr "Valor inicial do limite alto (dB)" + +#: src/FLTK/flgui.cpp:5450 +msgid "Misc" +msgstr "Misc" + +#: src/FLTK/flgui.cpp:5453 +msgid "Attach settings window to main window" +msgstr "Anexar janela de configurações na principal" + +#: src/FLTK/flgui.cpp:5454 +msgid "Attach this window to the butt window" +msgstr "Anexar esta janela à do butt" + +#: src/FLTK/flgui.cpp:5458 src/FLTK/flgui.cpp:5459 +msgid "Stay always on top" +msgstr "Sempre no topo" + +#: src/FLTK/flgui.cpp:5463 src/FLTK/flgui.cpp:5464 +msgid "Remember main window position" +msgstr "Lembrar a posição da janela principal" + +#: src/FLTK/flgui.cpp:5468 src/FLTK/flgui.cpp:5469 +msgid "Hide log window after start up" +msgstr "Ocultar janela de log após inicialização" + +#: src/FLTK/flgui.cpp:5473 src/FLTK/flgui.cpp:5474 +msgid "Change display mode every 5 seconds" +msgstr "Alterar o modo de exibição a cada 5 segundos" + +#: src/FLTK/flgui.cpp:5478 +msgid "Start minimized" +msgstr "Iniciar minimizado" + +#: src/FLTK/flgui.cpp:5479 +msgid "Minimize butt at startup" +msgstr "Minimizar o butt na inicialização" + +#: src/FLTK/flgui.cpp:5483 +msgid "Disable gain control" +msgstr "Desativar o controle de ganho" + +#: src/FLTK/flgui.cpp:5489 +msgid "Show listeners" +msgstr "Mostrar número de ouvintes" + +#: src/FLTK/flgui.cpp:5490 +msgid "Show current listeners in the display (not always available)" +msgstr "Mostrar o número atual de ouvintes no visor (nem sempre possível)" + +#: src/FLTK/flgui.cpp:5494 +msgid "Update rate:" +msgstr "Taxa atualiz.:" + +#: src/FLTK/flgui.cpp:5504 +msgid "Custom window title:" +msgstr "Título da janela personalizada:" + +#: src/FLTK/flgui.cpp:5505 +msgid "Define a custom window title" +msgstr "Define um título personalizado para a janela" + +#: src/FLTK/flgui.cpp:5515 +msgid "Donate" +msgstr "Doar" + +#: src/FLTK/flgui.cpp:5517 +msgid "Donation" +msgstr "Doação" + +#: src/FLTK/flgui.cpp:5520 +msgid "" +"Keeping this software up to date, adding\n" +"new features and answering support mails\n" +"takes a lot of time and effort. If you can\n" +"afford it, please consider supporting this\n" +"project.\n" +"\n" +"Thank you!" +msgstr "" +"Manter o software atualizado, adicionar novas\n" +"funcionalidades e responder aos mails de\n" +"suporte levam muito tempo e esforço. Se tiver\n" +"condições, considere contribuir com este\n" +"projeto.\n" +"\n" +"Muito obrigado!" + +#: src/FLTK/flgui.cpp:5525 +msgid "&Donate via PayPal" +msgstr "&Doar via PayPal" + +#: src/FLTK/flgui.cpp:5529 +msgid "Become a &patron" +msgstr "Tornar-se um &patron" + +#: src/FLTK/flgui.cpp:5533 +msgid "&Apple Pay, Google Pay, CC and more" +msgstr "&Apple Pay, Google Pay, CC e outros" + +#: src/FLTK/flgui.cpp:5537 +msgid "&Bitcoin && Co" +msgstr "&Bitcoin && Co" + +#: src/FLTK/flgui.cpp:5552 src/FLTK/flgui.cpp:5673 +msgid "Name:" +msgstr "Nome:" + +#: src/FLTK/flgui.cpp:5556 +msgid "Address:" +msgstr "Endereço:" + +#: src/FLTK/flgui.cpp:5560 +msgid "Port:" +msgstr "Porta:" + +#: src/FLTK/flgui.cpp:5564 +msgid "Password:" +msgstr "Senha:" + +#: src/FLTK/flgui.cpp:5569 +msgid "Icecast mountpoint:" +msgstr "Montagem do Icecast:" + +#: src/FLTK/flgui.cpp:5573 +msgid "Icecast user:" +msgstr "Usuário Icecast:" + +#: src/FLTK/flgui.cpp:5577 src/FLTK/fl_callbacks.cpp:1136 +#: src/FLTK/fl_callbacks.cpp:1215 src/FLTK/fl_callbacks.cpp:1623 +msgid "Show" +msgstr "Exibir" + +#: src/FLTK/flgui.cpp:5578 +msgid "show/hide password" +msgstr "exibir/ocultar senha" + +#: src/FLTK/flgui.cpp:5582 +msgid "Type" +msgstr "Tipo" + +#: src/FLTK/flgui.cpp:5585 +msgid "Shoutcast" +msgstr "Shoutcast" + +#: src/FLTK/flgui.cpp:5590 +msgid "Icecast" +msgstr "Icecast" + +#: src/FLTK/flgui.cpp:5595 +msgid "WebRTC" +msgstr "WebRTC" + +#: src/FLTK/flgui.cpp:5600 +msgid "Radio.co" +msgstr "Radio.co" + +#: src/FLTK/flgui.cpp:5607 src/FLTK/flgui.cpp:5709 +msgid "&Cancel" +msgstr "&Cancelar" + +#: src/FLTK/flgui.cpp:5611 src/FLTK/flgui.cpp:5713 +msgid "&ADD" +msgstr "&ADICIONAR" + +#: src/FLTK/flgui.cpp:5622 +msgid "Use SSL/TLS" +msgstr "Usar SSL/TLS" + +#: src/FLTK/flgui.cpp:5625 +msgid "Revoke certificate trust" +msgstr "Revogar certificado" + +#: src/FLTK/flgui.cpp:5631 +msgid "Radio.co Stations" +msgstr "Estações Radio.co" + +#: src/FLTK/flgui.cpp:5634 +msgid "Get Stations" +msgstr "Obter Estações" + +#: src/FLTK/flgui.cpp:5638 +msgid "Select all" +msgstr "Selecionar tudo" + +#: src/FLTK/flgui.cpp:5642 +msgid "Deselect all" +msgstr "Selecionar nenhum" + +#: src/FLTK/flgui.cpp:5646 +msgid "Use legacy Icecast protocol" +msgstr "Usar protocolo legado do Icecast" + +#: src/FLTK/flgui.cpp:5647 +msgid "" +"Activate this if you want to use the older SOURCE protocol instead of the " +"newer PUT protocol" +msgstr "" +"Ative isso caso queira utilizar o protocolo antigo SOURCE ao invés do novo " +"protocolo PUT" + +#: src/FLTK/flgui.cpp:5651 +msgid "ICE server (optional):" +msgstr "Servidor ICE (opcional):" + +#: src/FLTK/flgui.cpp:5654 +msgid "WebRTC (WHIP) URL:" +msgstr "WebRTC (WHIP) URL:" + +#: src/FLTK/flgui.cpp:5657 +msgid "Bearer token (optional):" +msgstr "Bearer token (optional):" + +#: src/FLTK/flgui.cpp:5660 +msgid "Custom listener URL (optional):" +msgstr "URL para números de ouvintes (opcional):" + +#: src/FLTK/flgui.cpp:5664 +msgid "Custom listener mountpoint (optional):" +msgstr "Ponto de montagem para números de ouvintes (optional):" + +#: src/FLTK/flgui.cpp:5674 +msgid "The name of your new ICY-entrie" +msgstr "O nome do seu novo ICY-entrie" + +#: src/FLTK/flgui.cpp:5678 +msgid "Description:" +msgstr "Descrição:" + +#: src/FLTK/flgui.cpp:5682 +msgid "Genre:" +msgstr "Gênero:" + +#: src/FLTK/flgui.cpp:5686 +msgid "URL:" +msgstr "URL:" + +#: src/FLTK/flgui.cpp:5690 +msgid "ICQ:" +msgstr "ICQ:" + +#: src/FLTK/flgui.cpp:5694 +msgid "IRC:" +msgstr "IRC:" + +#: src/FLTK/flgui.cpp:5698 +msgid "AIM:" +msgstr "AIM:" + +#: src/FLTK/flgui.cpp:5702 +msgid "Make server public" +msgstr "Tornar servidor público" + +#: src/FLTK/flgui.cpp:5705 +msgid "Expand variables" +msgstr "Expandir variáveis" + +#: src/FLTK/flgui.cpp:5706 +msgid "Activate to expand date variables in name and description" +msgstr "Ative para expandir as variáveis de data em nomes e descrições" + +#: src/FLTK/flgui.cpp:5736 +msgid "Donate Cryptocurrency" +msgstr "Doar criptomoeda" + +#: src/FLTK/flgui.cpp:5747 +msgid "Bitcoin" +msgstr "Bitcoin" + +#: src/FLTK/flgui.cpp:5752 src/FLTK/flgui.cpp:5761 src/FLTK/flgui.cpp:5770 +msgid "Copy" +msgstr "Copiar" + +#: src/FLTK/flgui.cpp:5756 +msgid "Litecoin" +msgstr "Litecoin" + +#: src/FLTK/flgui.cpp:5765 +msgid "Monero" +msgstr "Monero" + +#: src/FLTK/flgui.cpp:5774 src/FLTK/flgui.cpp:6106 src/FLTK/flgui.cpp:6461 +#: src/FLTK/flgui.cpp:6669 +msgid "&Close" +msgstr "&Fechar" + +#: src/FLTK/flgui.cpp:5780 +msgid "Streaming Codec Settings" +msgstr "Configurações do Codec de Transmissão" + +#: src/FLTK/flgui.cpp:5792 src/FLTK/flgui.cpp:6124 +msgid "MP3" +msgstr "MP3" + +#: src/FLTK/flgui.cpp:5793 src/FLTK/flgui.cpp:6125 +msgid "Encoding Quality" +msgstr "Qualidade do Encoding" + +#: src/FLTK/flgui.cpp:5806 src/FLTK/flgui.cpp:6138 +msgid "Stereo Mode" +msgstr "Modo Estéreo" + +#: src/FLTK/flgui.cpp:5819 src/FLTK/flgui.cpp:5949 src/FLTK/flgui.cpp:6015 +#: src/FLTK/flgui.cpp:6071 src/FLTK/flgui.cpp:6151 src/FLTK/flgui.cpp:6281 +#: src/FLTK/flgui.cpp:6334 src/FLTK/flgui.cpp:6403 +msgid "Bitrate Mode" +msgstr "Modo de Taxa de Bits" + +#: src/FLTK/flgui.cpp:5832 src/FLTK/flgui.cpp:6164 +msgid "VBR" +msgstr "VBR" + +#: src/FLTK/flgui.cpp:5835 src/FLTK/flgui.cpp:5989 src/FLTK/flgui.cpp:6167 +#: src/FLTK/flgui.cpp:6347 +msgid "Quality" +msgstr "Qualidade" + +#: src/FLTK/flgui.cpp:5848 src/FLTK/flgui.cpp:6180 +msgid "Min. Bitrate" +msgstr "Tx. Bits Min." + +#: src/FLTK/flgui.cpp:5861 src/FLTK/flgui.cpp:6193 +msgid "Max. Bitrate" +msgstr "Tx. Bits Max." + +#: src/FLTK/flgui.cpp:5874 src/FLTK/flgui.cpp:6206 +msgid "Force" +msgstr "Forçar" + +#: src/FLTK/flgui.cpp:5875 src/FLTK/flgui.cpp:6207 +msgid "Strictly enforce mininum Bitrate (-F option of the lame encoder)" +msgstr "Forçar taxa de bits mínima (Opção -F do lame encoder)" + +#: src/FLTK/flgui.cpp:5881 src/FLTK/flgui.cpp:6227 +msgid "Lowpass (kHz)" +msgstr "Passa-baixo (kHz)" + +#: src/FLTK/flgui.cpp:5884 src/FLTK/flgui.cpp:5909 src/FLTK/flgui.cpp:6230 +#: src/FLTK/flgui.cpp:6255 +msgid "Frequency" +msgstr "Frequência" + +#: src/FLTK/flgui.cpp:5890 src/FLTK/flgui.cpp:5915 src/FLTK/flgui.cpp:6236 +#: src/FLTK/flgui.cpp:6261 +msgid "Width" +msgstr "Largura" + +#: src/FLTK/flgui.cpp:5906 src/FLTK/flgui.cpp:6252 +msgid "Highpass (kHz)" +msgstr "Passa-alto (kHz)" + +#: src/FLTK/flgui.cpp:5931 src/FLTK/flgui.cpp:6213 +msgid "Resampling" +msgstr "Reamostrando" + +#: src/FLTK/flgui.cpp:5932 src/FLTK/flgui.cpp:6214 +msgid "Resample to the selected sample rate" +msgstr "Reamostrar para a taxa de amostragem selecionada" + +#: src/FLTK/flgui.cpp:5947 src/FLTK/flgui.cpp:6279 +msgid "OGG" +msgstr "OGG" + +#: src/FLTK/flgui.cpp:5962 src/FLTK/flgui.cpp:6294 +msgid "VBR Quality" +msgstr "Qualidade VBR" + +#: src/FLTK/flgui.cpp:5975 src/FLTK/flgui.cpp:6307 +msgid "VBR min. Bitrate" +msgstr "Taxa mín. do VBR" + +#: src/FLTK/flgui.cpp:5980 src/FLTK/flgui.cpp:6312 +msgid "VBR max. Bitrate" +msgstr "Taxa máx. do VBR" + +#: src/FLTK/flgui.cpp:5987 src/FLTK/flgui.cpp:6319 +msgid "OPUS" +msgstr "OPUS" + +#: src/FLTK/flgui.cpp:6002 src/FLTK/flgui.cpp:6321 +msgid "Optimize for" +msgstr "Otimizar para" + +#: src/FLTK/flgui.cpp:6028 src/FLTK/flgui.cpp:6360 +msgid "Max. Bandwidth" +msgstr "Banda Máxima" + +#: src/FLTK/flgui.cpp:6043 src/FLTK/flgui.cpp:6375 +msgid "AAC" +msgstr "AAC" + +#: src/FLTK/flgui.cpp:6045 src/FLTK/flgui.cpp:6377 +msgid "Profile" +msgstr "Perfil" + +#: src/FLTK/flgui.cpp:6058 src/FLTK/flgui.cpp:6390 +msgid "Afterburner" +msgstr "Afterburner" + +#: src/FLTK/flgui.cpp:6086 src/FLTK/flgui.cpp:6418 +msgid "FLAC" +msgstr "FLAC" + +#: src/FLTK/flgui.cpp:6088 src/FLTK/flgui.cpp:6420 src/FLTK/flgui.cpp:6438 +msgid "Bit depth" +msgstr "Resolução de bits" + +#: src/FLTK/flgui.cpp:6090 src/FLTK/flgui.cpp:6422 src/FLTK/flgui.cpp:6440 +msgid "16 bit" +msgstr "16 bit" + +#: src/FLTK/flgui.cpp:6095 src/FLTK/flgui.cpp:6427 src/FLTK/flgui.cpp:6450 +msgid "24 bit" +msgstr "24 bit" + +#: src/FLTK/flgui.cpp:6112 +msgid "Recording Codec Settings" +msgstr "Configurações de Codec de Gravação" + +#: src/FLTK/flgui.cpp:6436 +msgid "WAV" +msgstr "WAV" + +#: src/FLTK/flgui.cpp:6445 +msgid "32 bit" +msgstr "32 bit" + +#: src/FLTK/flgui.cpp:6467 +msgid "butt audio mixer" +msgstr "mixer de áudio do butt" + +#: src/FLTK/flgui.cpp:6483 +msgid "Audio Mixer" +msgstr "Mixer de Ãudio" + +#: src/FLTK/flgui.cpp:6486 src/FLTK/flgui.cpp:6516 src/FLTK/flgui.cpp:6546 +#: src/FLTK/flgui.cpp:6569 src/FLTK/flgui.cpp:6592 +msgid "+0.0 dB" +msgstr "+0.0 dB" + +#: src/FLTK/flgui.cpp:6491 src/FLTK/flgui.cpp:6634 +msgid "" +"Primary\n" +"Device" +msgstr "" +"Dispositivo\n" +"Primário" + +#: src/FLTK/flgui.cpp:6509 src/FLTK/flgui.cpp:6510 src/FLTK/flgui.cpp:6539 +#: src/FLTK/flgui.cpp:6540 +msgid "Mute" +msgstr "Mudo" + +#: src/FLTK/flgui.cpp:6521 src/FLTK/flgui.cpp:6642 +msgid "" +"Secondary\n" +"Device" +msgstr "" +"Dispositivo\n" +"Secundário" + +#: src/FLTK/flgui.cpp:6551 +msgid "" +"Streaming\n" +"Gain" +msgstr "" +"Ganho da\n" +"Transmissão" + +#: src/FLTK/flgui.cpp:6574 +msgid "" +"Recording\n" +"Gain" +msgstr "" +"Ganho de\n" +"Gravação" + +#: src/FLTK/flgui.cpp:6597 +msgid "" +"Master\n" +"Gain" +msgstr "" +"Ganho\n" +"Principal" + +#: src/FLTK/flgui.cpp:6615 +msgid "" +"\n" +"Cross Fader" +msgstr "" +"\n" +"Cross Fader" + +#: src/FLTK/flgui.cpp:6638 +msgid "|" +msgstr "|" + +#: src/FLTK/flgui.cpp:6650 +msgid "Alert" +msgstr "Alerta" + +#: src/FLTK/flgui.cpp:6661 +msgid "&Open the manual" +msgstr "&Abrir o manual" + +#: src/FLTK/flgui.cpp:6665 +msgid "" +"Could not find aac library.\n" +"\n" +"Please follow the instructions in the manual\n" +"for adding aac support." +msgstr "" +"Impossível encontrar a biblioteca aac.\n" +"\n" +"Favor seguir as instruções no manual\n" +"para adicionar suporte ao aac." + +#: src/FLTK/fl_timer_funcs.cpp:318 +#, c-format +msgid "" +"stream sent\n" +"%0.2lfMB" +msgstr "" +"enviando\n" +"%0.2lfMB" + +#: src/FLTK/fl_timer_funcs.cpp:323 +#, c-format +msgid "" +"stream time\n" +"%s" +msgstr "" +"tempo de stream\n" +"%s" + +# Will be shown in the main display and thus +# may only contain ascii-characters. When +# in doubt just keep "Listeners". Also the +# string length should not exceed 10 +# characters. +#: src/FLTK/fl_timer_funcs.cpp:330 +#, c-format +msgid "" +"On Air\n" +"Listeners %5d" +msgstr "" +"No Ar\n" +"Ouvintes %5d" + +# Will be shown in the main display and thus +# may only contain ascii-characters. When +# in doubt just keep "Listeners>". Also the +# string length should not exceed 10 +# characters. +#: src/FLTK/fl_timer_funcs.cpp:333 +#, c-format +msgid "" +"On Air\n" +"Listeners>%5d" +msgstr "" +"No Ar\n" +"Ouvintes>%5d" + +# Will be shown in the main display and thus +# may only contain ascii-characters. When +# in doubt just keep "On Air" +#: src/FLTK/fl_timer_funcs.cpp:337 +#, c-format +msgid "On Air" +msgstr "No Ar" + +#: src/FLTK/fl_timer_funcs.cpp:343 +#, c-format +msgid "" +"record time\n" +"%s" +msgstr "" +"tempo gravando\n" +"%s" + +#: src/FLTK/fl_timer_funcs.cpp:348 +#, c-format +msgid "" +"record size\n" +"%0.2lfMB" +msgstr "" +"tamanho gravado\n" +"%0.2lfMB" + +#: src/FLTK/fl_timer_funcs.cpp:479 +#, c-format +msgid "" +"ERROR: Connection lost\n" +"reconnecting in %d seconds..." +msgstr "" +"ERRO: Conexão perdida\n" +"reconectando em %d segundos..." + +#: src/FLTK/fl_timer_funcs.cpp:483 +msgid "" +"ERROR: Connection lost\n" +"reconnecting..." +msgstr "" +"ERRO: Conexão perdida\n" +"reconectando..." + +#: src/FLTK/fl_timer_funcs.cpp:608 +msgid "Listeners" +msgstr "Ouvintes" + +#: src/FLTK/fl_timer_funcs.cpp:674 +msgid "" +"Could not find a file extension in current filename\n" +"Automatic file splitting is deactivated" +msgstr "" +"Impossível encontrar uma extensão de arquivo no nome atual\n" +"A divisão automática de arquivos está desativada" + +#: src/FLTK/fl_timer_funcs.cpp:704 +msgid "" +"Could not find a valid filename for next file\n" +"butt keeps recording to current file" +msgstr "" +"Impossível achar um nome de arquivo válido para o próximo arquivo\n" +"o butt manterá a gravação no arquivo atual" + +#: src/FLTK/fl_timer_funcs.cpp:717 src/FLTK/fl_callbacks.cpp:1033 +#, c-format +msgid "" +"Could not open:\n" +"%s" +msgstr "" +"Impossível abrir:\n" +"%s" + +#: src/FLTK/fl_timer_funcs.cpp:721 src/port_audio.cpp:938 +msgid "Recording to:" +msgstr "Gravando em:" + +#: src/FLTK/fl_timer_funcs.cpp:964 +#, c-format +msgid "" +"Warning\n" +"Could not open: %s.\n" +"Will retry in 5 seconds" +msgstr "" +"Aviso\n" +"Impossível abrir %s.\n" +"Nova tentativa em 5 segundos" + +#: src/FLTK/fl_callbacks.cpp:145 +msgid "connecting" +msgstr "conectando" + +#: src/FLTK/fl_callbacks.cpp:187 +msgid "" +"Error: No server entry found.\n" +"Please add a server in the settings-window." +msgstr "" +"Erro: Nenhuma entrada de servidor encontrada.\n" +"Adicione um servidor na janela de configurações." + +#: src/FLTK/fl_callbacks.cpp:192 +msgid "" +"Error: ogg vorbis encoder doesn't support bitrates\n" +"lower than 48kbit" +msgstr "" +"Erro: o encoder de ogg vorbis não suporta taxas de bits\n" +"menores que 48kbit" + +#: src/FLTK/fl_callbacks.cpp:200 +#, c-format +msgid "Warning: %s is not supported by every Shoutcast version" +msgstr "Aviso: %s não é suportado por todas versões do Shoutcast" + +#: src/FLTK/fl_callbacks.cpp:204 +msgid "Error: FLAC is not supported by ShoutCast" +msgstr "Erro: ShoutCast não suporta FLAC" + +#: src/FLTK/fl_callbacks.cpp:211 +#, c-format +msgid "Error: Radio.co supports only mp3 and aac" +msgstr "Erro: O Radio.co suporta apenas mp3 e aac" + +#: src/FLTK/fl_callbacks.cpp:219 +#, c-format +msgid "Error: WebRTC only supports opus" +msgstr "Erro: WebRTC suporta apenas opus" + +#: src/FLTK/fl_callbacks.cpp:226 +#, c-format +msgid "Connecting to %s via %s ..." +msgstr "Conectando a %s via %s ..." + +#: src/FLTK/fl_callbacks.cpp:229 +#, c-format +msgid "Connecting to %s:%u ..." +msgstr "Conectando a %s:%u ..." + +#: src/FLTK/fl_callbacks.cpp:232 +#, c-format +msgid "Connecting to %s:%u (%u) ..." +msgstr "Conectando a %s:%u (%u) ..." + +#: src/FLTK/fl_callbacks.cpp:328 +msgid "Connection established" +msgstr "Conexão estabelecida" + +#: src/FLTK/fl_callbacks.cpp:342 src/FLTK/fl_callbacks.cpp:4275 +#: src/FLTK/fl_callbacks.cpp:4281 +msgid "no" +msgstr "não" + +#: src/FLTK/fl_callbacks.cpp:342 src/FLTK/fl_callbacks.cpp:4275 +#: src/FLTK/fl_callbacks.cpp:4281 +msgid "yes" +msgstr "sim" + +#: src/FLTK/fl_callbacks.cpp:344 +#, c-format +msgid "Device 1:\t%s\n" +msgstr "Dispositivo 1:\t%s\n" + +#: src/FLTK/fl_callbacks.cpp:345 +#, c-format +msgid "Device 2:\t%s\n" +msgstr "Dispositivo 2:\t%s\n" + +#: src/FLTK/fl_callbacks.cpp:396 +#, c-format +msgid "Connected to: %s" +msgstr "Conectado a %s" + +#: src/FLTK/fl_callbacks.cpp:567 src/FLTK/fl_callbacks.cpp:1669 +msgid "The custom listener URL must start with http:// or https://" +msgstr "A URL deve se iniciar em http:// ou https://" + +#: src/FLTK/fl_callbacks.cpp:574 src/FLTK/fl_callbacks.cpp:1676 +msgid "" +"No mountpoint specified\n" +"Setting mountpoint to \"stream\"" +msgstr "" +"Nenhum ponto de montagem definido\n" +"Definindo o ponto de montagem como \"stream\"" + +#: src/FLTK/fl_callbacks.cpp:578 src/FLTK/fl_callbacks.cpp:1680 +msgid "" +"No user specified\n" +"Setting user to \"source\"" +msgstr "" +"Nenhum usuário definido\n" +"Definindo usuário como \"source\"" + +#: src/FLTK/fl_callbacks.cpp:586 src/FLTK/fl_callbacks.cpp:1688 +msgid "" +"Unsupported listener URL.\n" +"The listener URL must end with status-json.xsl, 7.xsl, 7.html or contain " +"stats?sid" +msgstr "" +"URL de ouvinte não suportada.\n" +"A URL de ouvinte deve terminar com status-json.xsl, 7.xsl, 7.html ou conter " +"stats?sid" + +#: src/FLTK/fl_callbacks.cpp:592 src/FLTK/fl_callbacks.cpp:1694 +#: src/FLTK/fl_callbacks.cpp:1857 src/FLTK/fl_callbacks.cpp:2545 +msgid "No name specified" +msgstr "Nenhum nome definido" + +#: src/FLTK/fl_callbacks.cpp:597 src/FLTK/fl_callbacks.cpp:1699 +msgid "" +"The number of characters of all your server names exeeds 1000\n" +"Please reduce the number of characters of each server name" +msgstr "" +"O número de caracteres de todos os nomes de servidor excedem 1000\n" +"Reduza o número de caracteres de cada nome de servidor" + +#: src/FLTK/fl_callbacks.cpp:603 src/FLTK/fl_callbacks.cpp:1705 +msgid "Newline characters and [];/\\ are not allowed within the server name" +msgstr "" +"Caracteres de quebra de linha e [];/\\ não são permitidos para o nome de " +"servidor" + +#: src/FLTK/fl_callbacks.cpp:609 src/FLTK/fl_callbacks.cpp:1710 +msgid "No address specified" +msgstr "Nenhum endereço definido" + +#: src/FLTK/fl_callbacks.cpp:613 src/FLTK/fl_callbacks.cpp:1714 +msgid "No password specified" +msgstr "Nenhuma senha especificada" + +#: src/FLTK/fl_callbacks.cpp:617 src/FLTK/fl_callbacks.cpp:1718 +msgid "No port specified" +msgstr "Nenhuma porta definida" + +#: src/FLTK/fl_callbacks.cpp:621 src/FLTK/fl_callbacks.cpp:1722 +msgid "" +"Invalid port number\n" +"The port number must be between 1 and 65535" +msgstr "" +"Número de porta inválido\n" +"O número da porta deve estar entre 1 e 65535" + +#: src/FLTK/fl_callbacks.cpp:628 src/FLTK/fl_callbacks.cpp:1729 +msgid "No WHIP URL specified" +msgstr "Nenhuma URL WHIP especificada" + +#: src/FLTK/fl_callbacks.cpp:637 src/FLTK/fl_callbacks.cpp:1740 +#: src/FLTK/fl_callbacks.cpp:2564 +msgid "Server name already exist!" +msgstr "Nome de servidor já existe!" + +#: src/FLTK/fl_callbacks.cpp:966 +msgid "stop recording?" +msgstr "parar gravação?" + +#: src/FLTK/fl_callbacks.cpp:966 src/FLTK/fl_funcs.cpp:1462 +msgid "No" +msgstr "Não" + +#: src/FLTK/fl_callbacks.cpp:966 +msgid "Yes" +msgstr "Sim" + +#: src/FLTK/fl_callbacks.cpp:1005 +msgid "No recording filename specified" +msgstr "Nenhum arquivo de gravação especificado" + +#: src/FLTK/fl_callbacks.cpp:1015 +#, c-format +msgid "%s already exists!" +msgstr "%s já existe!" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "overwrite" +msgstr "sobrescrever" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "cancel" +msgstr "cancelar" + +#: src/FLTK/fl_callbacks.cpp:1015 +msgid "append" +msgstr "acrescentar" + +#: src/FLTK/fl_callbacks.cpp:1021 +msgid "Recording canceled" +msgstr "Gravação cancelada" + +#: src/FLTK/fl_callbacks.cpp:1090 src/FLTK/fl_funcs.cpp:1308 +msgid "Hide log" +msgstr "Ocultar log" + +#: src/FLTK/fl_callbacks.cpp:1123 +msgid "Add Server" +msgstr "Adicionar servidor" + +#: src/FLTK/fl_callbacks.cpp:1176 +msgid "Edit Server" +msgstr "Editar servidor" + +#: src/FLTK/fl_callbacks.cpp:1181 +msgid "Radio.co stations cannot be edited." +msgstr "Estações Radio.co não podem ser editadas." + +#: src/FLTK/fl_callbacks.cpp:1267 +msgid "Add Server Infos" +msgstr "Adicionar informações de Servidor" + +#: src/FLTK/fl_callbacks.cpp:1302 +msgid "Song update failed: WebRTC does not support song names" +msgstr "Falha ao atualizar música: O WebRTC não suporta nomes de músicas" + +#: src/FLTK/fl_callbacks.cpp:1345 +#, c-format +msgid "" +"Updated songname to:\n" +"%s\n" +msgstr "" +"Nome da música atualizado para:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:1354 +msgid "Updating songname failed" +msgstr "Atualização do nome da música falhou" + +#: src/FLTK/fl_callbacks.cpp:1428 +#, c-format +msgid "Audio buffer has been set to %d ms" +msgstr "O buffer de audio foi ajustado para %d ms" + +#: src/FLTK/fl_callbacks.cpp:1592 +msgid "" +"butt will open Radio.co in a new browser window.\n" +"\n" +"Login to Radio.co and allow butt access to your account." +msgstr "" +"o butt irá abrir o Radio.co em uma nova janela do navegador.\n" +"\n" +"Realize o login na Radio.co para permitir ao butt acesso à sua conta." + +#: src/FLTK/fl_callbacks.cpp:1618 +msgid "Hide" +msgstr "Ocultar" + +#: src/FLTK/fl_callbacks.cpp:1638 +msgid "Could not revoke trust for certificate" +msgstr "Impossível revogar o certificado" + +#: src/FLTK/fl_callbacks.cpp:1862 +msgid "" +"The number of characters of all your icy names exeeds 1000\n" +"Please reduce the count of characters of each icy name" +msgstr "" +"O número de caracteres dos seus nomes icy excede 1000\n" +"Reduza a quantidade de caracteres de cada nome icy" + +#: src/FLTK/fl_callbacks.cpp:1868 src/FLTK/fl_callbacks.cpp:2557 +msgid "Newline characters and [];/\\ are not allowed within the icy name" +msgstr "Caracteres de quebra de linha e [];/\\ não são permitidas no nome icy" + +#: src/FLTK/fl_callbacks.cpp:1877 +msgid "Icy name already exist!" +msgstr "Nome icy já existe!" + +#: src/FLTK/fl_callbacks.cpp:2002 src/FLTK/fl_callbacks.cpp:2015 +#: src/FLTK/fl_callbacks.cpp:2029 src/FLTK/fl_callbacks.cpp:2044 +#: src/FLTK/fl_callbacks.cpp:2233 src/FLTK/fl_callbacks.cpp:2246 +#: src/FLTK/fl_callbacks.cpp:2260 src/FLTK/fl_callbacks.cpp:2275 +#: src/FLTK/fl_callbacks.cpp:2290 +msgid "" +"Warning:\n" +"The stream Sample-/Bitrate combination is invalid" +msgstr "" +"Atenção:\n" +"A combinação de Sample/Taxa de Bits da transmissão é inválida" + +#: src/FLTK/fl_callbacks.cpp:2008 src/FLTK/fl_callbacks.cpp:2021 +#: src/FLTK/fl_callbacks.cpp:2035 src/FLTK/fl_callbacks.cpp:2050 +msgid "The previous values have been set\n" +msgstr "Os valores anteriores foram atribuídos\n" + +#: src/FLTK/fl_callbacks.cpp:2056 +#, c-format +msgid "Stream bitrate set to: %dk" +msgstr "Taxa de bits da transmissão configurada para: %dk" + +#: src/FLTK/fl_callbacks.cpp:2142 src/FLTK/fl_callbacks.cpp:2155 +#: src/FLTK/fl_callbacks.cpp:2169 src/FLTK/fl_callbacks.cpp:2184 +#: src/FLTK/fl_callbacks.cpp:2313 src/FLTK/fl_callbacks.cpp:2326 +#: src/FLTK/fl_callbacks.cpp:2340 src/FLTK/fl_callbacks.cpp:2355 +#: src/FLTK/fl_callbacks.cpp:2369 +msgid "" +"Warning:\n" +"The record Sample-/Bitrate combination is invalid" +msgstr "" +"Aviso:\n" +"A combinação de Sample/Bitrate de gravação é inválida" + +#: src/FLTK/fl_callbacks.cpp:2148 src/FLTK/fl_callbacks.cpp:2161 +#: src/FLTK/fl_callbacks.cpp:2175 src/FLTK/fl_callbacks.cpp:2190 +#: src/FLTK/fl_callbacks.cpp:2239 src/FLTK/fl_callbacks.cpp:2252 +#: src/FLTK/fl_callbacks.cpp:2266 src/FLTK/fl_callbacks.cpp:2281 +#: src/FLTK/fl_callbacks.cpp:2296 src/FLTK/fl_callbacks.cpp:2319 +#: src/FLTK/fl_callbacks.cpp:2332 src/FLTK/fl_callbacks.cpp:2346 +#: src/FLTK/fl_callbacks.cpp:2361 src/FLTK/fl_callbacks.cpp:2375 +msgid "The previous values have been set" +msgstr "Os valores anteriores foram atribuídos" + +#: src/FLTK/fl_callbacks.cpp:2196 +#, c-format +msgid "Record bitrate set to: %dk" +msgstr "Taxa de bits de gravação setado para: %dk" + +#: src/FLTK/fl_callbacks.cpp:2383 +#, c-format +msgid "Samplerate set to: %dHz" +msgstr "Samplerate setado para: %dHz" + +#: src/FLTK/fl_callbacks.cpp:2449 +msgid "Channels set to: stereo" +msgstr "Canais configurados como: estéreo" + +#: src/FLTK/fl_callbacks.cpp:2512 +msgid "Channels set to: mono" +msgstr "Canais configurados como: mono" + +#: src/FLTK/fl_callbacks.cpp:2551 +msgid "" +"The number of characters of all your icy names exeeds 1000\n" +"Please reduce the number of characters of each icy name" +msgstr "" +"O número de caracteres de todos seus nomes icy excedem 1000\n" +"Reduza o número de caracteres de cada nome icy" + +#: src/FLTK/fl_callbacks.cpp:2659 +msgid "Edit Server Infos" +msgstr "Editar Informações do Servidor" + +#: src/FLTK/fl_callbacks.cpp:2696 src/FLTK/fl_callbacks.cpp:2749 +msgid "" +"Primary and secondary audio device are both ASIO devices.\n" +"You can not use two ASIO devices at the same time.\n" +"Please select a different device.\n" +msgstr "" +"Ambos os dispositivos de áudio primário e secundário são ASIO.\n" +"Não é possível utilizar dois dispositivos ASIO ao mesmo tempo.\n" +"Favor selecionar um dispositivo diferente.\n" + +#: src/FLTK/fl_callbacks.cpp:2717 src/FLTK/fl_callbacks.cpp:4155 +msgid "" +"butt could not open selected audio device.\n" +"Please try another device.\n" +msgstr "" +"butt não conseguiu abrir o dispositivo de áudio selecionado.\n" +"Por favor, tente outro dispositivo.\n" + +#: src/FLTK/fl_callbacks.cpp:2732 +#, c-format +msgid "" +"Primary device:\n" +"%s\n" +msgstr "" +"Dispositivo primário:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:2769 +msgid "" +"butt could not open secondary audio device.\n" +"Please try another device.\n" +msgstr "" +"o butt não pode abrir o dispositivo de áudio secundário.\n" +"Favor tentar outro dispositivo.\n" + +#: src/FLTK/fl_callbacks.cpp:2783 +#, c-format +msgid "" +"Secondary device:\n" +"%s\n" +msgstr "" +"Dispositivo secundário:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:2894 src/FLTK/fl_callbacks.cpp:3072 +msgid "" +"MP3 encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"O encoder de MP3 não suporta a combinação\n" +"de Sample/Taxa de bits atual" + +#: src/FLTK/fl_callbacks.cpp:2915 +msgid "Stream codec set to mp3" +msgstr "Codec de transmissão setado para mp3" + +#: src/FLTK/fl_callbacks.cpp:2927 src/FLTK/fl_callbacks.cpp:3112 +msgid "" +"OGG Vorbis encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"O encoder de OGG Vorbis não suporta a combinação\n" +"de Sample/Taxa de bits atual" + +#: src/FLTK/fl_callbacks.cpp:2948 +msgid "Stream codec set to ogg/vorbis" +msgstr "Codec de transmissão setado para ogg/vorbis" + +#: src/FLTK/fl_callbacks.cpp:2959 src/FLTK/fl_callbacks.cpp:3151 +msgid "" +"Opus encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"O encoder de Opus não suporta a combinação\n" +"de Sample/Taxa de bits atual" + +#: src/FLTK/fl_callbacks.cpp:2979 +msgid "Stream codec set to opus" +msgstr "Codec de transmissão setado para opus" + +#: src/FLTK/fl_callbacks.cpp:3011 src/FLTK/fl_callbacks.cpp:3213 +msgid "" +"AAC encoder doesn't support current\n" +"Sample-/Bitrate combination" +msgstr "" +"O encoder de AAC não suporta a combinação\n" +"de Sample/Taxa de bits atual" + +#: src/FLTK/fl_callbacks.cpp:3032 +msgid "Stream codec set to aac" +msgstr "Codec de transmissão setado para aac" + +#: src/FLTK/fl_callbacks.cpp:3042 src/FLTK/fl_callbacks.cpp:3252 +msgid "ERROR: While initializing flac settings" +msgstr "ERRO: Ao inicializar as configurações de flac" + +#: src/FLTK/fl_callbacks.cpp:3060 +msgid "Stream codec set to flac" +msgstr "Codec de transmissão setado para flac" + +#: src/FLTK/fl_callbacks.cpp:3101 +msgid "Record codec set to mp3" +msgstr "Codec de gravação setado para mp3" + +#: src/FLTK/fl_callbacks.cpp:3140 +msgid "Record codec set to ogg/vorbis" +msgstr "Codec de gravação setado para ogg/vorbis" + +#: src/FLTK/fl_callbacks.cpp:3179 +msgid "Record codec set to opus" +msgstr "Codec de gravação setado para opus" + +#: src/FLTK/fl_callbacks.cpp:3242 +msgid "Record codec set to aac" +msgstr "Codec de gravação setado para aac" + +#: src/FLTK/fl_callbacks.cpp:3278 +msgid "Record codec set to flac" +msgstr "Codec de gravação setado para flac" + +#: src/FLTK/fl_callbacks.cpp:3294 +msgid "Record codec set to wav" +msgstr "Codec de gravação setado para wav" + +#: src/FLTK/fl_callbacks.cpp:3329 +msgid "Select certificate file..." +msgstr "Selecionar certificado..." + +#: src/FLTK/fl_callbacks.cpp:3334 src/FLTK/fl_callbacks.cpp:3355 +#: src/FLTK/fl_callbacks.cpp:3466 src/FLTK/fl_callbacks.cpp:3556 +#: src/FLTK/fl_callbacks.cpp:4109 src/FLTK/fl_callbacks.cpp:4133 +#: src/FLTK/fl_callbacks.cpp:4257 +#, c-format +msgid "ERROR: %s" +msgstr "ERRO: %s" + +#: src/FLTK/fl_callbacks.cpp:3347 +msgid "Select certificate directory..." +msgstr "Selecione a pasta do certificado..." + +#: src/FLTK/fl_callbacks.cpp:3458 +msgid "Record to..." +msgstr "Gravar para..." + +#: src/FLTK/fl_callbacks.cpp:3483 +msgid "File splitting only works if recording is active." +msgstr "Divisão de arquivos só funciona se a gravação estiver ativa." + +#: src/FLTK/fl_callbacks.cpp:3552 +msgid "Select Songfile" +msgstr "Escolher arquivo de música" + +#: src/FLTK/fl_callbacks.cpp:3657 +msgid "Gain control is disabled. Enable in Settings->GUI" +msgstr "O controle de ganho é desativado. Habilitar em Configs->GUI" + +#: src/FLTK/fl_callbacks.cpp:3718 +msgid "select background color" +msgstr "selecione a cor de fundo" + +#: src/FLTK/fl_callbacks.cpp:3728 +msgid "select text color" +msgstr "selecione a cor do texto" + +#: src/FLTK/fl_callbacks.cpp:3761 src/FLTK/fl_callbacks.cpp:3765 +#: src/FLTK/fl_callbacks.cpp:3774 src/FLTK/fl_callbacks.cpp:3778 +msgid "Value must be a number between -54 and 0" +msgstr "Valor deve ser um número entre -54 e 0" + +#: src/FLTK/fl_callbacks.cpp:3788 +msgid "Please restart butt to apply new language." +msgstr "Reinicie o butt para aplicar o novo idioma." + +#: src/FLTK/fl_callbacks.cpp:3867 src/FLTK/fl_callbacks.cpp:3872 +#: src/FLTK/fl_callbacks.cpp:3882 src/FLTK/fl_callbacks.cpp:3887 +msgid "Value must be a number between -90.0 and 0" +msgstr "Valor deve ser um número entre -90.0 e 0" + +#: src/FLTK/fl_callbacks.cpp:4082 +msgid "Recording volume" +msgstr "Volume de gravação" + +#: src/FLTK/fl_callbacks.cpp:4103 +msgid "Export to..." +msgstr "Exportar para..." + +#: src/FLTK/fl_callbacks.cpp:4146 +#, c-format +msgid "Could not import config %s" +msgstr "Impossível importar a configuração %s" + +#: src/FLTK/fl_callbacks.cpp:4160 +#, c-format +msgid "Config imported %s" +msgstr "Configuração importada %s" + +#: src/FLTK/fl_callbacks.cpp:4234 +msgid "" +"Could not get update information.\n" +"Reason: Network error" +msgstr "" +"Impossível obter as informações de atualização.\n" +"Motivo: Erro de rede" + +#: src/FLTK/fl_callbacks.cpp:4237 +msgid "" +"Could not get update information.\n" +"Reason: Unknown answer from server" +msgstr "" +"Impossível obter as informações de atualização.\n" +"Motivo: Resposta desconhecida do servidor" + +#: src/FLTK/fl_callbacks.cpp:4240 +msgid "You have the latest version!" +msgstr "Você possui a última versão!" + +#: src/FLTK/fl_callbacks.cpp:4243 +msgid "" +"Could not get update information.\n" +"Reason: Unknown" +msgstr "" +"Impossível obter as informações de atualização.\n" +"Motivo: Desconhecido" + +#: src/FLTK/fl_callbacks.cpp:4251 +msgid "Select logfile..." +msgstr "Escolher arquivo de log..." + +#: src/FLTK/fl_callbacks.cpp:4273 +msgid "" +"butt is currently streaming.\n" +"Do you really want to close butt now?" +msgstr "" +"o butt está transmitindo.\n" +"Deseja realmente fechar o butt agora?" + +#: src/FLTK/fl_callbacks.cpp:4279 +msgid "" +"butt is currently recording.\n" +"Do you really want to close butt now?" +msgstr "" +"o butt está gravando.\n" +"Deseja realmente fechar o butt agora?" + +#: src/FLTK/fl_callbacks.cpp:4354 +msgid "The URL must start with either http:// or https://" +msgstr "A URL deve se iniciar em http:// ou https://" + +#: src/FLTK/fl_callbacks.cpp:4366 +msgid "Value must be a number between 1 and 1000" +msgstr "Valor deve ser um número entre 1 e 1000" + +#: src/FLTK/fl_callbacks.cpp:5228 src/FLTK/fl_callbacks.cpp:5263 +#: src/FLTK/fl_callbacks.cpp:5298 src/FLTK/fl_callbacks.cpp:5333 +#: src/FLTK/fl_callbacks.cpp:5368 src/FLTK/fl_callbacks.cpp:5859 +#: src/FLTK/fl_callbacks.cpp:5894 src/FLTK/fl_callbacks.cpp:5929 +#: src/FLTK/fl_callbacks.cpp:5964 src/FLTK/fl_callbacks.cpp:5999 +msgid "The encoder could not be initialized with the provided parameters." +msgstr "Não foi possível iniciar o encoder com os parâmetros fornecidos." + +#: src/FLTK/fl_callbacks.cpp:5246 src/FLTK/fl_callbacks.cpp:5877 +msgid "The value must be between 0.001 kHz and 50 kHz" +msgstr "O valor deve estar entre 0.001 kHz e 50 kHz" + +#: src/FLTK/fl_callbacks.cpp:5281 src/FLTK/fl_callbacks.cpp:5316 +#: src/FLTK/fl_callbacks.cpp:5351 src/FLTK/fl_callbacks.cpp:5912 +#: src/FLTK/fl_callbacks.cpp:5947 src/FLTK/fl_callbacks.cpp:5982 +msgid "The value must be between 0.001 kHz and 16 kHz" +msgstr "O valor deve estar entre 0.001 kHz e 16 kHz" + +#: src/FLTK/fl_callbacks.cpp:6328 +msgid "MIDI device could not be opened." +msgstr "Dispositivo MIDI não pôde ser aberto." + +#: src/FLTK/fl_callbacks.cpp:6334 +#, c-format +msgid "" +"MIDI device:\n" +"%s\n" +msgstr "" +"Dispositivo MIDI:\n" +"%s\n" + +#: src/FLTK/fl_callbacks.cpp:6339 +msgid "MIDI device could not be started." +msgstr "Dispositivo MIDI não pôde ser iniciado." + +#: src/FLTK/fl_callbacks.cpp:6344 +msgid "MIDI support disabled\n" +msgstr "Suporte MIDI desabilitado\n" + +#: src/FLTK/fl_callbacks.cpp:6406 +msgid "The CC value must be between 0 and 127" +msgstr "O valor CC deve estar entre 0 e 127" + +#: src/FLTK/fl_callbacks.cpp:6429 +msgid "Waiting..." +msgstr "Aguardando..." + +#: src/FLTK/fl_funcs.cpp:193 +msgid "Disabled" +msgstr "Desabilitado" + +#: src/FLTK/fl_funcs.cpp:335 +#, c-format +msgid "%d seconds" +msgstr "%d segundos" + +#: src/FLTK/fl_funcs.cpp:386 +msgid "Not supported on Windows" +msgstr "Não suportado no Windows" + +#: src/FLTK/fl_funcs.cpp:808 +msgid "Start/Stop broadcasting" +msgstr "Iniciar/Parar transmissão" + +#: src/FLTK/fl_funcs.cpp:809 +msgid "Start/Stop recording" +msgstr "Iniciar/Parar gravação" + +#: src/FLTK/fl_funcs.cpp:811 +msgid "Streaming Gain" +msgstr "Ganho da Transmissão" + +#: src/FLTK/fl_funcs.cpp:812 +msgid "Recording Gain" +msgstr "Ganho da Gravação" + +#: src/FLTK/fl_funcs.cpp:813 +msgid "Primary Device Gain" +msgstr "Dispositivo Primário" + +#: src/FLTK/fl_funcs.cpp:814 +msgid "Secondary Device Gain" +msgstr "Dispositivo Secundário" + +#: src/FLTK/fl_funcs.cpp:815 +msgid "Cross fader" +msgstr "Cross fader" + +#: src/FLTK/fl_funcs.cpp:816 +msgid "Mute/Unmute Primary Device" +msgstr "Ativar/Desativar mudo no Dispositivo Primário" + +#: src/FLTK/fl_funcs.cpp:817 +msgid "Mute/Unmute Secondary Device" +msgstr "Ativar/Desativar mudo no Dispositivo Secundário" + +#: src/FLTK/fl_funcs.cpp:818 +msgid "Start broadcasting" +msgstr "Iniciar transmissão" + +#: src/FLTK/fl_funcs.cpp:819 +msgid "Stop broadcasting" +msgstr "Parar transmissão" + +#: src/FLTK/fl_funcs.cpp:820 +msgid "Start recording" +msgstr "Iniciar gravação" + +#: src/FLTK/fl_funcs.cpp:821 +msgid "Stop recording" +msgstr "Parar gravação" + +#: src/FLTK/fl_funcs.cpp:870 +msgid "dev. not supported" +msgstr "disp. não suportado" + +#: src/FLTK/fl_funcs.cpp:1087 +#, c-format +msgid "" +"Could not create recording folder:\n" +"%s\n" +"Please make sure the folder contains only valid format specifiers." +msgstr "" +"Impossível criar pasta de gravação\n" +"%s\n" +"Certifique-se de que a pasta tenha apenas especificadores de formato válidos." + +#: src/FLTK/fl_funcs.cpp:1102 +#, c-format +msgid "Could not create recording folder %s\n" +msgstr "Não foi possível escrever no arquivo: %s\n" + +#: src/FLTK/fl_funcs.cpp:1111 +#, c-format +msgid "" +"Could not create recording file:\n" +"%s\n" +"Please make sure the filename contains only valid format specifiers." +msgstr "" +"Impossível criar pasta de gravação:\n" +"%s\n" +"Certifique-se de que o nome do arquivo tenha apenas especificadores de " +"formato válidos." + +#: src/FLTK/fl_funcs.cpp:1157 +msgid "Could not find a valid filename" +msgstr "Impossível encontrar um nome de arquivo válido" + +#: src/FLTK/fl_funcs.cpp:1462 +msgid "TRUST" +msgstr "CONFIANÇA" + +#: src/icecast.cpp:90 +msgid "" +"\n" +"connect: Could not create network socket" +msgstr "" +"\n" +"conectar: Impossível criar o socket de rede" + +#: src/icecast.cpp:102 +msgid "" +"\n" +"connect: Error resolving server address" +msgstr "" +"\n" +"conectar: Erro ao resolver o endereço do servidor" + +#: src/icecast.cpp:142 +msgid "" +"\n" +"connect: SSL connection timed out. Trying again..." +msgstr "" +"\n" +"conectar: conexão SSL demorou a responder. Tentando novamente..." + +#: src/icecast.cpp:149 +#, c-format +msgid "" +"SSL/TLS certificate verification failed\n" +"Reason: %s\n" +"\n" +"Do you still want to trust this certificate?\n" +"Trusting will be permanent and can be revoked\n" +"in the server settings." +msgstr "" +"Verificação do certificado SSL/TLS falhou\n" +"Motivo: %s\n" +"\n" +"Deseja confiar neste certificado?\n" +"Confiar será permanente e poderá ser revogado\n" +"nas configurações do servidor." + +#: src/icecast.cpp:164 +#, c-format +msgid "" +"\n" +"connect: SSL connection failed\n" +"Reason: %s" +msgstr "" +"\n" +"conectar: conexão SSL falhou\n" +"Motivo: %s" + +#: src/icecast.cpp:320 +msgid "" +"\n" +"connect: connection timed out. Trying again..." +msgstr "" +"\n" +"conctar: tempo de conexão esgotado. Tentando novamente..." + +#: src/icecast.cpp:373 +msgid "" +"\n" +"connect: server answered with 400!\n" +msgstr "" +"\n" +"conectar: servidor respondeu com 400!\n" + +#: src/icecast.cpp:379 +msgid "" +"\n" +"connect: invalid user/password!\n" +msgstr "" +"\n" +"conectar: usuário/senha inválidos!\n" + +#: src/icecast.cpp:402 +msgid "" +"\n" +"connect: server answered with 404!\n" +msgstr "" +"\n" +"conectar: servidor respondeu com 404!\n" + +#: src/icecast.cpp:409 +#, c-format +msgid "" +"\n" +"connect: server answered with %d!\n" +msgstr "" +"\n" +"conectar: servidor respondeu com %d!\n" + +#: src/icecast.cpp:434 +msgid "" +"\n" +"ERROR: Opus is not supported by your\n" +"Icecast server (>=1.4.0 required)!\n" +msgstr "" +"\n" +"ERRO: Opus não é suportado por seu\n" +"servidor Icecast (>=1.4.0 requerida)!\n" + +#: src/icecast.cpp:507 +msgid "" +"\n" +"update_song: could not create network socket" +msgstr "" +"\n" +"atualizar_música: impossível criar o socket do servidor" + +#: src/icecast.cpp:511 +msgid "" +"\n" +"update_song: error resolving server address" +msgstr "" +"\n" +"atualizar_música: erro ao resolver o endereço do servidor" + +#: src/lame_encode.cpp:74 +#, c-format +msgid "unable to init lame params %d" +msgstr "impossível iniciar os parâmetros lame %d" + +#: src/port_audio.cpp:131 +#, c-format +msgid "" +"PortAudio init failed:\n" +"%s\n" +msgstr "" +"Inicialização do PortAudio falhou:\n" +"%s\n" + +#: src/port_audio.cpp:180 +msgid "ERROR: no sound device with input channels found" +msgstr "ERRO: Nenhum dispositivo de som com canais de entrada encontrado" + +#: src/port_audio.cpp:198 src/port_audio.cpp:289 src/port_audio.cpp:1331 +#: src/port_midi.cpp:177 +#, c-format +msgid "Error getting device Info (%d)" +msgstr "Erro obtendo as informações do dispositivo (%d)" + +#: src/port_audio.cpp:241 +#, c-format +msgid "" +"Samplerate not supported: %dHz\n" +"Using default samplerate: %dHz" +msgstr "" +"Taxa de sample não suportada: %dHz\n" +"Usando a taxa padrão: %dHz" + +#: src/port_audio.cpp:258 src/port_audio.cpp:360 +#, c-format +msgid "PA: Format not supported: %s\n" +msgstr "PA: Formato não suportado: %s\n" + +#: src/port_audio.cpp:268 +#, c-format +msgid "error opening sound device: %s" +msgstr "erro ao abrir dispositivo de som: %s" + +#: src/port_audio.cpp:326 +msgid "The selected secondary audio device can not be used" +msgstr "O dispositivo de áudio secundário não pode ser usado" + +#: src/port_audio.cpp:343 src/port_audio.cpp:1452 src/port_audio.cpp:1469 +msgid "ERROR: Could not initialize samplerate converter" +msgstr "ERRO: Impossível inicializar o conversor de taxa de sample" + +#: src/port_audio.cpp:354 +#, c-format +msgid "Samplerate of secondary device is resampled from %dHz to %dHz\n" +msgstr "" +"Taxa de sample do dispositivo secundário é alterada de %dHz para %dHz\n" + +#: src/port_audio.cpp:381 +#, c-format +msgid "error opening secondary sound device: %s" +msgstr "erro ao abrir dispositivo de som secundário: %s" + +#: src/port_audio.cpp:921 +msgid "disconnected\n" +msgstr "desconectado\n" + +#: src/port_audio.cpp:949 +msgid "recording stopped" +msgstr "gravação parada" + +#: src/port_midi.cpp:152 src/port_midi.cpp:211 src/port_midi.cpp:233 +#: src/port_midi.cpp:255 src/port_midi.cpp:282 src/port_midi.cpp:301 +#: src/port_midi.cpp:316 src/port_midi.cpp:341 src/port_midi.cpp:352 +msgid "Error: PortMidi was not initialized." +msgstr "Erro: PortMidi não foi inicializado." + +#: src/port_midi.cpp:262 +#, c-format +msgid "" +"Error: MIDI device %s could not be opened because no MIDI devices were found." +msgstr "" +"Erro: O dispositivo MIDI %s não pôde ser aberto porque não foi encontrado " +"nenhum dispositivo MIDI." + +#: src/port_midi.cpp:269 +#, c-format +msgid "Error: MIDI device %s could not be found." +msgstr "Erro: O dispositivo MIDI %s não foi encontrado." + +#: src/port_midi.cpp:286 +msgid "Error: MIDI thread already active." +msgstr "Erro: Thread MIDI já está ativa." + +#: src/port_midi.cpp:291 +msgid "Error: Could not start MIDI thread." +msgstr "Erro: Impossível iniciar a thread MIDI." + +#: src/shoutcast.cpp:80 +msgid "" +"\n" +"Connect: Could not create network socket" +msgstr "" +"\n" +"Conectar: Impossível criar o socket de rede" + +#: src/shoutcast.cpp:92 +msgid "" +"\n" +"Connect: Error resolving server address" +msgstr "" +"\n" +"Conectar: Erro ao resolver o endereço do servidor" + +#: src/shoutcast.cpp:172 +msgid "" +"\n" +"connect: connection timed out. Trying again...\n" +msgstr "" +"\n" +"conectar: tempo de conexão esgotado. Tentando novamente...\n" + +#: src/shoutcast.cpp:189 +msgid "" +"\n" +"Connect: Invalid password!\n" +msgstr "" +"\n" +"Conectar: Senha inválida!\n" + +#: src/shoutcast.cpp:238 +msgid "" +"\n" +"Update song: Could not create network socket" +msgstr "" +"\n" +"Atualizar música: Impossível criar o socket de rede" + +#: src/shoutcast.cpp:242 +msgid "" +"\n" +"Update song: Error resolving server address" +msgstr "" +"\n" +"Atualizar música: Erro resolvendo o endereço do servidor" + +#: src/tls.cpp:159 +msgid "check_host: could not read host name from cert" +msgstr "check_host: impossível ler o nome do host do certificado" + +#: src/tls.cpp:194 +msgid "check_cert: No peer certificate available" +msgstr "checar_cert: Nenhum certificado de par disponível" + +#: src/tls.cpp:207 +msgid "check_cert: X509_check_host failed" +msgstr "check_cert: X509_check_host falhou" + +#: src/tls.cpp:213 +msgid "check_cert: check_host failed" +msgstr "check_cert: check_host falhou" + +#: src/tls.cpp:229 +msgid "calc_cert_hash: No peer certificate available" +msgstr "calc_cert_hash: Nenhum certificado de par disponível" + +#: src/tls.cpp:236 +msgid "calc_cert_hash: Hash calculation failed" +msgstr "calc_cert_hash: Cálculo do hash falhou" + +#: src/tls.cpp:305 +msgid "tls_setup: Could not set cipher list" +msgstr "tls_setup: Impossível setar a lista cifrada" + +#: src/tls.cpp:318 +msgid "tls_setup: SSL_new failed" +msgstr "tls_setup: SSL_new falhou" + +#: src/tls.cpp:324 +msgid "tls_setup: Could not bind socket to SSL" +msgstr "tls_setup: Impossível associar o socket ao SSL" + +#: src/tls.cpp:338 +msgid "tls_setup: SSL_connect read timeout" +msgstr "tls_setup: leitura do SSL_connect esgotada" + +#: src/tls.cpp:344 +msgid "tls_setup: SSL_connect write timeout" +msgstr "tls_setup: escrita do SSL_connect esgotada" + +#: src/tls.cpp:361 +msgid "tls_setup: Cert hash could not be calculated" +msgstr "tls_setup: Hash do certificado não pôde ser calculado" + +#: src/tls.cpp:385 +msgid "tls_send: read timeout" +msgstr "tls_send: leitura esgotada" + +#: src/tls.cpp:392 +msgid "tls_send: write timeout" +msgstr "tls_send: escrita esgotada" + +#: src/tls.cpp:418 +msgid "tls_recv: read timeout" +msgstr "tls_recv: leitura esgotada" + +#: src/tls.cpp:425 +msgid "tls_recv: write timeout" +msgstr "tls_recv: escrita esgotada" + +#~ msgid "Listeners: 99999" +#~ msgstr "Ouvintes: 99999" + +#~ msgid "Resample output" +#~ msgstr "Qualidade de Resample" + +#~ msgid "Resample output to selected sample rate" +#~ msgstr "Selecione a taxa de sample de entrada" + +#, c-format +#~ msgid "" +#~ "error while parsing config. Missing WebRTC WHIP URL entry for server " +#~ "\"%s\".\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "erro ao analisar o config. Falta a entrada WebRTC URL para o servidor " +#~ "\"%s\".\n" +#~ "O butt irá iniciar com as configurações padrão" + +#, fuzzy, c-format +#~ msgid "" +#~ "error while parsing config. Missing WebRTC ICE server entry for server " +#~ "\"%s\".\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "erro ao analisar o config. Falta a entrada da porta do servidor \"%s\".\n" +#~ "O butt irá iniciar com as configurações padrão" + +#, fuzzy +#~ msgid "No ICE server specified" +#~ msgstr "Nenhum nome definido" + +#~ msgid "Text color" +#~ msgstr "Cor do texto" + +#~ msgid "Preset " +#~ msgstr "Predefinição " + +#~ msgid "Volume of Primary Device" +#~ msgstr "Volume do Dispositivo Primário" + +#~ msgid "Volume of Secondary Device" +#~ msgstr "Volume do Dispositivo Secundário" + +#~ msgid "" +#~ "error while parsing config. Illegal value (-1) for num_of_srv.\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "erro ao analisar o config. Valor incorreto (-1) para num_of_srv\n" +#~ "O butt irá iniciar com as configurações padrão" + +#~ msgid "" +#~ "error while parsing config. Illegal value (-1) for num_of_icy.\n" +#~ "butt will start with default settings" +#~ msgstr "" +#~ "erro ao analisar o config. Valor ilegal (-1) para o num_of_icy.\n" +#~ "O butt irá iniciar com as configurações padrão" + +#~ msgid "Dash address has been copied to clipboard." +#~ msgstr "O endereço do Dash foi copiado para o clipboard." + +#~ msgid "Dash" +#~ msgstr "Dash" + +#~ msgid "recording to:" +#~ msgstr "gravando em:" + +#~ msgid "Convert Mono to Stereo" +#~ msgstr "Converter Mono para Estéreo" + +#~ msgid "Copies a mono channel to both stereo channels" +#~ msgstr "Copia um canal mono para ambos os canais estéreo" diff --git a/po/quot.sed b/po/quot.sed new file mode 100644 index 0000000..0122c46 --- /dev/null +++ b/po/quot.sed @@ -0,0 +1,6 @@ +s/"\([^"]*\)"/“\1â€/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“â€/""/g diff --git a/po/remove-potcdate.sin b/po/remove-potcdate.sin new file mode 100644 index 0000000..2436c49 --- /dev/null +++ b/po/remove-potcdate.sin @@ -0,0 +1,19 @@ +# Sed script that remove the POT-Creation-Date line in the header entry +# from a POT file. +# +# The distinction between the first and the following occurrences of the +# pattern is achieved by looking at the hold space. +/^"POT-Creation-Date: .*"$/{ +x +# Test if the hold space is empty. +s/P/P/ +ta +# Yes it was empty. First occurrence. Remove the line. +g +d +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/po/stamp-po b/po/stamp-po new file mode 100644 index 0000000..9788f70 --- /dev/null +++ b/po/stamp-po @@ -0,0 +1 @@ +timestamp diff --git a/src/AskForMicPermission.h b/src/AskForMicPermission.h new file mode 100644 index 0000000..1e1af83 --- /dev/null +++ b/src/AskForMicPermission.h @@ -0,0 +1,14 @@ +// +// AskForMicPermission.h +// butt +// +// Created by Daniel Nöthen on 26.09.20. +// Copyright © 2020 Daniel Nöthen. All rights reserved. +// + +#ifndef AskForMicPermission_h +#define AskForMicPermission_h + +void askForMicPermission(); + +#endif /* AskForMicPermission_h */ diff --git a/src/AskForMicPermission.m b/src/AskForMicPermission.m new file mode 100644 index 0000000..e29292e --- /dev/null +++ b/src/AskForMicPermission.m @@ -0,0 +1,64 @@ +// +// AskForMicPermission.m +// butt +// +// Created by Daniel Nöthen on 26.09.20. +// Copyright © 2020 Daniel Nöthen. All rights reserved. +// + +#import +#import +#import +#import +#import "gettext.h" + + +void showAlert() { + + dispatch_async(dispatch_get_main_queue(), ^{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@(_("Microphone access"))]; + [alert setInformativeText:@(_("butt needs access to your microphone.\n\nPlease go to\nSystem Preferences->Privacy & Security->Microphone\nand activate the check mark next to the butt entry."))]; + [alert addButtonWithTitle:@"Ok"]; + [alert runModal]; + [alert release]; + }); +} + +void askForMicPermission() +{ + if (@available(macOS 10.14, *)) { + // Request permission to access the camera and microphone. + switch ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]) + { + case AVAuthorizationStatusAuthorized: + { + break; + } + case AVAuthorizationStatusNotDetermined: + { + // The app hasn't yet asked the user for microphone access. + [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) { + if (granted) { + } else { + showAlert(); + } + }]; + + break; + } + case AVAuthorizationStatusDenied: + { + // The user has previously denied access. + showAlert(); + return; + } + case AVAuthorizationStatusRestricted: + { + showAlert(); + // The user can't grant access due to restrictions. + return; + } + } + } +} diff --git a/src/Biquad.cpp b/src/Biquad.cpp new file mode 100644 index 0000000..70adc0e --- /dev/null +++ b/src/Biquad.cpp @@ -0,0 +1,179 @@ +// +// Biquad.cpp +// +// Created by Nigel Redmon on 11/24/12 +// EarLevel Engineering: earlevel.com +// Copyright 2012 Nigel Redmon +// +// For a complete explanation of the Biquad code: +// http://www.earlevel.com/main/2012/11/26/biquad-c-source-code/ +// +// License: +// +// This source code is provided as is, without warranty. +// You may copy and distribute verbatim copies of this document. +// You may modify and use this source code to create binary code +// for your own purposes, free or commercial. +// + +// Modifications by melchor629 on 20/08/2016 + +#include +#include "Biquad.h" + +Biquad::Biquad() +{ + type = bq_type_lowpass; + a0 = 1.0; + a1 = a2 = b1 = b2 = 0.0; + Fc = 0.50; + Q = 0.707; + peakGain = 0.0; + z1 = z2 = 0.0; +} + +Biquad::Biquad(int type, double Fc, double Q, double peakGainDB) +{ + setBiquad(type, Fc, Q, peakGainDB); + z1 = z2 = 0.0; +} + +Biquad::~Biquad() {} + +void Biquad::setType(int type) +{ + if (this->type != type) { + this->type = type; + calcBiquad(); + } +} + +void Biquad::setQ(double Q) +{ + if (this->Q != Q) { + this->Q = Q; + calcBiquad(); + } +} + +void Biquad::setFc(double Fc) +{ + if (this->Fc != Fc) { + this->Fc = Fc; + calcBiquad(); + } +} + +void Biquad::setPeakGain(double peakGainDB) +{ + if (this->peakGain != peakGainDB) { + this->peakGain = peakGainDB; + calcBiquad(); + } +} + +void Biquad::setBiquad(int type, double Fc, double Q, double peakGainDB) +{ + this->type = type; + this->Q = Q; + this->Fc = Fc; + this->peakGain = peakGainDB; + calcBiquad(); +} + +void Biquad::calcBiquad(void) +{ + double norm; + double V = pow(10, fabs(peakGain) / 20.0); + double K = tan(M_PI * Fc); + switch (this->type) { + case bq_type_lowpass: + norm = 1 / (1 + K / Q + K * K); + a0 = K * K * norm; + a1 = 2 * a0; + a2 = a0; + b1 = 2 * (K * K - 1) * norm; + b2 = (1 - K / Q + K * K) * norm; + break; + case bq_type_highpass: + norm = 1 / (1 + K / Q + K * K); + a0 = 1 * norm; + a1 = -2 * a0; + a2 = a0; + b1 = 2 * (K * K - 1) * norm; + b2 = (1 - K / Q + K * K) * norm; + break; + case bq_type_bandpass: + norm = 1 / (1 + K / Q + K * K); + a0 = K / Q * norm; + a1 = 0; + a2 = -a0; + b1 = 2 * (K * K - 1) * norm; + b2 = (1 - K / Q + K * K) * norm; + break; + case bq_type_notch: + norm = 1 / (1 + K / Q + K * K); + a0 = (1 + K * K) * norm; + a1 = 2 * (K * K - 1) * norm; + a2 = a0; + b1 = a1; + b2 = (1 - K / Q + K * K) * norm; + break; + case bq_type_peak: + if (peakGain >= 0) { // boost + norm = 1 / (1 + 1 / Q * K + K * K); + a0 = (1 + V / Q * K + K * K) * norm; + a1 = 2 * (K * K - 1) * norm; + a2 = (1 - V / Q * K + K * K) * norm; + b1 = a1; + b2 = (1 - 1 / Q * K + K * K) * norm; + } + else { // cut + norm = 1 / (1 + V / Q * K + K * K); + a0 = (1 + 1 / Q * K + K * K) * norm; + a1 = 2 * (K * K - 1) * norm; + a2 = (1 - 1 / Q * K + K * K) * norm; + b1 = a1; + b2 = (1 - V / Q * K + K * K) * norm; + } + break; + case bq_type_lowshelf: + if (peakGain >= 0) { // boost + norm = 1 / (1 + sqrt(2) * K + K * K); + a0 = (1 + sqrt(2 * V) * K + V * K * K) * norm; + a1 = 2 * (V * K * K - 1) * norm; + a2 = (1 - sqrt(2 * V) * K + V * K * K) * norm; + b1 = 2 * (K * K - 1) * norm; + b2 = (1 - sqrt(2) * K + K * K) * norm; + } + else { // cut + norm = 1 / (1 + sqrt(2 * V) * K + V * K * K); + a0 = (1 + sqrt(2) * K + K * K) * norm; + a1 = 2 * (K * K - 1) * norm; + a2 = (1 - sqrt(2) * K + K * K) * norm; + b1 = 2 * (V * K * K - 1) * norm; + b2 = (1 - sqrt(2 * V) * K + V * K * K) * norm; + } + break; + case bq_type_highshelf: + if (peakGain >= 0) { // boost + norm = 1 / (1 + sqrt(2) * K + K * K); + a0 = (V + sqrt(2 * V) * K + K * K) * norm; + a1 = 2 * (K * K - V) * norm; + a2 = (V - sqrt(2 * V) * K + K * K) * norm; + b1 = 2 * (K * K - 1) * norm; + b2 = (1 - sqrt(2) * K + K * K) * norm; + } + else { // cut + norm = 1 / (V + sqrt(2 * V) * K + K * K); + a0 = (1 + sqrt(2) * K + K * K) * norm; + a1 = 2 * (K * K - 1) * norm; + a2 = (1 - sqrt(2) * K + K * K) * norm; + b1 = 2 * (K * K - V) * norm; + b2 = (V - sqrt(2 * V) * K + K * K) * norm; + } + break; + } + + return; +} diff --git a/src/Biquad.h b/src/Biquad.h new file mode 100644 index 0000000..87f5488 --- /dev/null +++ b/src/Biquad.h @@ -0,0 +1,63 @@ +// +// Biquad.h +// +// Created by Nigel Redmon on 11/24/12 +// EarLevel Engineering: earlevel.com +// Copyright 2012 Nigel Redmon +// +// For a complete explanation of the Biquad code: +// http://www.earlevel.com/main/2012/11/25/biquad-c-source-code/ +// +// License: +// +// This source code is provided as is, without warranty. +// You may copy and distribute verbatim copies of this document. +// You may modify and use this source code to create binary code +// for your own purposes, free or commercial. +// + +// Modifications by melchor629 on 20/08/2016 + +#ifndef Biquad_h +#define Biquad_h + +enum { + bq_type_lowpass = 0, + bq_type_highpass, + bq_type_bandpass, + bq_type_notch, + bq_type_peak, + bq_type_lowshelf, + bq_type_highshelf, +}; + +class Biquad { + public: + Biquad(); + Biquad(int type, double Fc, double Q, double peakGainDB); + ~Biquad(); + void setType(int type); + void setQ(double Q); + void setFc(double Fc); + void setPeakGain(double peakGainDB); + void setBiquad(int type, double Fc, double Q, double peakGain); + float process(float in); + + protected: + void calcBiquad(void); + + int type; + double a0, a1, a2, b1, b2; + double Fc, Q, peakGain; + double z1, z2; +}; + +inline float Biquad::process(float in) +{ + double out = in * a0 + z1; + z1 = in * a1 + z2 - b1 * out; + z2 = in * a2 - b2 * out; + return out; +} + +#endif // Biquad_h diff --git a/src/CurrentTrackOSX.h b/src/CurrentTrackOSX.h new file mode 100644 index 0000000..e49236f --- /dev/null +++ b/src/CurrentTrackOSX.h @@ -0,0 +1,27 @@ +// +// CurrentTrackOSX.h +// butt +// +// Created by Melchor Garau Madrigal on 8/7/15. +// Copyright (c) 2015 Daniel Nöthen. All rights reserved. +// + +#import + +/** + * Gets the current track from iTunes in a string formated as: + * TITLE - ARTIST, or NULL if iTunes is closed or stopped. + */ +const char *getCurrentTrackFromiTunes(int); + +/** + * Gets the current track from Spotify in a string formated as: + * TITLE - ARTIST, or NULL if Spotify is closed or stopped. + */ +const char *getCurrentTrackFromSpotify(int); + +/** + * Gets the current track from VOX in a string formated as: + * TITLE - ARTIST, or NULL if VOX is closed or stopped. + */ +const char *getCurrentTrackFromVOX(int); diff --git a/src/CurrentTrackOSX.m b/src/CurrentTrackOSX.m new file mode 100644 index 0000000..1fdaea2 --- /dev/null +++ b/src/CurrentTrackOSX.m @@ -0,0 +1,90 @@ +// +// CurrentTrackOSX.m +// butt +// +// Created by Melchor Garau Madrigal on 8/7/15. +// Copyright (c) 2015 Daniel Nöthen. All rights reserved. +// + +#import "CurrentTrackOSX.h" +#import "iTunes.h" +#import "Spotify.h" +#import "VOX.h" + +const char* getCurrentTrackFromiTunes(int artist_title_order) { + NSProcessInfo *pInfo = [NSProcessInfo processInfo]; + NSOperatingSystemVersion version = [pInfo operatingSystemVersion]; + + char* ret = NULL; + iTunesApplication *iTunes; + if(version.majorVersion < 11 && version.minorVersion < 15) + iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.itunes"]; + else + iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.music"]; + + if([iTunes isRunning]) { + if([iTunes playerState] != iTunesEPlSStopped) { + NSString* track; + if(artist_title_order == 0) { + track = [NSString stringWithFormat:@"%@ - %@", [[iTunes currentTrack] artist], [[iTunes currentTrack] name]]; + } + else { + track = [NSString stringWithFormat:@"%@ - %@", [[iTunes currentTrack] name], [[iTunes currentTrack] artist]]; + } + ret = (char*) malloc([track lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1); + [track getCString:ret maxLength:([track lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1) encoding:NSUTF8StringEncoding]; + } + } + + return ret; +} + +const char* getCurrentTrackFromSpotify(int artist_title_order) { + char* ret = NULL; + SpotifyApplication *spotify = [SBApplication applicationWithBundleIdentifier:@"com.spotify.client"]; + if([spotify isRunning]) { + if([spotify playerState] != SpotifyEPlSStopped) { + NSString* track; + if(artist_title_order == 0) { + track = [NSString stringWithFormat:@"%@ - %@", [[spotify currentTrack] artist], [[spotify currentTrack] name]]; + } + else { + track = [NSString stringWithFormat:@"%@ - %@", [[spotify currentTrack] name], [[spotify currentTrack] artist]]; + } + ret = (char*) malloc([track lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1); + [track getCString:ret maxLength:([track lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1) encoding:NSUTF8StringEncoding]; + } + } + + return ret; +} + +const char* getCurrentTrackFromVOX(int artist_title_order) { + char* ret = NULL; + VOXApplication *vox = [SBApplication applicationWithBundleIdentifier:@"com.coppertino.Vox"]; + if([vox isRunning]) { + if([vox playerState]) { + NSString* track; + if(artist_title_order == 0) { + track = [NSString stringWithFormat:@"%@ - %@", [vox artist], [vox track]]; + } + else { + track = [NSString stringWithFormat:@"%@ - %@", [vox track], [vox artist]]; + } + ret = (char*) malloc([track lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1); + [track getCString:ret maxLength:([track lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1) encoding:NSUTF8StringEncoding]; + } + } + + return ret; +} + +typedef const char* (*currentTrackFunction)(int); +currentTrackFunction getCurrentTrackFunctionFromId(int i) { + switch(i) { + case 0: return &getCurrentTrackFromiTunes; + case 1: return &getCurrentTrackFromSpotify; + case 2: return &getCurrentTrackFromVOX; + default: return NULL; + } +} diff --git a/src/FLTK/FL/Fl_My_Double_Window.H b/src/FLTK/FL/Fl_My_Double_Window.H new file mode 100644 index 0000000..4c4c37e --- /dev/null +++ b/src/FLTK/FL/Fl_My_Double_Window.H @@ -0,0 +1,96 @@ +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef FL_MY_DOUBLE_WINDOW_H +#define FL_MY_DOUBLE_WINDOW_H + +#include +#include + +#ifdef WIN32 +#include +#include "tray_agent.h" +#include "fl_timer_funcs.h" +#include "fl_callbacks.h" +#elif __APPLE__ +#import +#else +#include +#endif + +class Fl_My_Double_Window : public Fl_Double_Window { + public: + bool is_main_window = false; + bool minimize_to_tray = false; + + void stay_on_top(int ontop) + { +#ifdef WIN32 + SetWindowPos(fl_xid(this), ontop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER); + +#elif __APPLE__ + + if (ontop) { + [fl_xid(this) setLevel:NSFloatingWindowLevel]; + } + else { + [fl_xid(this) setLevel:NSNormalWindowLevel]; + } + +#else // UNIX + XEvent e; + + Atom WM_STATE = XInternAtom(fl_display, "_NET_WM_STATE", 0); + Atom WM_STATE_ABOVE = XInternAtom(fl_display, "_NET_WM_STATE_ABOVE", 0); + + e.xclient.type = ClientMessage; + e.xclient.window = fl_xid(this); + e.xclient.message_type = WM_STATE; + e.xclient.format = 32; + e.xclient.data.l[0] = (long)ontop; + e.xclient.data.l[1] = (long)WM_STATE_ABOVE; + e.xclient.data.l[2] = (long)0; + e.xclient.data.l[3] = (long)0; + e.xclient.data.l[4] = (long)0; + + XSendEvent(fl_display, RootWindow(fl_display, fl_screen), 0, SubstructureNotifyMask | SubstructureRedirectMask, &e); + XFlush(fl_display); +#endif + } + + int handle(int event) + { +#ifdef WIN32 + if (event == FL_HIDE && is_main_window == true && minimize_to_tray == true) { + int ret = tray_agent_send_cmd(TA_MINIMIZE); + if (ret == 0) { + Fl::remove_timeout(&agent_watchdog_timer); + Fl::add_timeout(1, &agent_watchdog_timer); + } + } + return Fl_Double_Window::handle(event); +#else + Fl_Double_Window::handle(event); + return 0; +#endif + } + + Fl_My_Double_Window(int W, int H, const char *l = 0) : Fl_Double_Window(W, H, l) {} + + Fl_My_Double_Window(int X, int Y, int W, int H, const char *l = 0) : Fl_Double_Window(X, Y, W, H, l) {} + + ~Fl_My_Double_Window() { hide(); } +}; + +#endif // FL_MY_DOUBLE_WINDOW_H diff --git a/src/FLTK/FL/Fl_My_Invisible_Box.H b/src/FLTK/FL/Fl_My_Invisible_Box.H new file mode 100644 index 0000000..db5fb55 --- /dev/null +++ b/src/FLTK/FL/Fl_My_Invisible_Box.H @@ -0,0 +1,50 @@ +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef FL_MY_INVISIBLE_BOX +#define FL_MY_INVISIBLE_BOX + +#include +#include + +#include "fl_callbacks.h" + +class Fl_My_Invisible_Box : public Fl_Box { + public: + Fl_My_Invisible_Box(int x, int y, int w, int h, const char *label = 0) : Fl_Box(x, y, w, h, label) { enabled = 0; } + + void disable(void) { enabled = 0; } + + void enable(void) { enabled = 1; } + + int handle(int e) + { + if (enabled == 1) { + switch (e) { + case FL_ENTER: + show_vu_tabs(); + break; + case FL_LEAVE: + hide_vu_tabs(); + break; + } + } + return Fl_Box::handle(e); + } + + private: + int enabled; +}; + +#endif diff --git a/src/FLTK/FL/Fl_My_Native_File_Chooser.H b/src/FLTK/FL/Fl_My_Native_File_Chooser.H new file mode 100644 index 0000000..f7f6eba --- /dev/null +++ b/src/FLTK/FL/Fl_My_Native_File_Chooser.H @@ -0,0 +1,348 @@ +// +// "$Id$" +// +// FLTK native OS file chooser widget +// +// Copyright 1998-2014 by Bill Spitzak and others. +// Copyright 2004 Greg Ercolano. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/** \file + Fl_My_Native_File_Chooser widget. */ + +#ifndef FL_MY_NATIVE_FILE_CHOOSER_H +#define FL_MY_NATIVE_FILE_CHOOSER_H + +// Use Windows' chooser +#ifdef WIN32 +// #define _WIN32_WINNT 0x0501 // needed for OPENFILENAME's 'FlagsEx' +#if defined(FL_LIBRARY) || FLTK_ABI_VERSION < 10304 +#include +#include // OPENFILENAMEW, GetOpenFileName() +#include // BROWSEINFOW, SHBrowseForFolder() +typedef OPENFILENAMEW fl_OPENFILENAMEW; +typedef BROWSEINFOW fl_BROWSEINFOW; +#else +typedef void fl_OPENFILENAMEW; +typedef void fl_BROWSEINFOW; +#endif +#endif + +// Use Apple's chooser +#ifdef __APPLE__ +#define MAXFILTERS 80 +#endif + +// All else falls back to FLTK's own chooser +#if !defined(__APPLE__) && !defined(WIN32) +#include +#else +#include // FL_EXPORT +#endif + +class Fl_FLTK_File_Chooser; +class Fl_GTK_File_Chooser; + +/** + This class lets an FLTK application easily and consistently access + the operating system's native file chooser. Some operating systems + have very complex and specific file choosers that many users want + access to specifically, instead of FLTK's default file chooser(s). + + In cases where there is no native file browser, FLTK's own file browser + is used instead. + + To use this widget, use the following include in your code: + \code + #include + \endcode + + The following example shows how to pick a single file: + \code + // Create and post the local native file chooser + #include + [..] + Fl_My_Native_File_Chooser fnfc; + fnfc.title("Pick a file"); + fnfc.type(Fl_My_Native_File_Chooser::BROWSE_FILE); + fnfc.filter("Text\t*.txt\n" + "C Files\t*.{cxx,h,c}"); + fnfc.directory("/var/tmp"); // default directory to use + // Show native chooser + switch ( fnfc.show() ) { + case -1: printf("ERROR: %s\n", fnfc.errmsg()); break; // ERROR + case 1: printf("CANCEL\n"); break; // CANCEL + default: printf("PICKED: %s\n", fnfc.filename()); break; // FILE CHOSEN + } + \endcode + + The Fl_My_Native_File_Chooser widget transmits UTF-8 encoded filenames to its user. It is + recommended to open files that may have non-ASCII names with the fl_fopen() or + fl_open() utility functions that handle these names in a cross-platform way + (whereas the standard fopen()/open() functions fail on the MSWindows platform + to open files with a non-ASCII name). + + Platform Specific Caveats + + - Under X windows, and if Fl::OPTION_FNFC_USES_GTK has not been switched off, + the widget attempts to use standard GTK file chooser dialogs if they are + available at run-time on the platform, and falls back to use FLTK's Fl_File_Chooser if they are not. + In the latter case, it's best if you call Fl_File_Icon::load_system_icons() + at the start of main(), to enable the nicer looking file browser widgets. + Use the static public attributes of class Fl_File_Chooser to localize + the browser. + - Some operating systems support certain OS specific options; see + Fl_My_Native_File_Chooser::options() for a list. + + \image html Fl_My_Native_File_Chooser.png "The Fl_My_Native_File_Chooser on different platforms." + \image latex Fl_My_Native_File_Chooser.png "The Fl_My_Native_File_Chooser on different platforms" width=14cm + + */ +class FL_EXPORT Fl_My_Native_File_Chooser { + public: + enum Type { + BROWSE_FILE = 0, ///< browse files (lets user choose one file) + BROWSE_DIRECTORY, ///< browse directories (lets user choose one directory) + BROWSE_MULTI_FILE, ///< browse files (lets user choose multiple files) + BROWSE_MULTI_DIRECTORY, ///< browse directories (lets user choose multiple directories) + BROWSE_SAVE_FILE, ///< browse to save a file + BROWSE_SAVE_DIRECTORY ///< browse to save a directory + }; + enum Option { + NO_OPTIONS = 0x0000, ///< no options enabled + SAVEAS_CONFIRM = 0x0001, ///< Show native 'Save As' overwrite confirm dialog + NEW_FOLDER = 0x0002, ///< Show 'New Folder' icon (if supported) + PREVIEW = 0x0004, ///< enable preview mode (if supported) + USE_FILTER_EXT = 0x0008 ///< Chooser filter pilots the output file extension (if supported) + }; + /** Localizable message */ + static const char *file_exists_message; + + public: + Fl_My_Native_File_Chooser(int val = BROWSE_FILE); + ~Fl_My_Native_File_Chooser(); + + // Public methods + void type(int t); + int type() const; + void options(int o); + int options() const; + int count() const; + const char *filename() const; + const char *filename(int i) const; + void directory(const char *val); + const char *directory() const; + void title(const char *t); + const char *title() const; + const char *filter() const; + void filter(const char *f); + int filters() const; + void filter_value(int i); + int filter_value() const; + void preset_file(const char *f); + const char *preset_file() const; + const char *errmsg() const; + int show(); + +#ifdef WIN32 + private: + int _btype; // kind-of browser to show() + int _options; // general options +#if FLTK_ABI_VERSION >= 10304 + fl_OPENFILENAMEW *_ofn_ptr; // GetOpenFileName() & GetSaveFileName() struct + fl_BROWSEINFOW *_binf_ptr; // SHBrowseForFolder() struct + WCHAR *_wpattern; // pattern buffer for filter +#else + fl_OPENFILENAMEW _ofn; + fl_BROWSEINFOW _binf; +#endif + char **_pathnames; // array of pathnames + int _tpathnames; // total pathnames + char *_directory; // default pathname to use + char *_title; // title for window + char *_filter; // user-side search filter + char *_parsedfilt; // filter parsed for Windows dialog + int _nfilters; // number of filters parse_filter counted + char *_preset_file; // the file to preselect + char *_errmsg; // error message + + // Private methods + void errmsg(const char *msg); + + void clear_pathnames(); + void set_single_pathname(const char *s); + void add_pathname(const char *s); + + void ClearOFN(); + void ClearBINF(); + void Win2Unix(char *s); + void Unix2Win(char *s); + int showfile(); + int showdir(); + + void parse_filter(const char *); + void clear_filters(); + void add_filter(const char *, const char *); +#endif + +#ifdef __APPLE__ + private: + int _btype; // kind-of browser to show() + int _options; // general options + void *_panel; + char **_pathnames; // array of pathnames + int _tpathnames; // total pathnames + char *_directory; // default pathname to use + char *_title; // title for window + char *_preset_file; // the 'save as' filename + + char *_filter; // user-side search filter, eg: + // C Files\t*.[ch]\nText Files\t*.txt" + + char *_filt_names; // filter names (tab delimited) + // eg. "C Files\tText Files" + + char *_filt_patt[MAXFILTERS]; + // array of filter patterns, eg: + // _filt_patt[0]="*.{cxx,h}" + // _filt_patt[1]="*.txt" + + int _filt_total; // parse_filter() # of filters loaded + int _filt_value; // index of the selected filter + char *_errmsg; // error message + + // Private methods + void errmsg(const char *msg); + void clear_pathnames(); + void set_single_pathname(const char *s); + int get_saveas_basename(void); + void clear_filters(); + void add_filter(const char *, const char *); + void parse_filter(const char *from); + int post(); + int runmodal(); +#endif + +#if !defined(__APPLE__) && !defined(WIN32) + private: +#if FLTK_ABI_VERSION <= 10302 + int _btype; // kind-of browser to show() + int _options; // general options + int _nfilters; + char *_filter; // user supplied filter + char *_parsedfilt; // parsed filter + int _filtvalue; // selected filter + char *_preset_file; + char *_prevvalue; // Returned filename + char *_directory; + char *_errmsg; // error message +#endif + static int have_looked_for_GTK_libs; + union { + Fl_FLTK_File_Chooser *_x11_file_chooser; + Fl_GTK_File_Chooser *_gtk_file_chooser; + }; +#endif +}; + +#if !defined(__APPLE__) && !defined(WIN32) +class FL_EXPORT Fl_FLTK_File_Chooser { + friend class Fl_My_Native_File_Chooser; + + protected: + int _btype; // kind-of browser to show() + int _options; // general options + int _nfilters; + char *_filter; // user supplied filter + char *_parsedfilt; // parsed filter + int _filtvalue; // selected filter + char *_preset_file; + char *_prevvalue; // Returned filename + char *_directory; + char *_errmsg; // error message + Fl_FLTK_File_Chooser(int val); + virtual ~Fl_FLTK_File_Chooser(); + void errmsg(const char *msg); + int type_fl_file(int); + void parse_filter(); + int exist_dialog(); + Fl_File_Chooser *_file_chooser; + virtual void type(int); + int type() const; + void options(int); + int options() const; + virtual int count() const; + virtual const char *filename() const; + virtual const char *filename(int i) const; + void directory(const char *val); + const char *directory() const; + virtual void title(const char *); + virtual const char *title() const; + const char *filter() const; + void filter(const char *); + int filters() const; + void filter_value(int i); + int filter_value() const; + void preset_file(const char *); + const char *preset_file() const; + const char *errmsg() const; + virtual int show(); +}; + +class FL_EXPORT Fl_GTK_File_Chooser : public Fl_FLTK_File_Chooser { + friend class Fl_My_Native_File_Chooser; + + private: + typedef struct _GtkWidget GtkWidget; + typedef struct _GtkFileFilterInfo GtkFileFilterInfo; + struct pair { + Fl_GTK_File_Chooser *running; // the running Fl_GTK_File_Chooser + const char *filter; // a filter string of the chooser + pair(Fl_GTK_File_Chooser *c, const char *f) + { + running = c; + filter = strdup(f); + }; + ~pair() { free((char *)filter); }; + }; + GtkWidget *gtkw_ptr; // used to hold a GtkWidget* without pulling GTK into everything... + void *gtkw_slist; // used to hold a GLib GSList... + unsigned gtkw_count; // number of files read back - if any + mutable char *gtkw_filename; // last name we read back + char *gtkw_title; // the title to be applied to the dialog + const char *previous_filter; + + int fl_gtk_chooser_wrapper(); // method that wraps the GTK widget + Fl_GTK_File_Chooser(int val); + virtual ~Fl_GTK_File_Chooser(); + static int did_find_GTK_libs; + static void probe_for_GTK_libs(void); + virtual void type(int); + virtual int count() const; + virtual const char *filename() const; + virtual const char *filename(int i) const; + virtual void title(const char *); + virtual const char *title() const; + virtual int show(); + void changed_output_type(const char *filter); + + static int custom_gtk_filter_function(const GtkFileFilterInfo *, Fl_GTK_File_Chooser::pair *); + static void free_pair(pair *p); +}; +#endif // !defined(__APPLE__) && !defined(WIN32) + +#endif /*FL_NATIVE_FILE_CHOOSER_H*/ + +// +// End of "$Id$". +// diff --git a/src/FLTK/FL/Fl_My_Value_Slider.H b/src/FLTK/FL/Fl_My_Value_Slider.H new file mode 100644 index 0000000..55330bc --- /dev/null +++ b/src/FLTK/FL/Fl_My_Value_Slider.H @@ -0,0 +1,250 @@ +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef FL_MY_VALUE_SLIDER +#define FL_MY_VALUE_SLIDER + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gettext.h" + +class Fl_My_Value_Slider; + +// FLOATING TIP WINDOW +class TipWin : public Fl_Menu_Window { + char tip[40]; + + public: + TipWin() : Fl_Menu_Window(1, 1) + { // will autosize + strcpy(tip, "X.XX"); + set_override(); + end(); + } + void draw(void) + { + draw_box(FL_BORDER_BOX, 0, 0, w(), h(), Fl_Color(175)); + fl_color(FL_BLACK); + fl_font(labelfont(), labelsize()); + fl_draw(tip, 3, 3, w() - 6, h() - 6, Fl_Align(FL_ALIGN_LEFT | FL_ALIGN_WRAP)); + show(); + } + void value(char *t) + { + strncpy(tip, t, sizeof(tip) - 1); + // Recalc size of window + fl_font(labelfont(), labelsize()); + int W = w(), H = h(); + fl_measure(tip, W, H, 0); + W += 8; + size(W, H); + redraw(); + } +}; + +class My_Value_Input : public Fl_Value_Input { + public: + My_Value_Input(int x, int y, int w, int h, const char *label = 0) : Fl_Value_Input(x, y, w, h, label) {} + + void (*custom_callback)(Fl_Widget *, void *); + void *data = NULL; + + int handle(int e) + { + switch (e) { + case FL_KEYDOWN: + if (Fl::event_key() == FL_Enter) { + custom_callback(this, data); + return 1; + } + break; + } + return Fl_Value_Input::handle(e); + } +}; + +// VALUE SLIDER WITH FLOATING TIP WINDOW +class Fl_My_Value_Slider : public Fl_Slider { + TipWin *tipwin; + Fl_Window *window_value; + My_Value_Input *input_value; + + public: + float default_value = 0.0; + bool hide_tipwin = false; + + Fl_My_Value_Slider(int x, int y, int w, int h, const char *l = 0) : Fl_Slider(x, y, w, h, l) + { + // type(FL_HORIZONTAL); + + Fl_Group *save = Fl_Group::current(); // save current widget.. + tipwin = new TipWin(); // ..because this trashes it + tipwin->hide(); + create_value_window(); + Fl_Group::current(save); // ..then back to previous. + } + + void value_cb2(const char *suffix) + { + char tip[40]; + snprintf(tip, sizeof(tip), "%.2f%s", value(), suffix); + tipwin->value(tip); + tipwin->position(Fl::event_x_root() + 20, Fl::event_y_root()); + } + + void create_value_window() + { + int window_width = 180, window_height = 90; + + window_value = new Fl_Window(0, 0, window_width, window_height); + window_value->user_data(this); + window_value->set_modal(); + window_value->label(label()); + // window_value->border(0); + window_value->color(fl_darker(window_value->color())); + + /* Fl_Box *title = new Fl_Box(0, 5, window_width, 10); + title->label(label()); + title->align(FL_ALIGN_INSIDE);*/ + + input_value = new My_Value_Input(5, 25, 165, 22); + input_value->align(FL_ALIGN_TOP_LEFT); + input_value->custom_callback = &input_value_cb_; + + Fl_Button *button_close = new Fl_Button(5, 55, 80, 22, _("Close")); + button_close->box(FL_ENGRAVED_BOX); + button_close->callback((Fl_Callback *)button_close_cb_); + + Fl_Button *button_ok = new Fl_Button(5 + 80 + 5, 55, 80, 22, _("Ok")); + button_ok->box(FL_ENGRAVED_BOX); + button_ok->callback((Fl_Callback *)button_ok_cb_); + + window_value->end(); + } + + // MARK: Callbacks + + // Close button + static void button_close_cb_(Fl_Widget *widget, void *data) + { + Fl_Widget *p = widget; + while (p->parent()) { + p = p->parent(); + } + + ((Fl_My_Value_Slider *)p->user_data())->button_close_cb(widget, p->user_data()); + } + void button_close_cb(Fl_Widget *widget, void *data) { this->window_value->hide(); } + + // ok button + static void button_ok_cb_(Fl_Widget *widget, void *data) + { + Fl_Widget *p = widget; + while (p->parent()) { + p = p->parent(); + } + + ((Fl_My_Value_Slider *)p->user_data())->button_ok_cb(widget, data); + } + + void button_ok_cb(Fl_Widget *button, void *data) + { + this->set_value(clamp(this->input_value->value())); + this->do_callback(); + this->parent()->redraw(); + this->window_value->hide(); + } + + // input field + static void input_value_cb_(Fl_Widget *widget, void *data) + { + Fl_Widget *p = widget; + while (p->parent()) { + p = p->parent(); + } + + ((Fl_My_Value_Slider *)p->user_data())->input_value_cb(widget, data); + } + + void input_value_cb(Fl_Widget *button, void *data) + { + this->set_value(clamp(this->input_value->value())); + this->do_callback(); + this->parent()->redraw(); + } + + int handle(int e) + { + switch (e) { + case FL_PUSH: + if (Fl::event_button() == FL_LEFT_MOUSE) { + if (Fl::event_clicks()) // move slider to zero when double clicking + { + this->value(default_value); + this->do_callback(); + this->parent()->redraw(); + return 1; + } + if (hide_tipwin == false) { + tipwin->position(Fl::event_x_root() + 20, Fl::event_y_root()); + tipwin->show(); + } + } + if (Fl::event_button() == FL_RIGHT_MOUSE) { + return 1; + } + + break; + case FL_RELEASE: // release mouse + tipwin->hide(); + if (Fl::event_button() == FL_RIGHT_MOUSE) { + char input_label[64]; + float current_slider_value = value(); + input_value->value(current_slider_value); + window_value->position(Fl::event_x_root() - window_value->w() / 2, Fl::event_y_root() - window_value->h() - 15); + + if (this->minimum() < this->maximum()) { + snprintf(input_label, sizeof(input_label), "Min: %.2f Max: %.2f", this->minimum(), this->maximum()); + } + else { + snprintf(input_label, sizeof(input_label), "Min: %.2f Max: %.2f", this->maximum(), + this->minimum()); // Reversed direction (for vertical sliders) + } + + input_value->copy_label(input_label); + input_value->take_focus(); + window_value->show(); + + return 1; + } + case FL_HIDE: // valuator goes away + case FL_LEAVE: // leave focus + // Make sure tipwin closes when app closes + tipwin->hide(); + break; + } + return (Fl_Slider::handle(e)); + } +}; + +#endif diff --git a/src/FLTK/Fl_ILM216.cpp b/src/FLTK/Fl_ILM216.cpp new file mode 100644 index 0000000..e5e54f5 --- /dev/null +++ b/src/FLTK/Fl_ILM216.cpp @@ -0,0 +1,577 @@ +// +// "$Id: Fl_ILM216.cxx,v 1.8 2003/02/26 01:59:31 easysw Exp $" +// +// ILM-216 LCD emulator widget code for flcdsim. +// +// Copyright 2003 by Michael Sweet. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Contents: +// +// Fl_ILM216::Fl_ILM216() - Create a new ILM-216 widget. +// Fl_ILM216::~Fl_ILM216() - Delete an ILM-216 widget. +// Fl_ILM216::draw() - Draw the widget. +// Fl_LCD216::load_char() - Load a single character in the font. +// Fl_LCD216::load_font() - Load the standard ILM-216 font. +// Fl_LCD216::process() - Process data like an ILM-216. +// + +// modified by Daniel Noethen + +// +// Include necessary headers... +// + +#include +#include +#include +#include +#include +#include + +#include "butt.h" +#include "flgui.h" + +#include "../xpm/rec.xpm" //rec_xpm +#include "../xpm/rec_dark.xpm" //rec_xpm +#include "../xpm/rec_armed.xpm" //rec_xpm +#include "../xpm/conn.xpm" //conn_xpm +#include "../xpm/conn_dark.xpm" //conn_xpm + +// +// Font data for the LCD-216... +// +// +// + +static const uchar standard_font[224][8] = { + // 0x20 to 0x2f + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x04, 0x00}, + {0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x0a, 0x0a, 0x1f, 0x0a, 0x1f, 0x0a, 0x0a, 0x00}, + {0x04, 0x0f, 0x14, 0x0e, 0x05, 0x1e, 0x04, 0x00}, + {0x18, 0x19, 0x02, 0x04, 0x08, 0x13, 0x03, 0x00}, + {0x0c, 0x12, 0x14, 0x08, 0x15, 0x12, 0x0d, 0x00}, + {0x0c, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0x04, 0x08, 0x08, 0x08, 0x04, 0x02, 0x00}, + {0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08, 0x00}, + {0x00, 0x04, 0x15, 0x0e, 0x15, 0x04, 0x00, 0x00}, + {0x00, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x04, 0x08}, + {0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00}, + {0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00}, + + // 0x30 to 0x3f + {0x0e, 0x11, 0x13, 0x15, 0x19, 0x11, 0x0e, 0x00}, + {0x04, 0x0c, 0x04, 0x04, 0x04, 0x04, 0x1f, 0x00}, + {0x0e, 0x11, 0x01, 0x02, 0x04, 0x08, 0x1f, 0x00}, + {0x1f, 0x02, 0x04, 0x02, 0x01, 0x11, 0x0e, 0x00}, + {0x02, 0x06, 0x0a, 0x12, 0x1f, 0x02, 0x02, 0x00}, + {0x1f, 0x10, 0x1e, 0x01, 0x01, 0x11, 0x0e, 0x00}, + {0x06, 0x08, 0x10, 0x1e, 0x11, 0x11, 0x0e, 0x00}, + {0x1f, 0x01, 0x02, 0x04, 0x08, 0x08, 0x08, 0x00}, + {0x0e, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x0e, 0x00}, + {0x0e, 0x11, 0x11, 0x0f, 0x01, 0x02, 0x0c, 0x00}, + {0x00, 0x0c, 0x0c, 0x00, 0x0c, 0x0c, 0x00, 0x00}, + {0x00, 0x0c, 0x0c, 0x00, 0x0c, 0x04, 0x08, 0x00}, + {0x02, 0x04, 0x08, 0x10, 0x08, 0x04, 0x02, 0x00}, + {0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00}, + {0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x00}, + {0x0e, 0x11, 0x01, 0x02, 0x04, 0x00, 0x04, 0x00}, + + // 0x40 to 0x4f + {0x0e, 0x11, 0x01, 0x0d, 0x15, 0x15, 0x0e, 0x00}, + {0x0e, 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x00}, + {0x1e, 0x11, 0x11, 0x1e, 0x11, 0x11, 0x1e, 0x00}, + {0x0e, 0x11, 0x10, 0x10, 0x10, 0x11, 0x0e, 0x00}, + {0x1c, 0x12, 0x11, 0x11, 0x11, 0x12, 0x1c, 0x00}, + {0x1f, 0x10, 0x10, 0x1e, 0x10, 0x10, 0x1f, 0x00}, + {0x1f, 0x10, 0x10, 0x1e, 0x10, 0x10, 0x10, 0x00}, + {0x0e, 0x11, 0x10, 0x17, 0x11, 0x11, 0x0f, 0x00}, + {0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11, 0x00}, + {0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f, 0x00}, + {0x07, 0x02, 0x02, 0x02, 0x02, 0x12, 0x0c, 0x00}, + {0x11, 0x12, 0x14, 0x18, 0x14, 0x12, 0x11, 0x00}, + {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1f, 0x00}, + {0x11, 0x1b, 0x15, 0x15, 0x11, 0x11, 0x11, 0x00}, + {0x11, 0x11, 0x19, 0x15, 0x13, 0x11, 0x11, 0x00}, + {0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e, 0x00}, + + // 0x50 to 0x5f + {0x1e, 0x11, 0x11, 0x1e, 0x10, 0x10, 0x10, 0x00}, + {0x0e, 0x11, 0x11, 0x11, 0x15, 0x12, 0x0d, 0x00}, + {0x1e, 0x11, 0x11, 0x1e, 0x14, 0x12, 0x11, 0x00}, + {0x0f, 0x10, 0x10, 0x0e, 0x01, 0x01, 0x1e, 0x00}, + {0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00}, + {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e, 0x00}, + {0x11, 0x11, 0x11, 0x11, 0x11, 0x0a, 0x04, 0x00}, + {0x11, 0x11, 0x11, 0x15, 0x15, 0x15, 0x0a, 0x00}, + {0x11, 0x11, 0x0a, 0x04, 0x0a, 0x11, 0x11, 0x00}, + {0x11, 0x11, 0x11, 0x0a, 0x04, 0x04, 0x04, 0x00}, + {0x1f, 0x01, 0x02, 0x04, 0x08, 0x10, 0x1f, 0x00}, + {0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x00}, + {0x11, 0x0a, 0x1f, 0x04, 0x1f, 0x04, 0x04, 0x00}, + {0x0e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0e, 0x00}, + {0x04, 0x0a, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f}, + + // 0x60 to 0x6f + {0x08, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x0e, 0x01, 0x0f, 0x11, 0x0f, 0x00}, + {0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x1e, 0x00}, + {0x00, 0x00, 0x0e, 0x10, 0x10, 0x11, 0x0e, 0x00}, + {0x01, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x0f, 0x00}, + {0x00, 0x00, 0x0e, 0x11, 0x1f, 0x10, 0x0e, 0x00}, + {0x06, 0x09, 0x08, 0x1c, 0x08, 0x08, 0x08, 0x00}, + {0x00, 0x0f, 0x11, 0x11, 0x0f, 0x01, 0x0e, 0x00}, + {0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x11, 0x00}, + {0x04, 0x00, 0x0c, 0x04, 0x04, 0x04, 0x0e, 0x00}, + {0x02, 0x00, 0x02, 0x02, 0x02, 0x12, 0x0c, 0x00}, + {0x10, 0x10, 0x12, 0x14, 0x18, 0x14, 0x12, 0x00}, + {0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0e, 0x00}, + {0x00, 0x00, 0x1a, 0x15, 0x15, 0x11, 0x11, 0x00}, + {0x00, 0x00, 0x16, 0x19, 0x11, 0x11, 0x11, 0x00}, + {0x00, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e, 0x00}, + + // 0x70 to 0x7f + {0x00, 0x1e, 0x11, 0x11, 0x1e, 0x10, 0x10, 0x00}, + {0x00, 0x0d, 0x13, 0x11, 0x0f, 0x01, 0x01, 0x00}, + {0x00, 0x00, 0x16, 0x19, 0x10, 0x10, 0x10, 0x00}, + {0x00, 0x00, 0x0e, 0x10, 0x0e, 0x01, 0x1e, 0x00}, + {0x08, 0x08, 0x1c, 0x08, 0x08, 0x09, 0x06, 0x00}, + {0x00, 0x00, 0x11, 0x11, 0x11, 0x13, 0x0d, 0x00}, + {0x00, 0x00, 0x11, 0x11, 0x11, 0x0a, 0x04, 0x00}, + {0x00, 0x00, 0x11, 0x11, 0x15, 0x15, 0x0a, 0x00}, + {0x00, 0x00, 0x11, 0x0a, 0x04, 0x0a, 0x11, 0x00}, + {0x00, 0x11, 0x11, 0x11, 0x0f, 0x01, 0x0e, 0x00}, + {0x00, 0x00, 0x1f, 0x02, 0x04, 0x08, 0x1f, 0x00}, + {0x02, 0x04, 0x04, 0x08, 0x04, 0x04, 0x02, 0x00}, + {0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00}, + {0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08, 0x00}, + {0x00, 0x04, 0x02, 0x1f, 0x02, 0x04, 0x00, 0x00}, + {0x00, 0x04, 0x08, 0x1f, 0x08, 0x04, 0x00, 0x00}, + + // 0x80 to 0x8f + {0x1c, 0x10, 0x18, 0x10, 0x12, 0x02, 0x02, 0x02}, + {0x1c, 0x10, 0x18, 0x16, 0x11, 0x02, 0x04, 0x07}, + {0x1c, 0x10, 0x18, 0x16, 0x11, 0x02, 0x01, 0x06}, + {0x1c, 0x10, 0x18, 0x15, 0x15, 0x07, 0x01, 0x01}, + {0x08, 0x14, 0x14, 0x08, 0x05, 0x06, 0x05, 0x05}, + {0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f}, + {0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + // 0x90 to 0x9f + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + + // 0xa0 to 0xaf + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x14, 0x1c}, + {0x07, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x1c}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x04}, + {0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00}, + {0x00, 0x1f, 0x01, 0x1f, 0x01, 0x02, 0x04, 0x00}, + {0x00, 0x00, 0x00, 0x1f, 0x01, 0x06, 0x04, 0x08}, + {0x00, 0x00, 0x00, 0x02, 0x04, 0x0c, 0x14, 0x04}, + {0x00, 0x00, 0x00, 0x04, 0x1f, 0x11, 0x01, 0x06}, + {0x00, 0x00, 0x00, 0x00, 0x1f, 0x04, 0x04, 0x1f}, + {0x00, 0x00, 0x00, 0x02, 0x1f, 0x06, 0x0a, 0x12}, + {0x00, 0x00, 0x00, 0x08, 0x1f, 0x09, 0x0a, 0x08}, + {0x00, 0x00, 0x00, 0x00, 0x0e, 0x02, 0x02, 0x1f}, + {0x00, 0x00, 0x00, 0x1e, 0x02, 0x1e, 0x02, 0x1e}, + {0x00, 0x00, 0x00, 0x00, 0x15, 0x15, 0x01, 0x06}, + + // 0xb0 to 0xbf + {0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00}, + {0x1f, 0x01, 0x05, 0x06, 0x04, 0x04, 0x08, 0x00}, + {0x01, 0x02, 0x04, 0x0c, 0x14, 0x04, 0x04, 0x00}, + {0x04, 0x1f, 0x11, 0x11, 0x01, 0x02, 0x04, 0x00}, + {0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x1f, 0x00}, + {0x02, 0x1f, 0x02, 0x06, 0x0a, 0x12, 0x02, 0x00}, + {0x08, 0x1f, 0x09, 0x09, 0x09, 0x09, 0x12, 0x00}, + {0x04, 0x1f, 0x04, 0x1f, 0x04, 0x04, 0x04, 0x00}, + {0x00, 0x0f, 0x09, 0x11, 0x01, 0x02, 0x0c, 0x00}, + {0x08, 0x0f, 0x12, 0x02, 0x02, 0x02, 0x04, 0x00}, + {0x00, 0x1f, 0x01, 0x01, 0x01, 0x01, 0x1f, 0x00}, + {0x0a, 0x1f, 0x0a, 0x0a, 0x02, 0x04, 0x08, 0x00}, + {0x00, 0x18, 0x01, 0x19, 0x01, 0x02, 0x1c, 0x00}, + {0x00, 0x1f, 0x01, 0x02, 0x04, 0x0a, 0x11, 0x00}, + {0x08, 0x1f, 0x09, 0x0a, 0x08, 0x08, 0x07, 0x00}, + {0x00, 0x11, 0x11, 0x09, 0x01, 0x02, 0x0c, 0x00}, + + // 0xc0 to 0xcf + {0x00, 0x0f, 0x09, 0x15, 0x03, 0x02, 0x0c, 0x00}, + {0x02, 0x1c, 0x04, 0x1f, 0x04, 0x04, 0x08, 0x00}, + {0x00, 0x15, 0x15, 0x15, 0x01, 0x02, 0x04, 0x00}, + {0x0e, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x08, 0x00}, + {0x08, 0x08, 0x08, 0x0c, 0x0a, 0x08, 0x08, 0x00}, + {0x04, 0x04, 0x1f, 0x04, 0x04, 0x08, 0x10, 0x00}, + {0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00}, + {0x00, 0x1f, 0x01, 0x0a, 0x04, 0x0a, 0x10, 0x00}, + {0x04, 0x1f, 0x02, 0x04, 0x0e, 0x15, 0x04, 0x00}, + {0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x08, 0x00}, + {0x00, 0x04, 0x02, 0x11, 0x11, 0x11, 0x11, 0x00}, + {0x10, 0x10, 0x1f, 0x10, 0x10, 0x10, 0x0f, 0x00}, + {0x00, 0x1f, 0x01, 0x01, 0x01, 0x02, 0x04, 0x00}, + {0x00, 0x08, 0x14, 0x02, 0x01, 0x01, 0x00, 0x00}, + {0x04, 0x1f, 0x04, 0x04, 0x15, 0x15, 0x04, 0x00}, + {0x00, 0x1f, 0x01, 0x01, 0x0a, 0x04, 0x02, 0x00}, + + // 0xd0 to 0xdf + {0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x01, 0x00}, + {0x00, 0x04, 0x08, 0x10, 0x11, 0x1f, 0x01, 0x00}, + {0x00, 0x01, 0x01, 0x0a, 0x04, 0x0a, 0x10, 0x00}, + {0x00, 0x1f, 0x08, 0x1f, 0x08, 0x08, 0x07, 0x00}, + {0x08, 0x08, 0x1f, 0x09, 0x0a, 0x08, 0x08, 0x00}, + {0x00, 0x0e, 0x02, 0x02, 0x02, 0x02, 0x1f, 0x00}, + {0x00, 0x1f, 0x01, 0x1f, 0x01, 0x01, 0x1f, 0x00}, + {0x0e, 0x00, 0x1f, 0x01, 0x01, 0x02, 0x04, 0x00}, + {0x12, 0x12, 0x12, 0x12, 0x02, 0x04, 0x08, 0x00}, + {0x00, 0x04, 0x14, 0x14, 0x15, 0x15, 0x16, 0x00}, + {0x00, 0x10, 0x10, 0x11, 0x12, 0x14, 0x18, 0x00}, + {0x00, 0x1f, 0x11, 0x11, 0x11, 0x11, 0x1f, 0x00}, + {0x00, 0x1f, 0x11, 0x11, 0x01, 0x02, 0x04, 0x00}, + {0x00, 0x18, 0x00, 0x01, 0x01, 0x02, 0x1c, 0x00}, + {0x04, 0x12, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x1c, 0x14, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00}, + + // 0xe0 to 0xef + {0x00, 0x00, 0x09, 0x15, 0x12, 0x12, 0x0d, 0x00}, + {0x0a, 0x00, 0x0e, 0x01, 0x0f, 0x11, 0x0f, 0x00}, + {0x00, 0x00, 0x0e, 0x11, 0x1e, 0x11, 0x1e, 0x00}, + {0x00, 0x00, 0x0e, 0x10, 0x0c, 0x11, 0x0e, 0x00}, + {0x00, 0x00, 0x11, 0x11, 0x13, 0x1d, 0x10, 0x00}, + {0x00, 0x00, 0x0f, 0x14, 0x12, 0x11, 0x0e, 0x00}, + {0x00, 0x00, 0x06, 0x19, 0x11, 0x19, 0x16, 0x00}, + {0x00, 0x00, 0x0f, 0x11, 0x11, 0x13, 0x0d, 0x00}, + {0x00, 0x00, 0x07, 0x04, 0x04, 0x14, 0x08, 0x00}, + {0x00, 0x02, 0x1a, 0x02, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0x00, 0x06, 0x02, 0x02, 0x02, 0x02, 0x00}, + {0x00, 0x14, 0x08, 0x14, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x04, 0x0e, 0x14, 0x15, 0x0e, 0x04, 0x00}, + {0x08, 0x08, 0x1c, 0x08, 0x1c, 0x08, 0x0f, 0x00}, + {0x0e, 0x00, 0x16, 0x19, 0x11, 0x11, 0x11, 0x00}, + {0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e, 0x00}, + + // 0xf0 to 0xff + {0x00, 0x00, 0x16, 0x19, 0x11, 0x19, 0x16, 0x00}, + {0x00, 0x00, 0x0d, 0x13, 0x11, 0x13, 0x0d, 0x00}, + {0x00, 0x0e, 0x11, 0x1f, 0x11, 0x11, 0x0e, 0x00}, + {0x00, 0x00, 0x00, 0x0b, 0x11, 0x1a, 0x00, 0x00}, + {0x00, 0x00, 0x0e, 0x11, 0x11, 0x0a, 0x1b, 0x00}, + {0x0a, 0x00, 0x11, 0x11, 0x11, 0x13, 0x0d, 0x00}, + {0x1f, 0x80, 0x04, 0x02, 0x04, 0x08, 0x1f, 0x00}, + {0x00, 0x00, 0x1f, 0x0a, 0x0a, 0x0a, 0x13, 0x00}, + {0x1f, 0x00, 0x11, 0x0a, 0x04, 0x0a, 0x11, 0x00}, + {0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x0f, 0x00}, + {0x00, 0x01, 0x1e, 0x04, 0x1f, 0x04, 0x04, 0x00}, + {0x00, 0x00, 0x1f, 0x08, 0x0f, 0x09, 0x11, 0x00}, + {0x00, 0x00, 0x1f, 0x15, 0x1f, 0x11, 0x11, 0x00}, + {0x00, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x04, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f}}; + +// +// 'Fl_ILM216::Fl_ILM216()' - Create a new ILM-216 widget. +// + +Fl_ILM216::Fl_ILM216(int X, // I - X position + int Y, // I - Y position + int W, // I - Width + int H, // I - Height + const char *L) // I - Label string + : Fl_Widget(X, Y, W, H, L) +{ + // Initialize defaults... + backlight_ = 0; + + rec_ = new Fl_Pixmap(rec_xpm); + rec_dark_ = new Fl_Pixmap(rec_dark_xpm); + rec_armed_ = new Fl_Pixmap(rec_armed_xpm); + conn_ = new Fl_Pixmap(conn_xpm); + conn_dark_ = new Fl_Pixmap(conn_dark_xpm); + + // Load the standard font... + load_font(); +} + +// +// 'Fl_ILM216::~Fl_ILM216()' - Delete an ILM-216 widget. +// + +Fl_ILM216::~Fl_ILM216(void) +{ + // Unload the font data... + for (int i = 0; i < 256; i++) { + if (font_[i]) { + delete font_[i]; + } + + if (outline_[i]) { + delete outline_[i]; + } + } + delete rec_; + delete rec_dark_; + delete rec_armed_; + delete conn_; + delete conn_dark_; +} + +int Fl_ILM216::handle(int event) +{ + if (event == FL_RELEASE) { + do_callback(); + } + + return 1; +} + +// 'Fl_ILM216::draw()' - Draw the widget. +// + +void Fl_ILM216::draw(void) +{ + int i; // Looping var + int X = x() + (w() - 16 * 24) / 2; // X base position + int Y = y() + (h() - 2 * 40) / 2; // Y base position + Fl_Color oc; // Outline color + + // Draw the background... + if (backlight_) { + draw_box(box(), x(), y(), w(), h(), fl_lighter((Fl_Color)cfg.main.bg_color)); + oc = fl_color_average((Fl_Color)cfg.main.txt_color, fl_lighter((Fl_Color)cfg.main.bg_color), 0.5f); + } + else { + draw_box(box(), x(), y(), w(), h(), (Fl_Color)cfg.main.bg_color); + oc = fl_color_average((Fl_Color)cfg.main.txt_color, (Fl_Color)cfg.main.bg_color, 0.5f); + } + + // draw the right line + fl_color((Fl_Color)cfg.main.txt_color); + + fl_line_style(FL_SOLID, 1, NULL); + fl_line(X + 15 * 25 - 15, Y, X + 15 * 25 - 15, Y + 40 * 2); + fl_line_style(0); + + // draw the status symbols + if (connected) { + conn_->draw(X + 15 * 25 - 5, Y + 8); + } + else { + conn_dark_->draw(X + 15 * 25 - 5, Y + 8); + } + + if (recording) { + rec_->draw(X + 15 * 25 - 7, Y + 8 + 50); + } + else if (cfg.rec.start_rec) { + rec_armed_->draw(X + 15 * 25 - 7, Y + 8 + 50); + } + else { + rec_dark_->draw(X + 15 * 25 - 7, Y + 8 + 50); + } + + // Draw the LCD contents... + for (i = 0; i < 16; i++) { + fl_color((Fl_Color)cfg.main.txt_color); + + if (font_[chars_[i + 0]]) { + font_[chars_[i + 0]]->draw(X + i * 24, Y); + } + if (font_[chars_[i + 16]]) { + font_[chars_[i + 16]]->draw(X + i * 24, Y + 40); + } + + fl_color(oc); + + if (outline_[chars_[i + 0]]) { + outline_[chars_[i + 0]]->draw(X + i * 24, Y); + } + if (outline_[chars_[i + 16]]) { + outline_[chars_[i + 16]]->draw(X + i * 24, Y + 40); + } + } + fl_g->label_current_listeners->labelcolor((Fl_Color)cfg.main.txt_color); + fl_g->label_current_listeners->redraw(); +} + +// +// 'Fl_LCD216::load_char()' - Load a single character in the font. +// + +void Fl_ILM216::load_char(uchar ch, // I - Character + const uchar *data) // I - 5x8 bitmap data +{ + int i; // Looping var + uchar *fdata; // Pointer to font data + uchar *odata; // Pointer to outline data + + // Delete the existing character, if any... + if (font_[ch]) { + delete font_[ch]; + font_[ch] = 0; + } + + if (outline_[ch]) { + // delete outline_[ch]; + outline_[ch] = 0; + } + + // Don't need to define blank chars... + if (data[0] == 0 && !memcmp(data, data + 1, 7)) { + return; + } + + // Create a 20x32 bitmap from the 5x8 data, so that it looks like the + // LCD display. + fdata = fdata_[ch - ' ']; + odata = odata_[ch - ' ']; + + memset(fdata, 0, 96); + memset(odata, 0, 96); + + for (i = 0; i < 8; i++, fdata += 12, odata += 12, data++) { + // Each bit in the source byte is mapped to a 3x3 "pixel" and a 4x4 + // "outline" in the LCD bitmap. + if (*data & 0x10) { + fdata[0] |= 0x07; + fdata[3] |= 0x07; + fdata[6] |= 0x07; + + odata[0] |= 0x08; + odata[3] |= 0x08; + odata[6] |= 0x08; + odata[9] |= 0x0f; + } + + if (*data & 0x08) { + fdata[0] |= 0x70; + fdata[3] |= 0x70; + fdata[6] |= 0x70; + + odata[0] |= 0x80; + odata[3] |= 0x80; + odata[6] |= 0x80; + odata[9] |= 0xf0; + } + + if (*data & 0x04) { + fdata[1] |= 0x07; + fdata[4] |= 0x07; + fdata[7] |= 0x07; + + odata[1] |= 0x08; + odata[4] |= 0x08; + odata[7] |= 0x08; + odata[10] |= 0x0f; + } + + if (*data & 0x02) { + fdata[1] |= 0x70; + fdata[4] |= 0x70; + fdata[7] |= 0x70; + + odata[1] |= 0x80; + odata[4] |= 0x80; + odata[7] |= 0x80; + odata[10] |= 0xf0; + } + + if (*data & 0x01) { + fdata[2] |= 0x07; + fdata[5] |= 0x07; + fdata[8] |= 0x07; + + odata[2] |= 0x08; + odata[5] |= 0x08; + odata[8] |= 0x08; + odata[11] |= 0x0f; + } + } + + // Create the bitmap image for this char... + font_[ch] = new Fl_Bitmap(fdata_[ch - ' '], 20, 32); + outline_[ch] = new Fl_Bitmap(odata_[ch - ' '], 20, 32); +} + +// +// 'Fl_LCD216::load_font()' - Load the standard ILM-216 font. +// + +void Fl_ILM216::load_font(void) +{ + // Clear the font list... + memset(font_, 0, sizeof(font_)); + memset(outline_, 0, sizeof(outline_)); + + // Load standard font data for 224 chars... + for (int i = 0; i < 224; i++) + load_char(i + ' ', standard_font[i]); +} + +// +// 'Fl_LCD216::process()' - Process data like an ILM-216. +// + +int Fl_ILM216::print(const uchar *in, int inbytes) +{ + int nbytes; + + // Loop through the input bytes... + nbytes = 0; + + for (; inbytes > 0; inbytes--, in++) { + if (cursor_pos_ < sizeof(chars_) - 1) { + chars_[cursor_pos_++] = *in; + + if (*in == '\n') { + cursor_pos_ = 16; + } + } + } + + redraw(); + + // Return the number of bytes of output... + return (nbytes); +} + +// +// End of "$Id: Fl_ILM216.cxx,v 1.8 2003/02/26 01:59:31 easysw Exp $". +// diff --git a/src/FLTK/Fl_ILM216.h b/src/FLTK/Fl_ILM216.h new file mode 100644 index 0000000..3cb7c57 --- /dev/null +++ b/src/FLTK/Fl_ILM216.h @@ -0,0 +1,106 @@ +// +// "$Id: Fl_ILM216.h,v 1.5 2003/02/26 00:40:22 easysw Exp $" +// +// ILM-216 LCD emulation widget header file for flcdsim. +// +// Copyright 2003 by Michael Sweet. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +// modified by Daniel Noethen + +#ifndef FL_ILM216_H +#define FL_ILM216_H + +// +// Include necessary headers... +// + +#include +#include +#include +#include + +// +// Backlight color... +// + +#define FL_NOLIGHT (Fl_Color)76 +#define FL_BACKLIGHT (Fl_Color)85 + +// +// ILM-216 emulation widget... +// + +class Fl_ILM216 : public Fl_Widget { + public: + enum { + CURSOR_NONE = 0, + CURSOR_UNDERLINE, + CURSOR_BLINK, + }; + + private: + bool backlight_; // Backlight enabled? + uchar buttons_; // Current button state + uint32_t cursor_pos_; // Cursor position + bool cursor_state_; // Cursor state (blinking) + int cursor_type_; // Cursor type + Fl_Bitmap *font_[256]; // Images for characters + Fl_Bitmap *outline_[256]; // Outline images for characters + Fl_Pixmap *rec_; // blinks if recording + Fl_Pixmap *rec_dark_; // blinks if recording + Fl_Pixmap *rec_armed_; // blinks if recording + Fl_Pixmap *conn_; // blinks if streaming + Fl_Pixmap *conn_dark_; // blinks if streaming + uchar fdata_[224][96]; // Bitmap data (20x32) + uchar odata_[224][96]; // Outline data (20x32) + uchar prev_char_; // Previous character + + void draw(void); + void load_char(uchar ch, const uchar *data); + void load_font(void); + + public: + Fl_ILM216(int X, int Y, int W, int H, const char *L = 0); + ~Fl_ILM216(void); + + uchar chars_[32]; // Characters on-screen + + virtual int handle(int); + + bool backlight() const { return backlight_; } + void backlight(bool b) + { + backlight_ = b; + redraw(); + } + uchar buttons() const { return buttons_; } + void buttons(uchar b) { buttons_ = b; } + void clear() + { + for (int i = 0; i < 32; i++) + chars_[i] = ' '; + home(); + redraw(); + } + int cursor_pos() const { return cursor_pos_; } + void cursor_pos(int p) { cursor_pos_ = p; } + void home() { cursor_pos(0); } + int print(const uchar *in, int inbytes); +}; + +#endif // !Fl_ILM216_h + +// +// End of "$Id: Fl_ILM216.h,v 1.5 2003/02/26 00:40:22 easysw Exp $". +// diff --git a/src/FLTK/Fl_LED.cpp b/src/FLTK/Fl_LED.cpp new file mode 100644 index 0000000..0b8218a --- /dev/null +++ b/src/FLTK/Fl_LED.cpp @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "Fl_LED.h" + +LED::LED(int X, int Y, int W, int H, const char *L) : Fl_Group(X, Y, W, H, L) +{ + bg_color = color(); + width = w(); + height = h(); + x_origin = x(); + y_origin = y(); + LED_color = fl_rgb_color((uchar)(6), (uchar)(209), (uchar)(40)); + state = LED_OFF; +} + +void LED::draw() +{ + // Fl_Group::draw(); + // Clear whole widget area + // fl_rectf(x_origin, y_origin, width, height, bg_color); + + Fl_Color last_color = fl_color(); + + Fl_Color draw_color; + if (state == LED_ON) { + draw_color = LED_color; + } + else { + uchar r, g, b; + Fl::get_color(LED_color, r, g, b); + draw_color = fl_rgb_color(r / 2, g / 2, b / 2); + } + + fl_color(draw_color); + fl_pie(x_origin, y_origin, width - 1, height - 1, 0, 360); + + fl_color(FL_BLACK); + fl_arc(x_origin, y_origin, width, height, 0, 360); + + fl_color(last_color); +} + +void LED::set_color(Fl_Color color) +{ + LED_color = color; + redraw(); +} + +void LED::set_state(LED_STATE on_off) +{ + state = on_off; + redraw(); +} diff --git a/src/FLTK/Fl_LED.h b/src/FLTK/Fl_LED.h new file mode 100644 index 0000000..1714c04 --- /dev/null +++ b/src/FLTK/Fl_LED.h @@ -0,0 +1,30 @@ +#ifndef FL_LED_H +#define FL_LED_H +#include +#include +#include +#include +#include + +class LED : public Fl_Group { + public: + enum LED_STATE { + LED_OFF = 0, + LED_ON = 1, + }; + + int width, height; + int x_origin, y_origin; + LED_STATE state; + + Fl_Color LED_color; + Fl_Color bg_color; + + LED(int X, int Y, int W, int H, const char *L = 0); + + void set_color(Fl_Color color); + void set_state(LED_STATE state); + void draw(); +}; + +#endif // FL_VU_METER_H diff --git a/src/FLTK/Fl_My_Native_File_Chooser.cxx b/src/FLTK/Fl_My_Native_File_Chooser.cxx new file mode 100644 index 0000000..3947fac --- /dev/null +++ b/src/FLTK/Fl_My_Native_File_Chooser.cxx @@ -0,0 +1,38 @@ +// "$Id$" +// +// FLTK native OS file chooser widget +// +// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 2004 Greg Ercolano. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// + +// Use Windows' chooser +#ifdef WIN32 +#include "Fl_My_Native_File_Chooser_WIN32.cxx" +#endif + +// Use Apple's chooser +#ifdef __APPLE__ +#include "Fl_My_Native_File_Chooser_MAC.mm" +#endif + +// All else falls back to FLTK's own chooser +#if !defined(__APPLE__) && !defined(WIN32) +#include "Fl_My_Native_File_Chooser_FLTK.cxx" +#endif + +const char *Fl_My_Native_File_Chooser::file_exists_message = "File exists. Are you sure you want to overwrite?"; + +// +// End of "$Id$". +// diff --git a/src/FLTK/Fl_My_Native_File_Chooser_FLTK.cxx b/src/FLTK/Fl_My_Native_File_Chooser_FLTK.cxx new file mode 100644 index 0000000..e8d1164 --- /dev/null +++ b/src/FLTK/Fl_My_Native_File_Chooser_FLTK.cxx @@ -0,0 +1,634 @@ +// "$Id$" +// +// FLTK native file chooser widget wrapper for GTK's GtkFileChooserDialog +// +// Copyright 1998-2014 by Bill Spitzak and others. +// Copyright 2012 IMM +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// + +#include +#include +#include +#define FLTK_CHOOSER_SINGLE Fl_File_Chooser::SINGLE +#define FLTK_CHOOSER_DIRECTORY Fl_File_Chooser::DIRECTORY +#define FLTK_CHOOSER_MULTI Fl_File_Chooser::MULTI +#define FLTK_CHOOSER_CREATE Fl_File_Chooser::CREATE + +#include "Fl_My_Native_File_Chooser_common.cxx" +#include "Fl_My_Native_File_Chooser_GTK.cxx" + +#include +#include + +int Fl_My_Native_File_Chooser::have_looked_for_GTK_libs = 0; + +/** + The constructor. Internally allocates the native widgets. + Optional \p val presets the type of browser this will be, + which can also be changed with type(). + */ +Fl_My_Native_File_Chooser::Fl_My_Native_File_Chooser(int val) +{ +#if FLTK_ABI_VERSION <= 10302 + _btype = val; + _options = NO_OPTIONS; + _filter = NULL; + _filtvalue = 0; + _parsedfilt = NULL; + _preset_file = NULL; + _prevvalue = NULL; + _directory = NULL; + _errmsg = NULL; +#endif // FLTK_ABI_VERSION + if (have_looked_for_GTK_libs == 0) { + // First Time here, try to find the GTK libs if they are installed +#if HAVE_DLSYM && HAVE_DLFCN_H + if (Fl::option(Fl::OPTION_FNFC_USES_GTK)) { + Fl_GTK_File_Chooser::probe_for_GTK_libs(); + } +#endif + have_looked_for_GTK_libs = -1; + } + // if we found all the GTK functions we need, we will use the GtkFileChooserDialog + if (Fl_GTK_File_Chooser::did_find_GTK_libs) { + _gtk_file_chooser = new Fl_GTK_File_Chooser(val); + } + else { + _x11_file_chooser = new Fl_FLTK_File_Chooser(val); + } +} + +/** + Destructor. + Deallocates any resources allocated to this widget. + */ +Fl_My_Native_File_Chooser::~Fl_My_Native_File_Chooser() +{ + delete _x11_file_chooser; +} + +/** + Sets the current Fl_My_Native_File_Chooser::Type of browser. + */ +void Fl_My_Native_File_Chooser::type(int t) +{ + return _x11_file_chooser->type(t); +} + +/** + Gets the current Fl_My_Native_File_Chooser::Type of browser. + */ +int Fl_My_Native_File_Chooser::type() const +{ + return _x11_file_chooser->type(); +} + +/** + Sets the platform specific chooser options to \p val. + \p val is expected to be one or more Fl_My_Native_File_Chooser::Option flags ORed together. + Some platforms have OS-specific functions that can be enabled/disabled via this method. +

+ \code + Flag Description Win Mac Other + -------------- ----------------------------------------------- ------- ------- ------- + NEW_FOLDER Shows the 'New Folder' button. Ignored Used Used + PREVIEW Enables the 'Preview' mode by default. Ignored Ignored Used + SAVEAS_CONFIRM Confirm dialog if BROWSE_SAVE_FILE file exists. Used Used Used + USE_FILTER_EXT Chooser filter pilots the output file extension. Ignored Used Used (GTK) +\endcode + */ +void Fl_My_Native_File_Chooser::options(int o) +{ + _x11_file_chooser->options(o); +} + +/** + Gets the platform specific Fl_My_Native_File_Chooser::Option flags. + */ +int Fl_My_Native_File_Chooser::options() const +{ + return _x11_file_chooser->options(); +} + +/** + Returns the number of filenames (or directory names) the user selected. +

+ \b Example: + \code + if ( fnfc->show() == 0 ) { + // Print all filenames user selected + for (int n=0; ncount(); n++ ) { + printf("%d) '%s'\n", n, fnfc->filename(n)); + } + } + \endcode + */ +int Fl_My_Native_File_Chooser::count() const +{ + return _x11_file_chooser->count(); +} + +/** + Return the filename the user chose. + Use this if only expecting a single filename. + If more than one filename is expected, use filename(int) instead. + Return value may be "" if no filename was chosen (eg. user cancelled). + */ +const char *Fl_My_Native_File_Chooser::filename() const +{ + return _x11_file_chooser->filename(); +} + +/** + Return one of the filenames the user selected. + Use count() to determine how many filenames the user selected. +

+ \b Example: + \code + if ( fnfc->show() == 0 ) { + // Print all filenames user selected + for (int n=0; ncount(); n++ ) { + printf("%d) '%s'\n", n, fnfc->filename(n)); + } + } + \endcode + */ +const char *Fl_My_Native_File_Chooser::filename(int i) const +{ + return _x11_file_chooser->filename(i); +} + +/** + Preset the directory the browser will show when opened. + If \p val is NULL, or no directory is specified, the chooser will attempt + to use the last non-cancelled folder. + */ +void Fl_My_Native_File_Chooser::directory(const char *val) +{ + _x11_file_chooser->directory(val); +} + +/** + Returns the current preset directory() value. + */ +const char *Fl_My_Native_File_Chooser::directory() const +{ + return _x11_file_chooser->directory(); +} + +/** + Set the title of the file chooser's dialog window. + Can be NULL if no title desired. + The default title varies according to the platform, so you are advised to set the title explicitly. + */ +void Fl_My_Native_File_Chooser::title(const char *t) +{ + _x11_file_chooser->title(t); +} + +/** + Get the title of the file chooser's dialog window. + Return value may be NULL if no title was set. + */ +const char *Fl_My_Native_File_Chooser::title() const +{ + return _x11_file_chooser->title(); +} + +/** + Returns the filter string last set. + Can be NULL if no filter was set. + */ +const char *Fl_My_Native_File_Chooser::filter() const +{ + return _x11_file_chooser->filter(); +} + +/** + Sets the filename filters used for browsing. + The default is NULL, which browses all files. +

+ The filter string can be any of: +

+ - A single wildcard (eg. "*.txt") + - Multiple wildcards (eg. "*.{cxx,h,H}") + - A descriptive name followed by a "\t" and a wildcard (eg. "Text Files\t*.txt") + - A list of separate wildcards with a "\n" between each (eg. "*.{cxx,H}\n*.txt") + - A list of descriptive names and wildcards (eg. "C++ Files\t*.{cxx,H}\nTxt Files\t*.txt") +

+ The format of each filter is a wildcard, or an optional user description + followed by '\\t' and the wildcard. +

+ On most platforms, each filter is available to the user via a pulldown menu + in the file chooser. The 'All Files' option is always available to the user. + */ +void Fl_My_Native_File_Chooser::filter(const char *f) +{ + _x11_file_chooser->filter(f); +} + +/** + Gets how many filters were available, not including "All Files" + */ +int Fl_My_Native_File_Chooser::filters() const +{ + return _x11_file_chooser->filters(); +} + +/** + Sets which filter will be initially selected. + + The first filter is indexed as 0. + If filter_value()==filters(), then "All Files" was chosen. + If filter_value() > filters(), then a custom filter was set. + */ +void Fl_My_Native_File_Chooser::filter_value(int i) +{ + _x11_file_chooser->filter_value(i); +} + +/** + Returns which filter value was last selected by the user. + This is only valid if the chooser returns success. + */ +int Fl_My_Native_File_Chooser::filter_value() const +{ + return _x11_file_chooser->filter_value(); +} + +/** + Sets the default filename for the chooser. + Use directory() to set the default directory. + Mainly used to preset the filename for save dialogs, + and on most platforms can be used for opening files as well. + */ +void Fl_My_Native_File_Chooser::preset_file(const char *f) +{ + _x11_file_chooser->preset_file(f); +} + +/** + Get the preset filename. + */ +const char *Fl_My_Native_File_Chooser::preset_file() const +{ + return _x11_file_chooser->preset_file(); +} + +/** + Returns a system dependent error message for the last method that failed. + This message should at least be flagged to the user in a dialog box, or to some kind of error log. + Contents will be valid only for methods that document errmsg() will have info on failures. + */ +const char *Fl_My_Native_File_Chooser::errmsg() const +{ + return _x11_file_chooser->errmsg(); +} + +/** + Post the chooser's dialog. Blocks until dialog has been completed or cancelled. + \returns + - 0 -- user picked a file + - 1 -- user cancelled + - -1 -- failed; errmsg() has reason + */ +int Fl_My_Native_File_Chooser::show() +{ + return _x11_file_chooser->show(); +} + +Fl_FLTK_File_Chooser::Fl_FLTK_File_Chooser(int val) +{ + _btype = 0; + _options = 0; + _filter = NULL; + _filtvalue = 0; + _parsedfilt = NULL; + _preset_file = NULL; + _prevvalue = NULL; + _directory = NULL; + _errmsg = NULL; + _file_chooser = NULL; + if (val >= 0) { + _file_chooser = new Fl_File_Chooser(NULL, NULL, 0, NULL); + type(val); // do this after _file_chooser created + } + _nfilters = 0; +} + +Fl_FLTK_File_Chooser::~Fl_FLTK_File_Chooser() +{ + delete _file_chooser; + _file_chooser = NULL; + _filter = strfree(_filter); + _parsedfilt = strfree(_parsedfilt); + _preset_file = strfree(_preset_file); + _prevvalue = strfree(_prevvalue); + _directory = strfree(_directory); + _errmsg = strfree(_errmsg); +} + +// PRIVATE: SET ERROR MESSAGE +void Fl_FLTK_File_Chooser::errmsg(const char *msg) +{ + _errmsg = strfree(_errmsg); + _errmsg = strnew(msg); +} + +// PRIVATE: translate Native types to Fl_File_Chooser types +int Fl_FLTK_File_Chooser::type_fl_file(int val) +{ + switch (val) { + case Fl_My_Native_File_Chooser::BROWSE_FILE: + return (Fl_File_Chooser::SINGLE); + case Fl_My_Native_File_Chooser::BROWSE_DIRECTORY: + return (Fl_File_Chooser::SINGLE | Fl_File_Chooser::DIRECTORY); + case Fl_My_Native_File_Chooser::BROWSE_MULTI_FILE: + return (Fl_File_Chooser::MULTI); + case Fl_My_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: + return (Fl_File_Chooser::DIRECTORY | Fl_File_Chooser::MULTI); + case Fl_My_Native_File_Chooser::BROWSE_SAVE_FILE: + return (Fl_File_Chooser::SINGLE | Fl_File_Chooser::CREATE); + case Fl_My_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: + return (Fl_File_Chooser::DIRECTORY | Fl_File_Chooser::MULTI | Fl_File_Chooser::CREATE); + default: + return (Fl_File_Chooser::SINGLE); + } +} + +void Fl_FLTK_File_Chooser::type(int val) +{ + _btype = val; + _file_chooser->type(type_fl_file(val)); +} + +int Fl_FLTK_File_Chooser::type() const +{ + return (_btype); +} + +void Fl_FLTK_File_Chooser::options(int val) +{ + _options = val; +} + +int Fl_FLTK_File_Chooser::options() const +{ + return (_options); +} + +int Fl_FLTK_File_Chooser::show() +{ + // FILTER + if (_parsedfilt) { + _file_chooser->filter(_parsedfilt); + } + + // FILTER VALUE + // Set this /after/ setting the filter + // + _file_chooser->filter_value(_filtvalue); + + // DIRECTORY + if (_directory && _directory[0]) { + _file_chooser->directory(_directory); + } + else { + _file_chooser->directory(_prevvalue); + } + + // PRESET FILE + if (_preset_file) { + _file_chooser->value(_preset_file); + } + + // OPTIONS: PREVIEW + _file_chooser->preview((options() & Fl_My_Native_File_Chooser::PREVIEW) ? 1 : 0); + + // OPTIONS: NEW FOLDER + if (options() & Fl_My_Native_File_Chooser::NEW_FOLDER) { + _file_chooser->type(_file_chooser->type() | Fl_File_Chooser::CREATE); // on + } + + // SHOW + _file_chooser->show(); + + // BLOCK WHILE BROWSER SHOWN + while (_file_chooser->shown()) { + Fl::wait(); + } + + if (_file_chooser->value() && _file_chooser->value()[0]) { + _prevvalue = strfree(_prevvalue); + _prevvalue = strnew(_file_chooser->value()); + _filtvalue = _file_chooser->filter_value(); // update filter value + + // HANDLE SHOWING 'SaveAs' CONFIRM + if (options() & Fl_My_Native_File_Chooser::SAVEAS_CONFIRM && type() == Fl_My_Native_File_Chooser::BROWSE_SAVE_FILE) { + struct stat buf; + if (stat(_file_chooser->value(), &buf) != -1) { + if (buf.st_mode & S_IFREG) { // Regular file + exists? + if (exist_dialog() == 0) { + return (1); + } + } + } + } + } + + if (_file_chooser->count()) { + return (0); + } + else { + return (1); + } +} + +const char *Fl_FLTK_File_Chooser::errmsg() const +{ + return (_errmsg ? _errmsg : "No error"); +} + +const char *Fl_FLTK_File_Chooser::filename() const +{ + if (_file_chooser->count() > 0) { + return (_file_chooser->value()); + } + return (""); +} + +const char *Fl_FLTK_File_Chooser::filename(int i) const +{ + if (i < _file_chooser->count()) { + return (_file_chooser->value(i + 1)); // convert fltk 1 based to our 0 based + } + return (""); +} + +void Fl_FLTK_File_Chooser::title(const char *val) +{ + _file_chooser->label(val); +} + +const char *Fl_FLTK_File_Chooser::title() const +{ + return (_file_chooser->label()); +} + +void Fl_FLTK_File_Chooser::filter(const char *val) +{ + _filter = strfree(_filter); + _filter = strnew(val); + parse_filter(); +} + +const char *Fl_FLTK_File_Chooser::filter() const +{ + return (_filter); +} + +int Fl_FLTK_File_Chooser::filters() const +{ + return (_nfilters); +} + +void Fl_FLTK_File_Chooser::filter_value(int val) +{ + _filtvalue = val; +} + +int Fl_FLTK_File_Chooser::filter_value() const +{ + return _filtvalue; +} + +int Fl_FLTK_File_Chooser::count() const +{ + return _file_chooser->count(); +} + +void Fl_FLTK_File_Chooser::directory(const char *val) +{ + _directory = strfree(_directory); + _directory = strnew(val); +} + +const char *Fl_FLTK_File_Chooser::directory() const +{ + return _directory; +} + +// PRIVATE: Convert our filter format to fltk's chooser format +// FROM TO (FLTK) +// ------------------------- -------------------------- +// "*.cxx" "*.cxx Files(*.cxx)" +// "C Files\t*.{cxx,h}" "C Files(*.{cxx,h})" +// "C Files\t*.{cxx,h}\nText Files\t*.txt" "C Files(*.{cxx,h})\tText Files(*.txt)" +// +// Returns a modified version of the filter that the caller is responsible +// for freeing with strfree(). +// +void Fl_FLTK_File_Chooser::parse_filter() +{ + _parsedfilt = strfree(_parsedfilt); // clear previous parsed filter (if any) + _nfilters = 0; + char *in = _filter; + if (!in) { + return; + } + + int has_name = strchr(in, '\t') ? 1 : 0; + + char mode = has_name ? 'n' : 'w'; // parse mode: n=title, w=wildcard + char wildcard[1024] = ""; // parsed wildcard + char name[1024] = ""; + + // Parse filter user specified + for (; 1; in++) { + /*** DEBUG + printf("WORKING ON '%c': mode=<%c> name=<%s> wildcard=<%s>\n", + *in, mode, name, wildcard); + ***/ + + switch (*in) { + // FINISHED PARSING NAME? + case '\t': + if (mode != 'n') { + goto regchar; + } + mode = 'w'; + break; + // ESCAPE NEXT CHAR + case '\\': + ++in; + goto regchar; + // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS? + case '\r': + case '\n': + case '\0': + // APPEND NEW FILTER TO LIST + if (wildcard[0]) { + // OUT: "name(wild)\tname(wild)" + char comp[2048]; + sprintf(comp, "%s%.511s(%.511s)", ((_parsedfilt) ? "\t" : ""), name, wildcard); + _parsedfilt = strapp(_parsedfilt, comp); + _nfilters++; + // DEBUG printf("DEBUG: PARSED FILT NOW <%s>\n", _parsedfilt); + } + // RESET + wildcard[0] = name[0] = '\0'; + mode = strchr(in, '\t') ? 'n' : 'w'; + // DONE? + if (*in == '\0') { + return; // done + } + else { + continue; // not done yet, more filters + } + + // Parse all other chars + default: // handle all non-special chars +regchar: // handle regular char + switch (mode) { + case 'n': + chrcat(name, *in); + continue; + case 'w': + chrcat(wildcard, *in); + continue; + } + break; + } + } + // NOTREACHED +} + +void Fl_FLTK_File_Chooser::preset_file(const char *val) +{ + _preset_file = strfree(_preset_file); + _preset_file = strnew(val); +} + +const char *Fl_FLTK_File_Chooser::preset_file() const +{ + return _preset_file; +} + +int Fl_FLTK_File_Chooser::exist_dialog() +{ + return fl_choice("%s", fl_cancel, fl_ok, NULL, Fl_My_Native_File_Chooser::file_exists_message); +} + +// +// End of "$Id$". +// diff --git a/src/FLTK/Fl_My_Native_File_Chooser_GTK.cxx b/src/FLTK/Fl_My_Native_File_Chooser_GTK.cxx new file mode 100644 index 0000000..f556c17 --- /dev/null +++ b/src/FLTK/Fl_My_Native_File_Chooser_GTK.cxx @@ -0,0 +1,769 @@ +// "$Id$" +// +// FLTK native file chooser widget wrapper for GTK's GtkFileChooserDialog +// +// Copyright 1998-2014 by Bill Spitzak and others. +// Copyright 2012 IMM +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// + +#include +#if HAVE_DLSYM && HAVE_DLFCN_H +#include // for dlopen et al +#endif +#include // for setlocale + +/* --------------------- Type definitions from GLIB and GTK --------------------- */ +/* all of this is from the public gnome API, so unlikely to change */ +#ifndef FALSE +#define FALSE (0) +#endif +#ifndef TRUE +#define TRUE (!FALSE) +#endif +typedef void *gpointer; +typedef int gint; +typedef unsigned int guint; +typedef unsigned long gulong; +typedef gint gboolean; +typedef char gchar; +typedef struct _GSList GSList; +struct _GSList { + gpointer data; + GSList *next; +}; +#define g_slist_next(slist) ((slist) ? (((GSList *)(slist))->next) : NULL) +typedef struct _GtkWidget GtkWidget; +typedef struct _GtkFileChooser GtkFileChooser; +typedef struct _GtkDialog GtkDialog; +typedef struct _GtkWindow GtkWindow; +typedef struct _GdkDrawable GdkWindow; +typedef struct _GtkFileFilter GtkFileFilter; +typedef struct _GtkToggleButton GtkToggleButton; +typedef enum { + GTK_FILE_FILTER_FILENAME = 1 << 0, + GTK_FILE_FILTER_URI = 1 << 1, + GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2, + GTK_FILE_FILTER_MIME_TYPE = 1 << 3 +} GtkFileFilterFlags; +struct _GtkFileFilterInfo { + GtkFileFilterFlags contains; + + const gchar *filename; + const gchar *uri; + const gchar *display_name; + const gchar *mime_type; +}; +typedef struct _GtkFileFilterInfo GtkFileFilterInfo; +typedef gboolean (*GtkFileFilterFunc)(const GtkFileFilterInfo *filter_info, gpointer data); +typedef void (*GDestroyNotify)(gpointer data); +typedef enum { + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, + GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER +} GtkFileChooserAction; +#define GTK_STOCK_CANCEL "gtk-cancel" +#define GTK_STOCK_SAVE "gtk-save" +#define GTK_STOCK_OPEN "gtk-open" +const int GTK_RESPONSE_NONE = -1; +const int GTK_RESPONSE_ACCEPT = -3; +const int GTK_RESPONSE_DELETE_EVENT = -4; +const int GTK_RESPONSE_CANCEL = -6; +typedef void (*GCallback)(void); +#define G_CALLBACK(f) ((GCallback)(f)) +typedef int GConnectFlags; +typedef struct _GClosure GClosure; +typedef void (*GClosureNotify)(gpointer data, GClosure *closure); + +/* --------------------- End of Type definitions from GLIB and GTK --------------------- */ + +int Fl_GTK_File_Chooser::did_find_GTK_libs = 0; + +/* These are the GTK/GLib methods we want to load, but not call by name...! */ + +// void g_free (gpointer mem); +typedef void (*XX_g_free)(gpointer); +static XX_g_free fl_g_free = NULL; + +// gpointer g_slist_nth_data (GSList *list, guint n); +typedef gpointer (*XX_g_slist_nth_data)(GSList *, guint); +static XX_g_slist_nth_data fl_g_slist_nth_data = NULL; + +// guint g_slist_length (GSList *list); +typedef guint (*XX_g_slist_length)(GSList *); +static XX_g_slist_length fl_g_slist_length = NULL; + +// void g_slist_free (GSList *list); +typedef void (*XX_g_slist_free)(GSList *); +static XX_g_slist_free fl_g_slist_free = NULL; + +// gboolean gtk_init_check (int *argc, char ***argv); +typedef gboolean (*XX_gtk_init_check)(int *, char ***); +static XX_gtk_init_check fl_gtk_init_check = NULL; + +// void gtk_widget_destroy (GtkWidget *widget); +typedef void (*XX_gtk_widget_destroy)(GtkWidget *); +static XX_gtk_widget_destroy fl_gtk_widget_destroy = NULL; + +// void gtk_file_chooser_set_select_multiple(GtkFileChooser *chooser, gboolean select_multiple); +typedef void (*XX_gtk_file_chooser_set_select_multiple)(GtkFileChooser *, gboolean); +static XX_gtk_file_chooser_set_select_multiple fl_gtk_file_chooser_set_select_multiple = NULL; + +// void gtk_file_chooser_set_do_overwrite_confirmation(GtkFileChooser *chooser, gboolean do_overwrite_confirmation); +typedef void (*XX_gtk_file_chooser_set_do_overwrite_confirmation)(GtkFileChooser *, gboolean); +static XX_gtk_file_chooser_set_do_overwrite_confirmation fl_gtk_file_chooser_set_do_overwrite_confirmation = NULL; + +// void gtk_file_chooser_set_current_name (GtkFileChooser *chooser, const gchar *name); +typedef void (*XX_gtk_file_chooser_set_current_name)(GtkFileChooser *, const gchar *); +static XX_gtk_file_chooser_set_current_name fl_gtk_file_chooser_set_current_name = NULL; + +// void gtk_file_chooser_set_current_folder (GtkFileChooser *chooser, const gchar *name); +typedef void (*XX_gtk_file_chooser_set_current_folder)(GtkFileChooser *, const gchar *); +static XX_gtk_file_chooser_set_current_folder fl_gtk_file_chooser_set_current_folder = NULL; + +// void gtk_file_chooser_set_create_folders (GtkFileChooser *chooser, gboolean create_folders); +typedef void (*XX_gtk_file_chooser_set_create_folders)(GtkFileChooser *, gboolean); +static XX_gtk_file_chooser_set_create_folders fl_gtk_file_chooser_set_create_folders = NULL; + +// gboolean gtk_file_chooser_get_select_multiple(GtkFileChooser *chooser); +typedef gboolean (*XX_gtk_file_chooser_get_select_multiple)(GtkFileChooser *); +static XX_gtk_file_chooser_get_select_multiple fl_gtk_file_chooser_get_select_multiple = NULL; + +// void gtk_widget_hide(GtkWidget *widget); +typedef void (*XX_gtk_widget_hide)(GtkWidget *); +static XX_gtk_widget_hide fl_gtk_widget_hide = NULL; + +// gchar * gtk_file_chooser_get_filename(GtkFileChooser *chooser); +typedef gchar *(*XX_gtk_file_chooser_get_filename)(GtkFileChooser *); +static XX_gtk_file_chooser_get_filename fl_gtk_file_chooser_get_filename = NULL; + +// GSList * gtk_file_chooser_get_filenames(GtkFileChooser *chooser); +typedef GSList *(*XX_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); +static XX_gtk_file_chooser_get_filenames fl_gtk_file_chooser_get_filenames = NULL; + +// gboolean gtk_main_iteration(void); +typedef gboolean (*XX_gtk_main_iteration)(void); +static XX_gtk_main_iteration fl_gtk_main_iteration = NULL; + +// gboolean gtk_events_pending(void); +typedef gboolean (*XX_gtk_events_pending)(void); +static XX_gtk_events_pending fl_gtk_events_pending = NULL; + +// GtkWidget * gtk_file_chooser_dialog_new(const gchar *title, GtkWindow *parent, GtkFileChooserAction action, const gchar *first_button_text, ...); +typedef GtkWidget *(*XX_gtk_file_chooser_dialog_new)(const gchar *, GtkWindow *, GtkFileChooserAction, const gchar *, ...); +static XX_gtk_file_chooser_dialog_new fl_gtk_file_chooser_dialog_new = NULL; + +// void gtk_file_chooser_add_filter(GtkFileChooser*, GtkFileFilter*); +typedef void (*XX_gtk_file_chooser_add_filter)(GtkFileChooser *, GtkFileFilter *); +static XX_gtk_file_chooser_add_filter fl_gtk_file_chooser_add_filter = NULL; + +// GtkFileFilter* gtk_file_chooser_get_filter(GtkFileChooser*); +typedef GtkFileFilter *(*XX_gtk_file_chooser_get_filter)(GtkFileChooser *); +static XX_gtk_file_chooser_get_filter fl_gtk_file_chooser_get_filter = NULL; + +// void gtk_file_chooser_set_filter(GtkFileChooser*, GtkFileFilter*); +typedef void (*XX_gtk_file_chooser_set_filter)(GtkFileChooser *, GtkFileFilter *); +static XX_gtk_file_chooser_set_filter fl_gtk_file_chooser_set_filter = NULL; + +// GtkFileFilter * gtk_file_filter_new(); +typedef GtkFileFilter *(*XX_gtk_file_filter_new)(void); +static XX_gtk_file_filter_new fl_gtk_file_filter_new = NULL; + +// void gtk_file_filter_add_pattern(GtkFileFilter*, const gchar*); +typedef void (*XX_gtk_file_filter_add_pattern)(GtkFileFilter *, const gchar *); +static XX_gtk_file_filter_add_pattern fl_gtk_file_filter_add_pattern = NULL; + +// void gtk_file_filter_add_custom(GtkFileFilter *filter, GtkFileFilterFlags needed, +// GtkFileFilterFunc func, gpointer data, GDestroyNotify notify); +typedef void (*XX_gtk_file_filter_add_custom)(GtkFileFilter *filter, GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data, GDestroyNotify notify); +static XX_gtk_file_filter_add_custom fl_gtk_file_filter_add_custom = NULL; + +// void gtk_file_filter_set_name(GtkFileFilter*, const gchar*); +typedef void (*XX_gtk_file_filter_set_name)(GtkFileFilter *, const gchar *); +static XX_gtk_file_filter_set_name fl_gtk_file_filter_set_name = NULL; + +// const gchar* gtk_file_filter_get_name(GtkFileFilter*); +typedef const gchar *(*XX_gtk_file_filter_get_name)(GtkFileFilter *); +static XX_gtk_file_filter_get_name fl_gtk_file_filter_get_name = NULL; + +// void gtk_file_chooser_set_extra_widget(GtkFileChooser *, GtkWidget *); +typedef void (*XX_gtk_file_chooser_set_extra_widget)(GtkFileChooser *, GtkWidget *); +static XX_gtk_file_chooser_set_extra_widget fl_gtk_file_chooser_set_extra_widget = NULL; + +// void gtk_widget_show_now(GtkWidget *); +typedef void (*XX_gtk_widget_show_now)(GtkWidget *); +static XX_gtk_widget_show_now fl_gtk_widget_show_now = NULL; + +// GdkWindow* gtk_widget_get_window(GtkWidget *); +typedef GdkWindow *(*XX_gtk_widget_get_window)(GtkWidget *); +static XX_gtk_widget_get_window fl_gtk_widget_get_window = NULL; + +// Window gdk_x11_drawable_get_xid(GdkWindow *); +typedef Window (*XX_gdk_x11_drawable_get_xid)(GdkWindow *); +static XX_gdk_x11_drawable_get_xid fl_gdk_x11_drawable_get_xid = NULL; + +// GtkWidget *gtk_check_button_new_with_label(const gchar *); +typedef GtkWidget *(*XX_gtk_check_button_new_with_label)(const gchar *); +static XX_gtk_check_button_new_with_label fl_gtk_check_button_new_with_label = NULL; + +// gulong g_signal_connect_data(gpointer, const gchar *, GCallback, gpointer, GClosureNotify, GConnectFlags); +typedef gulong (*XX_g_signal_connect_data)(gpointer, const gchar *, GCallback, gpointer, GClosureNotify, GConnectFlags); +static XX_g_signal_connect_data fl_g_signal_connect_data = NULL; + +// gboolean gtk_toggle_button_get_active(GtkToggleButton *); +typedef gboolean (*XX_gtk_toggle_button_get_active)(GtkToggleButton *); +static XX_gtk_toggle_button_get_active fl_gtk_toggle_button_get_active = NULL; + +// void gtk_file_chooser_set_show_hidden(GtkFileChooser *, gboolean); +typedef void (*XX_gtk_file_chooser_set_show_hidden)(GtkFileChooser *, gboolean); +static XX_gtk_file_chooser_set_show_hidden fl_gtk_file_chooser_set_show_hidden = NULL; + +// gboolean gtk_file_chooser_get_show_hidden(GtkFileChooser *); +typedef gboolean (*XX_gtk_file_chooser_get_show_hidden)(GtkFileChooser *); +static XX_gtk_file_chooser_get_show_hidden fl_gtk_file_chooser_get_show_hidden = NULL; + +// void gtk_toggle_button_set_active(GtkToggleButton *, gboolean); +typedef void (*XX_gtk_toggle_button_set_active)(GtkToggleButton *, gboolean); +static XX_gtk_toggle_button_set_active fl_gtk_toggle_button_set_active = NULL; + +Fl_GTK_File_Chooser::Fl_GTK_File_Chooser(int val) : Fl_FLTK_File_Chooser(-1) +{ + gtkw_ptr = NULL; // used to hold a GtkWidget* + gtkw_slist = NULL; // will hold the returned file names in a multi-selection... + gtkw_count = 0; // How many items were selected? + gtkw_filename = NULL; // holds the last name we read back in a single file selection... + gtkw_title = NULL; // dialog title + _btype = val; + previous_filter = NULL; +} + +Fl_GTK_File_Chooser::~Fl_GTK_File_Chooser() +{ + // Should free up resources taken for... + if (gtkw_ptr) { + fl_gtk_widget_destroy(gtkw_ptr); + gtkw_ptr = NULL; + } + if (gtkw_filename) { + fl_g_free(gtkw_filename); + gtkw_filename = NULL; + } + if (gtkw_slist) { + GSList *iter = (GSList *)gtkw_slist; + while (iter) { + if (iter->data) { + fl_g_free(iter->data); + } + iter = g_slist_next(iter); + } + fl_g_slist_free((GSList *)gtkw_slist); + gtkw_slist = NULL; + } + gtkw_count = 0; // assume we have no files selected now + gtkw_title = strfree(gtkw_title); +} + +void Fl_GTK_File_Chooser::type(int val) +{ + _btype = val; +} + +int Fl_GTK_File_Chooser::count() const +{ + return gtkw_count; +} + +const char *Fl_GTK_File_Chooser::filename() const +{ + if (gtkw_ptr) { + if (fl_gtk_file_chooser_get_select_multiple((GtkFileChooser *)gtkw_ptr) == FALSE) { + return gtkw_filename; + } + else { + GSList *iter = (GSList *)gtkw_slist; + char *nm = (char *)iter->data; + return nm; + } + } + return (""); +} + +const char *Fl_GTK_File_Chooser::filename(int i) const +{ + if (fl_gtk_file_chooser_get_select_multiple((GtkFileChooser *)gtkw_ptr) == FALSE) { + return gtkw_filename; + } + else { + if ((unsigned)i < gtkw_count) { + GSList *iter = (GSList *)gtkw_slist; + char *nm = (char *)fl_g_slist_nth_data(iter, i); + return nm; + } + } + return (""); +} + +void Fl_GTK_File_Chooser::title(const char *val) +{ + strfree(gtkw_title); + gtkw_title = strnew(val); +} + +const char *Fl_GTK_File_Chooser::title() const +{ + return gtkw_title; +} + +/* changes the extension of the outfile in the chooser according to newly selected filter */ +void Fl_GTK_File_Chooser::changed_output_type(const char *filter) +{ + if (!(options() & Fl_My_Native_File_Chooser::USE_FILTER_EXT)) { + return; + } + if (strchr(filter, '(') || strchr(filter, '{') || strchr(filter + 1, '*') || strncmp(filter, "*.", 2)) { + return; + } + const char *p = fl_gtk_file_chooser_get_filename((GtkFileChooser *)gtkw_ptr); + if (!p) { + return; + } + p = fl_filename_name(p); + const char *q = strrchr(p, '.'); + if (!q) { + q = p + strlen(p); + } + char *r = new char[strlen(p) + strlen(filter)]; + strcpy(r, p); + strcpy(r + (q - p), filter + 1); + fl_gtk_file_chooser_set_current_name((GtkFileChooser *)gtkw_ptr, r); + delete[] r; +} + +/* Filters files before display in chooser. + Also used to detect when the filter just changed */ +gboolean Fl_GTK_File_Chooser::custom_gtk_filter_function(const GtkFileFilterInfo *info, Fl_GTK_File_Chooser::pair *p) +{ + if (p->running->previous_filter != p->filter) { + p->running->changed_output_type(p->filter); + p->running->previous_filter = p->filter; + } + return (gboolean)fl_filename_match(fl_filename_name(info->filename), p->filter); +} + +void Fl_GTK_File_Chooser::free_pair(Fl_GTK_File_Chooser::pair *p) +{ + delete p; +} + +static void hidden_files_cb(GtkToggleButton *togglebutton, gpointer user_data) +{ + gboolean state = fl_gtk_toggle_button_get_active(togglebutton); + fl_gtk_file_chooser_set_show_hidden((GtkFileChooser *)user_data, state); +} + +int Fl_GTK_File_Chooser::show() +{ + // The point here is that after running a GTK dialog, the calling program's current locale is modified. + // To avoid that, we memorize the calling program's current locale, and the locale as modified + // by GTK after the first dialog use. We restore the calling program's current locale + // before returning, and we set the locale as modified by GTK before subsequent GTK dialog uses. + static bool first = true; + char *p; + char *before = NULL; + static char *gtk_wants = NULL; + fl_open_display(); + // record in before the calling program's current locale + p = setlocale(LC_ALL, NULL); + if (p) { + before = strdup(p); + } + if (gtk_wants) { // set the locale as GTK 'wants it' + setlocale(LC_ALL, gtk_wants); + } + int retval = fl_gtk_chooser_wrapper(); // may change the locale + if (first) { + first = false; + // record in gtk_wants the locale as modified by the GTK dialog + p = setlocale(LC_ALL, NULL); + if (p) { + gtk_wants = strdup(p); + } + } + if (before) { + setlocale(LC_ALL, before); // restore calling program's current locale + free(before); + } + return retval; +} + +static char *extract_dir_from_path(const char *path) +{ + static char *dir = NULL; + if (fl_filename_isdir(path)) { + return (char *)path; + } + if (*path != '/') { + return NULL; + } + if (dir) { + free(dir); + } + dir = strdup(path); + do { + char *p = strrchr(dir, '/'); + if (p == dir) { + p++; + } + *p = 0; + } while (!fl_filename_isdir(dir)); + return dir; +} + +static void run_response_handler(GtkDialog *dialog, gint response_id, gpointer data) +{ + gint *ri = (gint *)data; + *ri = response_id; +} + +int Fl_GTK_File_Chooser::fl_gtk_chooser_wrapper() +{ + int result = 1; + static int have_gtk_init = 0; + char *p; + + if (!have_gtk_init) { + have_gtk_init = -1; + int ac = 0; + fl_gtk_init_check(&ac, NULL); + } + + if (gtkw_ptr) { // discard the previous dialog widget + fl_gtk_widget_destroy(gtkw_ptr); + gtkw_ptr = NULL; + } + + // set the dialog action type + GtkFileChooserAction gtw_action_type; + switch (_btype) { + case Fl_My_Native_File_Chooser::BROWSE_DIRECTORY: + case Fl_My_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: + gtw_action_type = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; + break; + + case Fl_My_Native_File_Chooser::BROWSE_SAVE_FILE: + gtw_action_type = GTK_FILE_CHOOSER_ACTION_SAVE; + break; + + case Fl_My_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: + gtw_action_type = GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER; + break; + + case Fl_My_Native_File_Chooser::BROWSE_MULTI_FILE: + case Fl_My_Native_File_Chooser::BROWSE_FILE: + default: + gtw_action_type = GTK_FILE_CHOOSER_ACTION_OPEN; + break; + } + // create a new dialog + gtkw_ptr = fl_gtk_file_chooser_dialog_new( + gtkw_title, NULL, /* parent_window */ + gtw_action_type, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + gtw_action_type == GTK_FILE_CHOOSER_ACTION_SAVE || gtw_action_type == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER ? GTK_STOCK_SAVE : GTK_STOCK_OPEN, + GTK_RESPONSE_ACCEPT, NULL); + // did we create a valid dialog widget? + if (!gtkw_ptr) { + // fail + return -1; + } + + // set the dialog properties + switch (_btype) { + case Fl_My_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: + case Fl_My_Native_File_Chooser::BROWSE_MULTI_FILE: + fl_gtk_file_chooser_set_select_multiple((GtkFileChooser *)gtkw_ptr, TRUE); + break; + + case Fl_My_Native_File_Chooser::BROWSE_SAVE_FILE: + if (_preset_file) { + fl_gtk_file_chooser_set_current_name((GtkFileChooser *)gtkw_ptr, fl_filename_name(_preset_file)); + } + /* FALLTHROUGH */ + case Fl_My_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: + fl_gtk_file_chooser_set_create_folders((GtkFileChooser *)gtkw_ptr, TRUE); + fl_gtk_file_chooser_set_do_overwrite_confirmation((GtkFileChooser *)gtkw_ptr, (_options & Fl_My_Native_File_Chooser::SAVEAS_CONFIRM) ? TRUE : FALSE); + break; + + case Fl_My_Native_File_Chooser::BROWSE_DIRECTORY: + case Fl_My_Native_File_Chooser::BROWSE_FILE: + default: + break; + } + + if (_directory && _directory[0]) { + p = extract_dir_from_path(_directory); + if (p) { + fl_gtk_file_chooser_set_current_folder((GtkFileChooser *)gtkw_ptr, p); + } + } + else if (_preset_file) { + p = extract_dir_from_path(_preset_file); + if (p) { + fl_gtk_file_chooser_set_current_folder((GtkFileChooser *)gtkw_ptr, p); + } + } + + GtkFileFilter **filter_tab = NULL; + if (_parsedfilt) { + filter_tab = new GtkFileFilter *[_nfilters]; + char *filter = strdup(_parsedfilt); + p = strtok(filter, "\t"); + int count = 0; + while (p) { + filter_tab[count] = fl_gtk_file_filter_new(); + fl_gtk_file_filter_set_name(filter_tab[count], p); + p = strchr(p, '(') + 1; + char *q = strchr(p, ')'); + *q = 0; + fl_gtk_file_filter_add_custom(filter_tab[count], GTK_FILE_FILTER_FILENAME, (GtkFileFilterFunc)Fl_GTK_File_Chooser::custom_gtk_filter_function, + new Fl_GTK_File_Chooser::pair(this, p), (GDestroyNotify)Fl_GTK_File_Chooser::free_pair); + fl_gtk_file_chooser_add_filter((GtkFileChooser *)gtkw_ptr, filter_tab[count]); + p = strtok(NULL, "\t"); + count++; + } + free(filter); + fl_gtk_file_chooser_set_filter((GtkFileChooser *)gtkw_ptr, filter_tab[_filtvalue < _nfilters ? _filtvalue : 0]); + previous_filter = NULL; + if (gtw_action_type == GTK_FILE_CHOOSER_ACTION_OPEN) { + GtkFileFilter *gfilter = fl_gtk_file_filter_new(); + fl_gtk_file_filter_set_name(gfilter, Fl_File_Chooser::all_files_label); + fl_gtk_file_filter_add_pattern(gfilter, "*"); + fl_gtk_file_chooser_add_filter((GtkFileChooser *)gtkw_ptr, gfilter); + } + } + + GtkWidget *toggle = fl_gtk_check_button_new_with_label(Fl_File_Chooser::hidden_label); + fl_gtk_file_chooser_set_extra_widget((GtkFileChooser *)gtkw_ptr, toggle); + fl_g_signal_connect_data(toggle, "toggled", G_CALLBACK(hidden_files_cb), gtkw_ptr, NULL, (GConnectFlags)0); + Fl_Window *firstw = Fl::first_window(); + fl_gtk_widget_show_now(gtkw_ptr); // map the GTK window on screen + if (firstw) { + GdkWindow *gdkw = fl_gtk_widget_get_window(gtkw_ptr); + Window xw = fl_gdk_x11_drawable_get_xid(gdkw); // get the X11 ref of the GTK window + XSetTransientForHint(fl_display, xw, fl_xid(firstw)); // set the GTK window transient for the last FLTK win + } + gboolean state = fl_gtk_file_chooser_get_show_hidden((GtkFileChooser *)gtkw_ptr); + fl_gtk_toggle_button_set_active((GtkToggleButton *)toggle, state); + + gint response_id = GTK_RESPONSE_NONE; + fl_g_signal_connect_data(gtkw_ptr, "response", G_CALLBACK(run_response_handler), &response_id, NULL, (GConnectFlags)0); + while (response_id == GTK_RESPONSE_NONE) { // loop that shows the GTK dialog window + fl_gtk_main_iteration(); // one iteration of the GTK event loop + while (XEventsQueued(fl_display, QueuedAfterReading)) { // emulate modal dialog + XEvent xevent; + XNextEvent(fl_display, &xevent); + Window xid = xevent.xany.window; + if (xevent.type == ConfigureNotify) { + xid = xevent.xmaprequest.window; + } + if (!fl_find(xid)) { + continue; // skip events to non-FLTK windows + } + // process Expose and ConfigureNotify events + if (xevent.type == Expose || xevent.type == ConfigureNotify) { + fl_handle(xevent); + } + } + Fl::flush(); // do the drawings needed after Expose events + } + + if (response_id == GTK_RESPONSE_ACCEPT) { + if (_parsedfilt) { + GtkFileFilter *gfilter = fl_gtk_file_chooser_get_filter((GtkFileChooser *)gtkw_ptr); + for (_filtvalue = 0; _filtvalue < _nfilters; _filtvalue++) { + if (filter_tab[_filtvalue] == gfilter) { + break; + } + } + } + + // discard any filenames or lists from previous calls + if (gtkw_filename) { + fl_g_free(gtkw_filename); + gtkw_filename = NULL; + } + if (gtkw_slist) { + GSList *iter = (GSList *)gtkw_slist; + while (iter) { + if (iter->data) { + fl_g_free(iter->data); + } + iter = g_slist_next(iter); + } + fl_g_slist_free((GSList *)gtkw_slist); + gtkw_slist = NULL; + } + gtkw_count = 0; // assume we have no files selected now + + if (fl_gtk_file_chooser_get_select_multiple((GtkFileChooser *)gtkw_ptr) == FALSE) { + gtkw_filename = fl_gtk_file_chooser_get_filename((GtkFileChooser *)gtkw_ptr); + if (gtkw_filename) { + gtkw_count = 1; + result = 0; + // printf("single: %s\n", gtkw_filename); + } + } + else { + gtkw_slist = fl_gtk_file_chooser_get_filenames((GtkFileChooser *)gtkw_ptr); + gtkw_count = fl_g_slist_length((GSList *)gtkw_slist); + if (gtkw_count) { + result = 0; + } + + // puts("multiple"); + // GSList *iter = (GSList *)gtkw_slist; + // printf ("Selected %d files\n", gtkw_count); + // while(iter) { + // char *nm = (char *)iter->data; + // printf("%s\n", nm); + // iter = g_slist_next(iter); + // } + } + } + delete[] filter_tab; + if (response_id == GTK_RESPONSE_DELETE_EVENT) { + gtkw_ptr = NULL; + } + else { + fl_gtk_widget_hide(gtkw_ptr); + } + + // I think this is analogus to doing an Fl::check() - we need this here to make sure + // the GtkFileChooserDialog is removed from the display correctly + while (fl_gtk_events_pending()) + fl_gtk_main_iteration(); + + return result; +} // fl_gtk_chooser_wrapper + +#if HAVE_DLSYM && HAVE_DLFCN_H +// macro to help with the symbol loading boilerplate... +#define GET_SYM(SSS, LLL) \ + dlerror(); /* Clear any existing error */ \ + fl_##SSS = (XX_##SSS)dlsym(LLL, #SSS); \ + if ((pc_dl_error = dlerror()) != NULL) { \ + fprintf(stderr, "%s\n", pc_dl_error); \ + did_find_GTK_libs = 0; \ + return; \ + } + +static void *fl_dlopen(const char *filename1, const char *filename2) +{ + void *ptr = dlopen(filename1, RTLD_LAZY | RTLD_GLOBAL); + if (!ptr) { + ptr = dlopen(filename2, RTLD_LAZY | RTLD_GLOBAL); + } + return ptr; +} +#endif + +/* + * Use dlopen to see if we can load the gtk dynamic libraries that + * will allow us to create a GtkFileChooserDialog() on the fly, + * without linking to the GTK libs at compile time. + */ +void Fl_GTK_File_Chooser::probe_for_GTK_libs(void) +{ +#if HAVE_DLSYM && HAVE_DLFCN_H + void *ptr_glib = NULL; + void *ptr_gtk = NULL; + +#ifdef __APPLE_CC__ // allows testing on Darwin + X11 + ptr_glib = dlopen("/sw/lib/libglib-2.0.dylib", RTLD_LAZY | RTLD_GLOBAL); +#else + ptr_glib = fl_dlopen("libglib-2.0.so", "libglib-2.0.so.0"); +#endif + // Try first with GTK2 +#ifdef __APPLE_CC__ // allows testing on Darwin + X11 + ptr_gtk = dlopen("/sw/lib/libgtk-x11-2.0.dylib", RTLD_LAZY | RTLD_GLOBAL); +#else + ptr_gtk = fl_dlopen("libgtk-x11-2.0.so", "libgtk-x11-2.0.so.0"); +#endif + if (ptr_gtk && ptr_glib) { +#ifdef DEBUG + puts("selected GTK-2\n"); +#endif + } + else { // Try then with GTK3 + ptr_gtk = fl_dlopen("libgtk-3.so", "libgtk-3.so.0"); +#ifdef DEBUG + if (ptr_gtk && ptr_glib) { + puts("selected GTK-3\n"); + } +#endif + } + + if ((!ptr_glib) || (!ptr_gtk)) { +#ifdef DEBUG + puts("Failure to load libglib or libgtk"); +#endif + did_find_GTK_libs = 0; + return; + } + + char *pc_dl_error; // used to report errors by the GET_SYM macro... + // items we need from GLib + GET_SYM(g_free, ptr_glib); + GET_SYM(g_slist_nth_data, ptr_glib); + GET_SYM(g_slist_length, ptr_glib); + GET_SYM(g_slist_free, ptr_glib); + // items we need from GTK + GET_SYM(gtk_init_check, ptr_gtk); + GET_SYM(gtk_widget_destroy, ptr_gtk); + GET_SYM(gtk_file_chooser_set_select_multiple, ptr_gtk); + GET_SYM(gtk_file_chooser_set_do_overwrite_confirmation, ptr_gtk); + GET_SYM(gtk_file_chooser_set_current_name, ptr_gtk); + GET_SYM(gtk_file_chooser_set_current_folder, ptr_gtk); + GET_SYM(gtk_file_chooser_set_create_folders, ptr_gtk); + GET_SYM(gtk_file_chooser_get_select_multiple, ptr_gtk); + GET_SYM(gtk_widget_hide, ptr_gtk); + GET_SYM(gtk_file_chooser_get_filename, ptr_gtk); + GET_SYM(gtk_file_chooser_get_filenames, ptr_gtk); + GET_SYM(gtk_main_iteration, ptr_gtk); + GET_SYM(gtk_events_pending, ptr_gtk); + GET_SYM(gtk_file_chooser_dialog_new, ptr_gtk); + GET_SYM(gtk_file_chooser_add_filter, ptr_gtk); + GET_SYM(gtk_file_chooser_get_filter, ptr_gtk); + GET_SYM(gtk_file_chooser_set_filter, ptr_gtk); + GET_SYM(gtk_file_filter_new, ptr_gtk); + GET_SYM(gtk_file_filter_add_pattern, ptr_gtk); + GET_SYM(gtk_file_filter_add_custom, ptr_gtk); + GET_SYM(gtk_file_filter_set_name, ptr_gtk); + GET_SYM(gtk_file_filter_get_name, ptr_gtk); + GET_SYM(gtk_file_chooser_set_extra_widget, ptr_gtk); + GET_SYM(gtk_widget_show_now, ptr_gtk); + GET_SYM(gtk_widget_get_window, ptr_gtk); + GET_SYM(gdk_x11_drawable_get_xid, ptr_gtk); + GET_SYM(gtk_check_button_new_with_label, ptr_gtk); + GET_SYM(g_signal_connect_data, ptr_gtk); + GET_SYM(gtk_toggle_button_get_active, ptr_gtk); + GET_SYM(gtk_file_chooser_set_show_hidden, ptr_gtk); + GET_SYM(gtk_file_chooser_get_show_hidden, ptr_gtk); + GET_SYM(gtk_toggle_button_set_active, ptr_gtk); + + did_find_GTK_libs = 1; +#endif +} // probe_for_GTK_libs + +// +// End of "$Id$". +// diff --git a/src/FLTK/Fl_My_Native_File_Chooser_MAC.mm b/src/FLTK/Fl_My_Native_File_Chooser_MAC.mm new file mode 100644 index 0000000..b6a71b1 --- /dev/null +++ b/src/FLTK/Fl_My_Native_File_Chooser_MAC.mm @@ -0,0 +1,676 @@ +// "$Id$" +// +// FLTK native OS file chooser widget +// +// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 2004 Greg Ercolano. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// + + +#ifdef __APPLE__ + +#include "Fl_My_Native_File_Chooser_common.cxx" // strnew/strfree/strapp/chrcat +#include // dirname(3) +#include // stat(2) +#include // stat(2) + + +#include +#include +#include "FL/Fl_My_Native_File_Chooser.H" +#include +#include + +// FREE PATHNAMES ARRAY, IF IT HAS ANY CONTENTS +void Fl_My_Native_File_Chooser::clear_pathnames() { + if ( _pathnames ) { + while ( --_tpathnames >= 0 ) { + _pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]); + } + delete [] _pathnames; + _pathnames = NULL; + } + _tpathnames = 0; +} + +// SET A SINGLE PATHNAME +void Fl_My_Native_File_Chooser::set_single_pathname(const char *s) { + clear_pathnames(); + _pathnames = new char*[1]; + _pathnames[0] = strnew(s); + _tpathnames = 1; +} + +// CONSTRUCTOR +Fl_My_Native_File_Chooser::Fl_My_Native_File_Chooser(int val) { + _btype = val; + _panel = NULL; + _options = NO_OPTIONS; + _pathnames = NULL; + _tpathnames = 0; + _title = NULL; + _filter = NULL; + _filt_names = NULL; + memset(_filt_patt, 0, sizeof(char*) * MAXFILTERS); + _filt_total = 0; + _filt_value = 0; + _directory = NULL; + _preset_file = NULL; + _errmsg = NULL; +} + +// DESTRUCTOR +Fl_My_Native_File_Chooser::~Fl_My_Native_File_Chooser() { + // _opts // nothing to manage + // _options // nothing to manage + // _keepstate // nothing to manage + // _tempitem // nothing to manage + clear_pathnames(); + _directory = strfree(_directory); + _title = strfree(_title); + _preset_file = strfree(_preset_file); + _filter = strfree(_filter); + //_filt_names // managed by clear_filters() + //_filt_patt[i] // managed by clear_filters() + //_filt_total // managed by clear_filters() + clear_filters(); + //_filt_value // nothing to manage + _errmsg = strfree(_errmsg); +} + +// GET TYPE OF BROWSER +int Fl_My_Native_File_Chooser::type() const { + return(_btype); +} + +// SET OPTIONS +void Fl_My_Native_File_Chooser::options(int val) { + _options = val; +} + +// GET OPTIONS +int Fl_My_Native_File_Chooser::options() const { + return(_options); +} + +// SHOW THE BROWSER WINDOW +// Returns: +// 0 - user picked a file +// 1 - user cancelled +// -1 - failed; errmsg() has reason +// +int Fl_My_Native_File_Chooser::show() { + + // Make sure fltk interface updates before posting our dialog + Fl::flush(); + + // POST BROWSER + int err = post(); + + return(err); +} + +// SET ERROR MESSAGE +// Internal use only. +// +void Fl_My_Native_File_Chooser::errmsg(const char *msg) { + _errmsg = strfree(_errmsg); + _errmsg = strnew(msg); +} + +// RETURN ERROR MESSAGE +const char *Fl_My_Native_File_Chooser::errmsg() const { + return(_errmsg ? _errmsg : "No error"); +} + +// GET FILENAME +const char* Fl_My_Native_File_Chooser::filename() const { + if ( _pathnames && _tpathnames > 0 ) return(_pathnames[0]); + return(""); +} + +// GET FILENAME FROM LIST OF FILENAMES +const char* Fl_My_Native_File_Chooser::filename(int i) const { + if ( _pathnames && i < _tpathnames ) return(_pathnames[i]); + return(""); +} + +// GET TOTAL FILENAMES CHOSEN +int Fl_My_Native_File_Chooser::count() const { + return(_tpathnames); +} + +// PRESET PATHNAME +// Value can be NULL for none. +// +void Fl_My_Native_File_Chooser::directory(const char *val) { + _directory = strfree(_directory); + _directory = strnew(val); +} + +// GET PRESET PATHNAME +// Returned value can be NULL if none set. +// +const char* Fl_My_Native_File_Chooser::directory() const { + return(_directory); +} + +// SET TITLE +// Value can be NULL if no title desired. +// +void Fl_My_Native_File_Chooser::title(const char *val) { + _title = strfree(_title); + _title = strnew(val); +} + +// GET TITLE +// Returned value can be NULL if none set. +// +const char *Fl_My_Native_File_Chooser::title() const { + return(_title); +} + +// SET FILTER +// Can be NULL if no filter needed +// +void Fl_My_Native_File_Chooser::filter(const char *val) { + _filter = strfree(_filter); + _filter = strnew(val); + + // Parse filter user specified + // IN: _filter = "C Files\t*.{cxx,h}\nText Files\t*.txt" + // OUT: _filt_names = "C Files\tText Files" + // _filt_patt[0] = "*.{cxx,h}" + // _filt_patt[1] = "*.txt" + // _filt_total = 2 + // + parse_filter(_filter); +} + +// GET FILTER +// Returned value can be NULL if none set. +// +const char *Fl_My_Native_File_Chooser::filter() const { + return(_filter); +} + +// CLEAR ALL FILTERS +// Internal use only. +// +void Fl_My_Native_File_Chooser::clear_filters() { + _filt_names = strfree(_filt_names); + for (int i=0; i<_filt_total; i++) { + _filt_patt[i] = strfree(_filt_patt[i]); + } + _filt_total = 0; +} + +// PARSE USER'S FILTER SPEC +// Parses user specified filter ('in'), +// breaks out into _filt_patt[], _filt_names, and _filt_total. +// +// Handles: +// IN: OUT:_filt_names OUT: _filt_patt +// ------------------------------------ ------------------ --------------- +// "*.{ma,mb}" "*.{ma,mb} Files" "*.{ma,mb}" +// "*.[abc]" "*.[abc] Files" "*.[abc]" +// "*.txt" "*.txt Files" "*.c" +// "C Files\t*.[ch]" "C Files" "*.[ch]" +// "C Files\t*.[ch]\nText Files\t*.cxx" "C Files" "*.[ch]" +// +// Parsing Mode: +// IN:"C Files\t*.{cxx,h}" +// ||||||| ||||||||| +// mode: nnnnnnn wwwwwwwww +// \_____/ \_______/ +// Name Wildcard +// +void Fl_My_Native_File_Chooser::parse_filter(const char *in) { + clear_filters(); + if ( ! in ) return; + int has_name = strchr(in, '\t') ? 1 : 0; + + char mode = has_name ? 'n' : 'w'; // parse mode: n=title, w=wildcard + char wildcard[1024] = ""; // parsed wildcard + char name[1024] = ""; + + // Parse filter user specified + for ( ; 1; in++ ) { + + //// DEBUG + //// printf("WORKING ON '%c': mode=<%c> name=<%s> wildcard=<%s>\n", + //// *in, mode, name, wildcard); + + switch (*in) { + // FINISHED PARSING NAME? + case '\t': + if ( mode != 'n' ) goto regchar; + mode = 'w'; + break; + + // ESCAPE NEXT CHAR + case '\\': + ++in; + goto regchar; + + // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS? + case '\r': + case '\n': + case '\0': + // TITLE + // If user didn't specify a name, make one + // + if ( name[0] == '\0' ) { + sprintf(name, "%.*s Files", (int)sizeof(name)-10, wildcard); + } + // APPEND NEW FILTER TO LIST + if ( wildcard[0] ) { + // Add to filtername list + // Tab delimit if more than one. We later break + // tab delimited string into CFArray with + // CFStringCreateArrayBySeparatingStrings() + // + if ( _filt_total ) { + _filt_names = strapp(_filt_names, "\t"); + } + _filt_names = strapp(_filt_names, name); + + // Add filter to the pattern array + _filt_patt[_filt_total++] = strnew(wildcard); + } + // RESET + wildcard[0] = name[0] = '\0'; + mode = strchr(in, '\t') ? 'n' : 'w'; + // DONE? + if ( *in == '\0' ) return; // done + else continue; // not done yet, more filters + + // Parse all other chars + default: // handle all non-special chars + regchar: // handle regular char + switch ( mode ) { + case 'n': chrcat(name, *in); continue; + case 'w': chrcat(wildcard, *in); continue; + } + break; + } + } + //NOTREACHED +} + +// SET PRESET FILE +// Value can be NULL for none. +// +void Fl_My_Native_File_Chooser::preset_file(const char* val) { + _preset_file = strfree(_preset_file); + _preset_file = strnew(val); +} + +// PRESET FILE +// Returned value can be NULL if none set. +// +const char* Fl_My_Native_File_Chooser::preset_file() const { + return(_preset_file); +} + +void Fl_My_Native_File_Chooser::filter_value(int val) { + _filt_value = val; +} + +int Fl_My_Native_File_Chooser::filter_value() const { + return(_filt_value); +} + +int Fl_My_Native_File_Chooser::filters() const { + return(_filt_total); +} + +#import +#define UNLIKELYPREFIX "___fl_very_unlikely_prefix_" + +int Fl_My_Native_File_Chooser::get_saveas_basename(void) { + + char *q = strdup( [[[(NSSavePanel*)_panel URL] path] UTF8String] ); + + if ( !(_options & SAVEAS_CONFIRM) ) + { + const char *d = [[[[(NSSavePanel*)_panel URL] path] stringByDeletingLastPathComponent] UTF8String]; + int l = (int)strlen(d) + 1; + + if (strcmp(d, "/") == 0) + l = 1; + + int lu = strlen(UNLIKELYPREFIX); + // Remove UNLIKELYPREFIX between directory and filename parts + + //memmove(q + l, q + l + lu, strlen(q + l + lu) + 1); orig from fltk //1.3.5 + + // Daniel + //fixes file picker on catalina + if (strstr(q, UNLIKELYPREFIX)) + memmove(q + l, q + l + lu, strlen(q + l + lu) + 1); + } + set_single_pathname(q); + free(q); + return 0; +} + +// SET THE TYPE OF BROWSER +void Fl_My_Native_File_Chooser::type(int val) { + _btype = val; +} + +/* Input + filter= "C files\t*.{c,h}\nText files\t*.txt\n" + patterns[0] = "*.{c,h}" + patterns[1] = "*.txt" + count = 2 + Return: + "C files (*.{c,h})\nText files (*.txt)\n" + */ +static char *prepareMacFilter(int count, const char *filter, char **patterns) { + int rank = 0, l = 0; + for (int i = 0; i < count; i++) { + l += strlen(patterns[i]) + 3; + } + const char *p = filter; + char *q; q = new char[strlen(p) + l + 1]; + const char *r, *s; + char *t; + t = q; + do { // copy to t what is in filter removing what is between \t and \n, if any + r = strchr(p, '\n'); + if (!r) r = p + strlen(p); + s = strchr(p, '\t'); + if (s && s < r) { + memcpy(q, p, s - p); + q += s - p; + if (rank < count) { sprintf(q, " (%s)", patterns[rank]); q += strlen(q); } + } + else { + memcpy(q, p, r - p); + q += r - p; + } + rank++; + *(q++) = '\n'; + if (*r) p = r + 1; else p = r; + } while(*p); + *q = 0; + return t; +} + +@interface FLopenDelegate : NSObject +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + +#endif +{ + NSPopUpButton *nspopup; + char **filter_pattern; +} +- (FLopenDelegate*)setPopup:(NSPopUpButton*)popup filter_pattern:(char**)pattern; +- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename; +- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url; +@end +@implementation FLopenDelegate +- (FLopenDelegate*)setPopup:(NSPopUpButton*)popup filter_pattern:(char**)pattern +{ + nspopup = popup; + filter_pattern = pattern; + return self; +} +- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename +{ + if ( [nspopup indexOfSelectedItem] == [nspopup numberOfItems] - 1) return YES; + BOOL isdir = NO; + [[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isdir]; + if (isdir) return YES; + if ( fl_filename_match([filename fileSystemRepresentation], filter_pattern[ [nspopup indexOfSelectedItem] ]) ) return YES; + return NO; +} +- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url +{ + return [self panel:sender shouldShowFilename:[url path]]; +} +@end + +@interface FLsaveDelegate : NSObject +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + +#endif +{ + NSSavePanel *dialog; + BOOL saveas_confirm; +} +- (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag; +- (void)changedPopup:(id)sender; +- (void)panel:(NSSavePanel*)p; +- (void)option:(BOOL)o; +@end +@implementation FLsaveDelegate +- (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag +{ + if ( !okFlag || saveas_confirm ) return filename; + // User has clicked save, and no overwrite confirmation should occur. + // To get the latter, we need to change the name we return (hence the prefix): + return [@ UNLIKELYPREFIX stringByAppendingString:filename]; +} +- (void)changedPopup:(id)sender +// runs when the save panel popup menu changes output file type +// correspondingly changes the extension of the output file name +{ + if (fl_mac_os_version < 100600) return; // because of setNameFieldStringValue and nameFieldStringValue + char *s = strdup([[(NSPopUpButton*)sender titleOfSelectedItem] UTF8String]); + if (!s) return; + char *p = strchr(s, '('); + if (!p) p = s; + p = strchr(p, '.'); + if (!p) {free(s); return;} + p++; + while (*p == ' ') p++; + if (!p || *p == '{') {free(s); return;} + char *q = p+1; + while (*q != ' ' && *q != ')' && *q != 0) q++; + *q = 0; + NSString *ns = [NSString stringWithFormat:@"%@.%@", + [[dialog performSelector:@selector(nameFieldStringValue)] stringByDeletingPathExtension], + [NSString stringWithUTF8String:p]]; + free(s); + [dialog performSelector:@selector(setNameFieldStringValue:) withObject:ns]; +} +- (void)panel:(NSSavePanel*)p +{ + dialog = p; +} +- (void) option:(BOOL)o +{ + saveas_confirm = o; +} +@end + +static NSPopUpButton *createPopupAccessory(NSSavePanel *panel, const char *filter, const char *title, int rank) +{ + NSPopUpButton *popup; + NSRect rectview = NSMakeRect(5, 5, 350, 30 ); + NSView *view = [[[NSView alloc] initWithFrame:rectview] autorelease]; + NSRect rectbox = NSMakeRect(0, 3, 140, 20 ); + NSBox *box = [[[NSBox alloc] initWithFrame:rectbox] autorelease]; + NSRect rectpop = NSMakeRect(105, 0, 246, 30 ); + popup = [[[NSPopUpButton alloc ] initWithFrame:rectpop pullsDown:NO] autorelease]; + [view addSubview:box]; + [view addSubview:popup]; + [box setBorderType:NSNoBorder]; + NSString *nstitle = [[NSString alloc] initWithUTF8String:title]; + [box setTitle:nstitle]; + [nstitle release]; + NSFont *font = [NSFont controlContentFontOfSize:NSRegularControlSize]; + [box setTitleFont:font]; + [box sizeToFit]; + // horizontally move box to fit the locale-dependent width of its title + NSRect r=[box frame]; + NSPoint o = r.origin; + o.x = rectpop.origin.x - r.size.width + 15; + [box setFrameOrigin:o]; + CFStringRef tab = CFSTR("\n"); + CFStringRef tmp_cfs; + tmp_cfs = CFStringCreateWithCString(NULL, filter, kCFStringEncodingUTF8); + CFArrayRef array = CFStringCreateArrayBySeparatingStrings(NULL, tmp_cfs, tab); + CFRelease(tmp_cfs); + CFRelease(tab); + [popup addItemsWithTitles:(NSArray*)array]; + NSMenuItem *item = [popup itemWithTitle:@""]; + if (item) [popup removeItemWithTitle:@""]; + CFRelease(array); + [popup selectItemAtIndex:rank]; + [panel setAccessoryView:view]; + return popup; +} + +int Fl_My_Native_File_Chooser::runmodal() +{ + NSString *dir = nil; + NSString *fname = nil; + NSString *preset = nil; + NSInteger retval; + if (_preset_file) { + preset = [[NSString alloc] initWithUTF8String:_preset_file]; + if (strchr(_preset_file, '/') != NULL) { + dir = [[NSString alloc] initWithString:[preset stringByDeletingLastPathComponent]]; + } + fname = [preset lastPathComponent]; + } + if (_directory && !dir) dir = [[NSString alloc] initWithUTF8String:_directory]; + if (fl_mac_os_version >= 100600) { + if (dir) [(NSSavePanel*)_panel performSelector:@selector(setDirectoryURL:) withObject:[NSURL fileURLWithPath:dir]]; + if (fname) [(NSSavePanel*)_panel performSelector:@selector(setNameFieldStringValue:) withObject:fname]; + retval = [(NSSavePanel*)_panel runModal]; + } + else { + retval = [(id)_panel runModalForDirectory:dir file:fname]; + } + [dir release]; + [preset release]; + return (retval == NSFileHandlingPanelOKButton ? 1 : 0); +} + +// POST BROWSER +// Internal use only. +// Assumes '_opts' has been initialized. +// +// Returns: +// 0 - user picked a file +// 1 - user cancelled +// -1 - failed; errmsg() has reason +// +int Fl_My_Native_File_Chooser::post() { + // INITIALIZE BROWSER + if ( _filt_total == 0 ) { // Make sure they match + _filt_value = 0; // TBD: move to someplace more logical? + } + fl_open_display(); + NSAutoreleasePool *localPool; + localPool = [[NSAutoreleasePool alloc] init]; + switch (_btype) { + case BROWSE_FILE: + case BROWSE_MULTI_FILE: + case BROWSE_DIRECTORY: + case BROWSE_MULTI_DIRECTORY: + _panel = [NSOpenPanel openPanel]; + break; + case BROWSE_SAVE_DIRECTORY: + case BROWSE_SAVE_FILE: + _panel = [NSSavePanel savePanel]; + break; + } + BOOL is_open_panel = [(NSSavePanel*)_panel isKindOfClass:[NSOpenPanel class]]; + if (_title) { + SEL title_or_message = (is_open_panel && fl_mac_os_version >= 101200) ? + @selector(setMessage:) : @selector(setTitle:); + [(NSSavePanel*)_panel performSelector:title_or_message withObject:[NSString stringWithUTF8String:_title]]; + } + switch (_btype) { + case BROWSE_MULTI_FILE: + [(NSOpenPanel*)_panel setAllowsMultipleSelection:YES]; + break; + case BROWSE_MULTI_DIRECTORY: + [(NSOpenPanel*)_panel setAllowsMultipleSelection:YES]; + /* FALLTHROUGH */ + case BROWSE_DIRECTORY: + [(NSOpenPanel*)_panel setCanChooseDirectories:YES]; + [(NSOpenPanel*)_panel setCanChooseFiles:NO]; // Daniel + break; + case BROWSE_SAVE_DIRECTORY: + [(NSSavePanel*)_panel setCanCreateDirectories:YES]; + break; + } + + // SHOW THE DIALOG + NSWindow *key = [NSApp keyWindow]; + NSPopUpButton *popup = nil; + if ( is_open_panel ) { + if (_filt_total) { + char *t = prepareMacFilter(_filt_total, _filter, _filt_patt); + popup = createPopupAccessory((NSSavePanel*)_panel, t, Fl_File_Chooser::show_label, 0); + delete[] t; + [[popup menu] addItem:[NSMenuItem separatorItem]]; + [popup addItemWithTitle:[NSString stringWithUTF8String:Fl_File_Chooser::all_files_label]]; + [popup setAction:@selector(validateVisibleColumns)]; + [popup setTarget:(NSObject*)_panel]; + FLopenDelegate *openDelegate = [[[FLopenDelegate alloc] init] autorelease]; + [openDelegate setPopup:popup filter_pattern:_filt_patt]; + [(NSOpenPanel*)_panel setDelegate:openDelegate]; + } + } + else { + FLsaveDelegate *saveDelegate = [[[FLsaveDelegate alloc] init] autorelease]; + [(NSSavePanel*)_panel setAllowsOtherFileTypes:YES]; + [(NSSavePanel*)_panel setDelegate:saveDelegate]; + [saveDelegate option:(_options & SAVEAS_CONFIRM)]; + if (_filt_total) { + if (_filt_value >= _filt_total) _filt_value = _filt_total - 1; + char *t = prepareMacFilter(_filt_total, _filter, _filt_patt); + popup = createPopupAccessory((NSSavePanel*)_panel, t, [[(NSSavePanel*)_panel nameFieldLabel] UTF8String], _filt_value); + delete[] t; + if (_options & USE_FILTER_EXT) { + [popup setAction:@selector(changedPopup:)]; + [popup setTarget:saveDelegate]; + [saveDelegate panel:(NSSavePanel*)_panel]; + } + [(NSSavePanel*)_panel setCanSelectHiddenExtension:YES]; + } + } + int retval = runmodal(); + if (_filt_total) { + _filt_value = (int)[popup indexOfSelectedItem]; + } + if ( retval == 1 ) { + if (is_open_panel) { + clear_pathnames(); + NSArray *array = [(NSOpenPanel*)_panel URLs]; + _tpathnames = (int)[array count]; + _pathnames = new char*[_tpathnames]; + for(int i = 0; i < _tpathnames; i++) { + _pathnames[i] = strnew([[(NSURL*)[array objectAtIndex:i] path] UTF8String]); + } + } + else get_saveas_basename(); + } + [key makeKeyWindow]; + [localPool release]; + return (retval == 1 ? 0 : 1); +} + +#endif // __APPLE__ + +// +// End of "$Id$". +// diff --git a/src/FLTK/Fl_My_Native_File_Chooser_WIN32.cxx b/src/FLTK/Fl_My_Native_File_Chooser_WIN32.cxx new file mode 100644 index 0000000..57ccedb --- /dev/null +++ b/src/FLTK/Fl_My_Native_File_Chooser_WIN32.cxx @@ -0,0 +1,1092 @@ +// "$Id$" +// +// FLTK native OS file chooser widget +// +// Copyright 1998-2014 by Bill Spitzak and others. +// Copyright 2004 Greg Ercolano. +// API changes + filter improvements by Nathan Vander Wilt 2005 +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// + +// Any application to multi-folder implementation: +// http://www.codeproject.com/dialog/selectfolder.asp +// + +#ifndef FL_DOXYGEN // PREVENT DOXYGEN'S USE OF THIS FILE +#include + +#if FLTK_ABI_VERSION < 10304 +#define _ofn_ptr (&_ofn) +#define _binf_ptr (&_binf) +#endif + +#include // malloc +#include // sprintf +#include + +#include "Fl_My_Native_File_Chooser_common.cxx" // strnew/strfree/strapp/chrcat + +#define FNFC_MAX_PATH 32768 // XXX: MAX_PATH under win32 is 260, too small for modern use + +#include "FL/Fl_My_Native_File_Chooser.H" +static LPCWSTR utf8towchar(const char *in); +static char *wchartoutf8(LPCWSTR in); + +#include // for fl_open_display + +#define LCURLY_CHR '{' +#define RCURLY_CHR '}' +#define LBRACKET_CHR '[' +#define RBRACKET_CHR ']' + +void fl_open_display(); + +// STATIC: PRINT WINDOWS 'DOUBLE NULL' STRING (DEBUG) +#ifdef DEBUG +#include +static void dnullprint(char *wp) +{ + if (!wp) { + return; + } + for (int t = 0; true; t++) { + if (wp[t] == '\0' && wp[t + 1] == '\0') { + printf("\\0\\0"); + fflush(stdout); + return; + } + else if (wp[t] == '\0') { + printf("\\0"); + } + else { + printf("%c", wp[t]); + } + } +} +#endif + +// RETURN LENGTH OF DOUBLENULL STRING +// Includes single nulls in count, excludes trailing doublenull. +// +// 1234 567 +// |||/\||| +// IN: "one\0two\0\0" +// OUT: 7 +// +static int dnulllen(const char *wp) +{ + int len = 0; + while (!(*(wp + 0) == 0 && *(wp + 1) == 0)) { + ++wp; + ++len; + } + return (len); +} + +// STATIC: Append a string to another, leaving terminated with DOUBLE NULL. +// Automatically handles extending length of string. +// wp can be NULL (a new wp will be allocated and initialized). +// string must be NULL terminated. +// The pointer wp may be modified on return. +// +static void dnullcat(char *&wp, const char *string, int n = -1) +{ + // DEBUG printf("DEBUG: dnullcat IN: <"); dnullprint(wp); printf(">\n"); + size_t inlen = (n < 0) ? strlen(string) : n; + if (!wp) { + wp = new char[inlen + 4]; + *(wp + 0) = '\0'; + *(wp + 1) = '\0'; + } + else { + int wplen = dnulllen(wp); + // Make copy of wp into larger buffer + char *tmp = new char[wplen + inlen + 4]; + memcpy(tmp, wp, wplen + 2); // copy of wp plus doublenull + delete[] wp; // delete old wp + wp = tmp; // use new copy + // DEBUG printf("DEBUG: dnullcat COPY: <"); dnullprint(wp); printf("> (wplen=%d)\n", wplen); + } + + // Find end of double null string + // *wp2 is left pointing at second null. + // + char *wp2 = wp; + if (*(wp2 + 0) != '\0' && *(wp2 + 1) != '\0') { + for (; 1; wp2++) { + if (*(wp2 + 0) == '\0' && *(wp2 + 1) == '\0') { + wp2++; + break; + } + } + } + + if (n == -1) { + n = (int)strlen(string); + } + strncpy(wp2, string, n); + + // Leave string double-null terminated + *(wp2 + n + 0) = '\0'; + *(wp2 + n + 1) = '\0'; + // DEBUG printf("DEBUG: dnullcat OUT: <"); dnullprint(wp); printf(">\n\n"); +} + +// CTOR +Fl_My_Native_File_Chooser::Fl_My_Native_File_Chooser(int val) +{ + _btype = val; + _options = NO_OPTIONS; +#if FLTK_ABI_VERSION >= 10304 + _ofn_ptr = new OPENFILENAMEW; + _binf_ptr = new BROWSEINFOW; + _wpattern = 0; +#endif + memset((void *)_ofn_ptr, 0, sizeof(OPENFILENAMEW)); + _ofn_ptr->lStructSize = sizeof(OPENFILENAMEW); + _ofn_ptr->hwndOwner = NULL; + memset((void *)_binf_ptr, 0, sizeof(BROWSEINFOW)); + _pathnames = NULL; + _tpathnames = 0; + _directory = NULL; + _title = NULL; + _filter = NULL; + _parsedfilt = NULL; + _nfilters = 0; + _preset_file = NULL; + _errmsg = NULL; +} + +// DTOR +Fl_My_Native_File_Chooser::~Fl_My_Native_File_Chooser() +{ + //_pathnames // managed by clear_pathnames() + //_tpathnames // managed by clear_pathnames() + _directory = strfree(_directory); + _title = strfree(_title); + _filter = strfree(_filter); + //_parsedfilt // managed by clear_filters() + //_nfilters // managed by clear_filters() + _preset_file = strfree(_preset_file); + _errmsg = strfree(_errmsg); + clear_filters(); + clear_pathnames(); + ClearOFN(); + ClearBINF(); +#if FLTK_ABI_VERSION >= 10304 + delete _binf_ptr; + delete _ofn_ptr; + if (_wpattern) { + delete[] _wpattern; + } +#endif +} + +// SET TYPE OF BROWSER +void Fl_My_Native_File_Chooser::type(int val) +{ + _btype = val; +} + +// GET TYPE OF BROWSER +int Fl_My_Native_File_Chooser::type() const +{ + return (_btype); +} + +// SET OPTIONS +void Fl_My_Native_File_Chooser::options(int val) +{ + _options = val; +} + +// GET OPTIONS +int Fl_My_Native_File_Chooser::options() const +{ + return (_options); +} + +// PRIVATE: SET ERROR MESSAGE +void Fl_My_Native_File_Chooser::errmsg(const char *val) +{ + _errmsg = strfree(_errmsg); + _errmsg = strnew(val); +} + +// FREE PATHNAMES ARRAY, IF IT HAS ANY CONTENTS +void Fl_My_Native_File_Chooser::clear_pathnames() +{ + if (_pathnames) { + while (--_tpathnames >= 0) { + _pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]); + } + delete[] _pathnames; + _pathnames = NULL; + } + _tpathnames = 0; +} + +// SET A SINGLE PATHNAME +void Fl_My_Native_File_Chooser::set_single_pathname(const char *s) +{ + clear_pathnames(); + _pathnames = new char *[1]; + _pathnames[0] = strnew(s); + _tpathnames = 1; +} + +// ADD PATHNAME TO EXISTING ARRAY +void Fl_My_Native_File_Chooser::add_pathname(const char *s) +{ + if (!_pathnames) { + // Create first element in array + ++_tpathnames; + _pathnames = new char *[_tpathnames]; + } + else { + // Grow array by 1 + char **tmp = new char *[_tpathnames + 1]; // create new buffer + memcpy((void *)tmp, (void *)_pathnames, + sizeof(char *) * _tpathnames); // copy old + delete[] _pathnames; // delete old + _pathnames = tmp; // use new + ++_tpathnames; + } + _pathnames[_tpathnames - 1] = strnew(s); +} + +// FREE A PIDL (Pointer to IDentity List) +static void FreePIDL(LPITEMIDLIST pidl) +{ + IMalloc *imalloc = NULL; + if (SUCCEEDED(SHGetMalloc(&imalloc))) { + imalloc->Free(pidl); + imalloc->Release(); + imalloc = NULL; + } +} + +// CLEAR MICROSOFT OFN (OPEN FILE NAME) CLASS +void Fl_My_Native_File_Chooser::ClearOFN() +{ + // Free any previously allocated lpstrFile before zeroing out _ofn_ptr + if (_ofn_ptr->lpstrFile) { + delete[] _ofn_ptr->lpstrFile; + _ofn_ptr->lpstrFile = NULL; + } + if (_ofn_ptr->lpstrInitialDir) { + delete[] (TCHAR *)_ofn_ptr->lpstrInitialDir; // msvc6 compilation fix + _ofn_ptr->lpstrInitialDir = NULL; + } + _ofn_ptr->lpstrFilter = NULL; // (deleted elsewhere) + int temp = _ofn_ptr->nFilterIndex; // keep the filter_value + memset((void *)_ofn_ptr, 0, sizeof(OPENFILENAMEW)); + _ofn_ptr->lStructSize = sizeof(OPENFILENAMEW); + _ofn_ptr->nFilterIndex = temp; +} + +// CLEAR MICROSOFT BINF (BROWSER INFO) CLASS +void Fl_My_Native_File_Chooser::ClearBINF() +{ + if (_binf_ptr->pidlRoot) { + FreePIDL((ITEMIDLIST *)_binf_ptr->pidlRoot); + _binf_ptr->pidlRoot = NULL; + } + memset((void *)_binf_ptr, 0, sizeof(BROWSEINFOW)); +} + +// CONVERT WINDOWS BACKSLASHES TO UNIX FRONTSLASHES +void Fl_My_Native_File_Chooser::Win2Unix(char *s) +{ + for (; *s; s++) + if (*s == '\\') { + *s = '/'; + } +} + +// CONVERT UNIX FRONTSLASHES TO WINDOWS BACKSLASHES +void Fl_My_Native_File_Chooser::Unix2Win(char *s) +{ + for (; *s; s++) { + if (*s == '/') { + *s = '\\'; + } + } +} + +// SAVE THE CURRENT WORKING DIRECTORY +// Returns a malloc()ed copy of the cwd that can +// later be freed with RestoreCWD(). May return 0 on error. +// +static char *SaveCWD() +{ + char *thecwd = 0; + DWORD thecwdsz = GetCurrentDirectory(0, 0); + if (thecwdsz > 0) { + thecwd = (char *)malloc(thecwdsz); + if (GetCurrentDirectory(thecwdsz, thecwd) == 0) { + free(thecwd); + thecwd = 0; + } + } + return thecwd; +} + +// RESTORES THE CWD SAVED BY SaveCWD(), FREES STRING +// Always returns NULL (string was freed). +// +static void RestoreCWD(char *thecwd) +{ + if (!thecwd) { + return; + } + SetCurrentDirectory(thecwd); + free(thecwd); +} + +// SHOW FILE BROWSER +int Fl_My_Native_File_Chooser::showfile() +{ + ClearOFN(); + clear_pathnames(); + size_t fsize = FNFC_MAX_PATH; + _ofn_ptr->Flags |= OFN_NOVALIDATE; // prevent disabling of front slashes + _ofn_ptr->Flags |= OFN_HIDEREADONLY; // hide goofy readonly flag + // USE NEW BROWSER + _ofn_ptr->Flags |= OFN_EXPLORER; // use newer explorer windows + _ofn_ptr->Flags |= OFN_ENABLESIZING; // allow window to be resized (hey, why not?) + _ofn_ptr->Flags |= OFN_NOCHANGEDIR; // XXX: docs say ineffective on XP/2K/NT, but set it anyway.. + + switch (_btype) { + case BROWSE_DIRECTORY: + case BROWSE_MULTI_DIRECTORY: + case BROWSE_SAVE_DIRECTORY: + abort(); // never happens: handled by showdir() + case BROWSE_FILE: + break; + case BROWSE_MULTI_FILE: + _ofn_ptr->Flags |= OFN_ALLOWMULTISELECT; + break; + case BROWSE_SAVE_FILE: + if (options() & SAVEAS_CONFIRM && type() == BROWSE_SAVE_FILE) { + _ofn_ptr->Flags |= OFN_OVERWRITEPROMPT; + } + break; + } + // SPACE FOR RETURNED FILENAME + _ofn_ptr->lpstrFile = new WCHAR[fsize]; + _ofn_ptr->nMaxFile = (DWORD)fsize - 1; + _ofn_ptr->lpstrFile[0] = 0; + _ofn_ptr->lpstrFile[1] = 0; // dnull + // PARENT WINDOW + _ofn_ptr->hwndOwner = GetForegroundWindow(); + // DIALOG TITLE + if (_title) { + static WCHAR wtitle[200]; + wcsncpy(wtitle, utf8towchar(_title), 200); + wtitle[200 - 1] = 0; + _ofn_ptr->lpstrTitle = wtitle; + } + else { + _ofn_ptr->lpstrTitle = NULL; + } + // FILTER + if (_parsedfilt != NULL) { // to convert a null-containing char string into a widechar string +#if FLTK_ABI_VERSION >= 10304 + // NEW + if (!_wpattern) { + _wpattern = new WCHAR[FNFC_MAX_PATH]; + } +#else + // OLD + static WCHAR _wpattern[FNFC_MAX_PATH]; // yuck -- replace with managed class member +#endif + const char *p = _parsedfilt; + while (*(p + strlen(p) + 1) != 0) + p += strlen(p) + 1; + p += strlen(p) + 2; + MultiByteToWideChar(CP_UTF8, 0, _parsedfilt, (int)(p - _parsedfilt), _wpattern, FNFC_MAX_PATH); + _ofn_ptr->lpstrFilter = _wpattern; + } + else { + _ofn_ptr->lpstrFilter = NULL; + } + // PRESET FILE + // If set, supercedes _directory. See KB Q86920 for details + // XXX: this doesn't preselect the item in the listview.. why? + // + if (_preset_file) { + size_t len = strlen(_preset_file); + if (len >= _ofn_ptr->nMaxFile) { + char msg[80]; + sprintf(msg, "preset_file() filename is too long: %ld is >=%ld", (long)len, (long)fsize); + return (-1); + } + wcscpy(_ofn_ptr->lpstrFile, utf8towchar(_preset_file)); + // Unix2Win(_ofn_ptr->lpstrFile); + len = wcslen(_ofn_ptr->lpstrFile); + _ofn_ptr->lpstrFile[len + 0] = 0; // multiselect needs dnull + _ofn_ptr->lpstrFile[len + 1] = 0; + } + if (_directory) { + // PRESET DIR + // XXX: See KB Q86920 for doc bug: + // http://support.microsoft.com/default.aspx?scid=kb;en-us;86920 + // + _ofn_ptr->lpstrInitialDir = new WCHAR[FNFC_MAX_PATH]; + wcscpy((WCHAR *)_ofn_ptr->lpstrInitialDir, utf8towchar(_directory)); + // Unix2Win((char*)_ofn_ptr->lpstrInitialDir); + } + // SAVE THE CURRENT DIRECTORY + // See above warning (XXX) for OFN_NOCHANGEDIR + // + char *save_cwd = SaveCWD(); // must be freed with RestoreCWD() + // OPEN THE DIALOG WINDOW + int err; + if (_btype == BROWSE_SAVE_FILE) { + err = GetSaveFileNameW(_ofn_ptr); + } + else { + err = GetOpenFileNameW(_ofn_ptr); + } + // GET EXTENDED ERROR + int exterr = CommDlgExtendedError(); + // RESTORE CURRENT DIRECTORY + RestoreCWD(save_cwd); + save_cwd = 0; // also frees save_cwd + // ERROR OR CANCEL? + if (err == 0) { + if (exterr == 0) { + return (1); // user hit cancel + } + // Otherwise, an error occurred.. + char msg[80]; + sprintf(msg, "CommDlgExtendedError() code=%d", err); + errmsg(msg); + return (-1); + } + // PREPARE PATHNAMES FOR RETURN + switch (_btype) { + case BROWSE_FILE: + case BROWSE_SAVE_FILE: + set_single_pathname(wchartoutf8(_ofn_ptr->lpstrFile)); + // Win2Unix(_pathnames[_tpathnames-1]); + break; + case BROWSE_MULTI_FILE: { + // EXTRACT MULTIPLE FILENAMES + const WCHAR *dirname = _ofn_ptr->lpstrFile; + size_t dirlen = wcslen(dirname); + if (dirlen > 0) { + // WALK STRING SEARCHING FOR 'DOUBLE-NULL' + // eg. "/dir/name\0foo1\0foo2\0foo3\0\0" + // + char pathname[FNFC_MAX_PATH]; + for (const WCHAR *s = dirname + dirlen + 1; *s; s += (wcslen(s) + 1)) { + strcpy(pathname, wchartoutf8(dirname)); + strcat(pathname, "\\"); + strcat(pathname, wchartoutf8(s)); + add_pathname(pathname); + } + } + // XXX + // Work around problem where pasted forward-slash pathname + // into the file browser causes new "Explorer" interface + // not to grok forward slashes, passing back as a 'filename'..! + // + if (_tpathnames == 0) { + add_pathname(wchartoutf8(dirname)); + // Win2Unix(_pathnames[_tpathnames-1]); + } + break; + } + case BROWSE_DIRECTORY: + case BROWSE_MULTI_DIRECTORY: + case BROWSE_SAVE_DIRECTORY: + abort(); // never happens: handled by showdir() + } + return (0); +} + +// Used by SHBrowseForFolder(), sets initial selected dir. +// Ref: Usenet: microsoft.public.vc.mfc, Dec 8 2000, 1:38p David Lowndes +// Subject: How to specify to select an initial folder .." +// +static int CALLBACK Dir_CB(HWND win, UINT msg, LPARAM param, LPARAM data) +{ + switch (msg) { + case BFFM_INITIALIZED: + if (data) { + ::SendMessageW(win, BFFM_SETSELECTIONW, TRUE, data); + } + break; + case BFFM_SELCHANGED: + TCHAR path[FNFC_MAX_PATH]; + if (SHGetPathFromIDList((ITEMIDLIST *)param, path)) { + ::SendMessage(win, BFFM_ENABLEOK, 0, 1); + } + else { + // disable ok button if not a path + ::SendMessage(win, BFFM_ENABLEOK, 0, 0); + } + break; + case BFFM_VALIDATEFAILED: + // we could pop up an annoying message here. + // also needs set ulFlags |= BIF_VALIDATE + break; + default: + break; + } + return (0); +} + +// SHOW DIRECTORY BROWSER +int Fl_My_Native_File_Chooser::showdir() +{ + // initialize OLE only once + fl_open_display(); // init needed by BIF_USENEWUI + ClearBINF(); + clear_pathnames(); + // PARENT WINDOW + _binf_ptr->hwndOwner = GetForegroundWindow(); + // DIALOG TITLE + //_binf_ptr->lpszTitle = _title ? _title : NULL; + if (_title) { + static WCHAR wtitle[256]; + wcsncpy(wtitle, utf8towchar(_title), 256); + wtitle[255] = 0; + _binf_ptr->lpszTitle = wtitle; + } + else { + _binf_ptr->lpszTitle = NULL; + } + + // FLAGS + _binf_ptr->ulFlags = 0; // initialize + + // TBD: make sure matches to runtime system, if need be. + //(what if _WIN32_IE doesn't match system? does the program not run?) + // + // TBD: match all 3 types of directories + // + // NOTE: *Don't* use BIF_SHAREABLE. It /disables/ mapped network shares + // from being visible in BROWSE_DIRECTORY mode. Walter Garm's comments: + // + // --- Garms, Walter (GE EntSol, Security) wrote: + // With your help I was able to solve the problem of the network drives. + // For Version 6.0, at least, the BIF_SHAREABLE flag seems to have the + // opposite sense: With BIF_SHAREABLE not set I see the mapped network + // drives, and with BIF_SHAREABLE set I do not. + // --- + +#if defined(BIF_NONEWFOLDERBUTTON) // Version 6.0 + if (_btype == BROWSE_DIRECTORY) { + _binf_ptr->ulFlags |= BIF_NONEWFOLDERBUTTON; + } + _binf_ptr->ulFlags |= BIF_USENEWUI | BIF_RETURNONLYFSDIRS; +#elif defined(BIF_USENEWUI) // Version 5.0 + if (_btype == BROWSE_DIRECTORY) { + _binf_ptr->ulFlags |= BIF_EDITBOX; + } + else if (_btype == BROWSE_SAVE_DIRECTORY) { + _binf_ptr->ulFlags |= BIF_USENEWUI; + } + _binf_ptr->ulFlags |= BIF_RETURNONLYFSDIRS; +#elif defined(BIF_EDITBOX) // Version 4.71 + _binf_ptr->ulFlags |= BIF_RETURNONLYFSDIRS | BIF_EDITBOX; +#else // Version Old + _binf_ptr->ulFlags |= BIF_RETURNONLYFSDIRS; +#endif + + // BUFFER + // char displayname[FNFC_MAX_PATH]; + WCHAR displayname[FNFC_MAX_PATH]; + _binf_ptr->pszDisplayName = displayname; + + // PRESET DIR + WCHAR presetname[FNFC_MAX_PATH]; + if (_directory) { + // Unix2Win(presetname); + wcsncpy(presetname, utf8towchar(_directory), FNFC_MAX_PATH); + presetname[FNFC_MAX_PATH - 1] = 0; + _binf_ptr->lParam = (LPARAM)presetname; + } + else { + _binf_ptr->lParam = 0; + } + _binf_ptr->lpfn = Dir_CB; + // OPEN BROWSER + LPITEMIDLIST pidl = SHBrowseForFolderW(_binf_ptr); + // CANCEL? + if (pidl == NULL) { + return (1); + } + + // GET THE PATHNAME(S) THE USER SELECTED + // TBD: expand NetHood shortcuts from this PIDL?? + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shbrowseforfolder.asp + + WCHAR path[FNFC_MAX_PATH]; + if (SHGetPathFromIDListW(pidl, path)) { + // Win2Unix(path); + // add_pathname(path); + add_pathname(wchartoutf8(path)); + } + FreePIDL(pidl); + if (!wcslen(path)) { + return (1); // don't return empty pathnames + } + return (0); +} + +// RETURNS: +// 0 - user picked a file +// 1 - user cancelled +// -1 - failed; errmsg() has reason +// +int Fl_My_Native_File_Chooser::show() +{ + int retval; + if (_btype == BROWSE_DIRECTORY || _btype == BROWSE_MULTI_DIRECTORY || _btype == BROWSE_SAVE_DIRECTORY) { + retval = showdir(); + } + else { + retval = showfile(); + } + // restore the correct state of mouse buttons and keyboard modifier keys (STR #3221) + HWND h = GetForegroundWindow(); + if (h) { + WNDPROC windproc = (WNDPROC)GetWindowLongPtrW(h, GWLP_WNDPROC); + CallWindowProc(windproc, h, WM_ACTIVATEAPP, 1, 0); + } + return retval; +} + +// RETURN ERROR MESSAGE +const char *Fl_My_Native_File_Chooser::errmsg() const +{ + return (_errmsg ? _errmsg : "No error"); +} + +// GET FILENAME +const char *Fl_My_Native_File_Chooser::filename() const +{ + if (_pathnames && _tpathnames > 0) { + return (_pathnames[0]); + } + return (""); +} + +// GET FILENAME FROM LIST OF FILENAMES +const char *Fl_My_Native_File_Chooser::filename(int i) const +{ + if (_pathnames && i < _tpathnames) { + return (_pathnames[i]); + } + return (""); +} + +// GET TOTAL FILENAMES CHOSEN +int Fl_My_Native_File_Chooser::count() const +{ + return (_tpathnames); +} + +// PRESET PATHNAME +// Can be NULL if no preset is desired. +// +void Fl_My_Native_File_Chooser::directory(const char *val) +{ + _directory = strfree(_directory); + _directory = strnew(val); +} + +// GET PRESET PATHNAME +// Can return NULL if none set. +// +const char *Fl_My_Native_File_Chooser::directory() const +{ + return (_directory); +} + +// SET TITLE +// Can be NULL if no title desired. +// +void Fl_My_Native_File_Chooser::title(const char *val) +{ + _title = strfree(_title); + _title = strnew(val); +} + +// GET TITLE +// Can return NULL if none set. +// +const char *Fl_My_Native_File_Chooser::title() const +{ + return (_title); +} + +// SET FILTER +// Can be NULL if no filter needed +// +void Fl_My_Native_File_Chooser::filter(const char *val) +{ + _filter = strfree(_filter); + clear_filters(); + if (val) { + _filter = strnew(val); + parse_filter(_filter); + } + add_filter("All Files", "*.*"); // always include 'all files' option + +#ifdef DEBUG + dnullprint(_parsedfilt); +#endif /*DEBUG*/ +} + +// GET FILTER +// Can return NULL if none set. +// +const char *Fl_My_Native_File_Chooser::filter() const +{ + return (_filter); +} + +// CLEAR FILTERS +void Fl_My_Native_File_Chooser::clear_filters() +{ + _nfilters = 0; + _parsedfilt = strfree(_parsedfilt); +} + +// ADD A FILTER +void Fl_My_Native_File_Chooser::add_filter(const char *name_in, // name of filter (optional: can be null) + const char *winfilter) +{ // windows style filter (eg. "*.cxx;*.h") + // No name? Make one.. + char name[1024]; + if (!name_in || name_in[0] == '\0') { + sprintf(name, "%.*s Files", int(sizeof(name) - 10), winfilter); + } + else { + if ((strlen(name_in) + strlen(winfilter) + 3) < sizeof(name)) { + sprintf(name, "%s (%s)", name_in, winfilter); + } + else { + sprintf(name, "%.*s", int(sizeof(name)), name_in); + } + } + dnullcat(_parsedfilt, name); + dnullcat(_parsedfilt, winfilter); + _nfilters++; + // DEBUG printf("DEBUG: ADD FILTER name=<%s> winfilter=<%s>\n", name, winfilter); +} + +// RETURN HOW MANY DIFFERENT FILTERS WERE SPECIFIED +// In: "foo.[CH]" or "foo.{C,H}" +// Out: 2 +// +static int count_filters(const char *filter) +{ + int count = 0; + char mode = 0; + const char *in = filter; + while (*in) { + switch (*in) { + case '\\': // escape next character + ++in; + if (*in == 0) { + continue; // skip escape. EOL? done + } + ++in; // skip escaped char + continue; + case LCURLY_CHR: // start "{aaa,bbb}" + mode = *in; // set mode, parse over curly + ++count; // at least +1 wildcard + break; + case RCURLY_CHR: // end "{aaa,bbb}" + if (mode == LCURLY_CHR) { // disable curly mode (if on) + mode = 0; + } + break; + case LBRACKET_CHR: // start "[xyz]" + mode = *in; // set mode, parse over bracket + break; + case RBRACKET_CHR: // end "[xyz]" + if (mode == LBRACKET_CHR) { // disable bracket mode (if on) + mode = 0; + } + break; + default: // any other char + switch (mode) { // handle {} or [] modes + case LCURLY_CHR: // handle "{aaa,bbb}" + if (*in == ',' || *in == '|') // ',' and '|' adds filters + ++count; + break; + case LBRACKET_CHR: // handle "[xyz]" + ++count; // all chars in []'s add new filter + break; + } + break; + } + ++in; // parse past char + } + return count > 0 ? count : 1; // return at least 1 +} + +// CONVERT FLTK STYLE PATTERN MATCHES TO WINDOWS 'DOUBLENULL' PATTERN +// Returns with the parsed double-null result in '_parsedfilt'. +// +// Handles: +// IN OUT +// ----------- ----------------------------- +// *.{ma,mb} "*.{ma,mb} Files\0*.ma;*.mb\0\0" +// *.[abc] "*.[abc] Files\0*.a;*.b;*.c\0\0" +// *.txt "*.txt Files\0*.txt\0\0" +// C Files\t*.[ch] "C Files\0*.c;*.h\0\0" +// +// Example: +// IN: "*.{ma,mb}" +// OUT: "*.ma;*.mb Files\0*.ma;*.mb\0All Files\0*.*\0\0" +// --------------- --------- --------- --- +// | | | | +// Title Wildcards Title Wildcards +// +// Parsing Mode: +// IN:"C Files\t*.{cxx,h}" +// ||||||| ||||||||| +// mode: nnnnnnn ww{{{{{{{ +// \_____/ \_______/ +// Name Wildcard +// +void Fl_My_Native_File_Chooser::parse_filter(const char *in) +{ + clear_filters(); + if (!in || in[0] == '\0') { + return; + } + + int has_name = strchr(in, '\t') ? 1 : 0; + char mode = has_name ? 'n' : 'w'; // parse mode: n=name, w=wildcard + + // whatever input string is, our output won't be much longer in length.. + // use double length just for safety. + size_t slen = strlen(in); + char *wildprefix = new char[(slen + 1) * 2]; + wildprefix[0] = 0; + char *comp = new char[(slen + 1) * 2]; + comp[0] = 0; + char *name = new char[(slen + 1) * 2]; + name[0] = 0; + + // Init + int nwildcards = 0; + int maxfilters = count_filters(in) + 1; // count wildcard seps + char **wildcards = new char *[maxfilters]; // parsed wildcards (can be several) + int t; + for (t = 0; t < maxfilters; t++) { + wildcards[t] = new char[slen + 1]; + wildcards[t][0] = '\0'; + } + + // Parse + for (; 1; in++) { + //// DEBUG + //// printf("WORKING ON '%c': mode=<%c> name=<%s> wildprefix=<%s> nwildcards=%d wildcards[n]=<%s>\n", + //// *in, mode, name, wildprefix, nwildcards, wildcards[nwildcards]); + + switch (*in) { + case ',': + case '|': + if (mode == LCURLY_CHR) { + // create new wildcard, copy in prefix + strcat(wildcards[nwildcards++], wildprefix); + continue; + } + else { + goto regchar; + } + continue; + + // FINISHED PARSING A NAME? + case '\t': + if (mode != 'n') { + goto regchar; + } + // finish parsing name? switch to wildcard mode + mode = 'w'; + break; + + // ESCAPE NEXT CHAR + case '\\': + ++in; + goto regchar; + + // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS? + case '\r': + case '\n': + case '\0': { + if (mode == 'w') { // finished parsing wildcard? + if (nwildcards == 0) { + strcpy(wildcards[nwildcards++], wildprefix); + } + // Append wildcards in Microsoft's "*.one;*.two" format + comp[0] = 0; + for (t = 0; t < nwildcards; t++) { + if (t != 0) { + strcat(comp, ";"); + } + strcat(comp, wildcards[t]); + } + // Add if not empty + if (comp[0]) { + add_filter(name, comp); + } + } + // RESET + for (t = 0; t < maxfilters; t++) { + wildcards[t][0] = '\0'; + } + nwildcards = 0; + wildprefix[0] = name[0] = '\0'; + mode = strchr(in, '\t') ? 'n' : 'w'; + // DONE? + if (*in == '\0') { // done + // Free everything + delete[] wildprefix; + delete[] comp; + delete[] name; + for (t = 0; t < maxfilters; t++) + delete[] wildcards[t]; + delete[] wildcards; + return; + } + continue; // not done yet, more filters + } + + // STARTING A WILDCARD? + case LBRACKET_CHR: + case LCURLY_CHR: + mode = *in; + if (*in == LCURLY_CHR) { + // create new wildcard + strcat(wildcards[nwildcards++], wildprefix); + } + continue; + + // ENDING A WILDCARD? + case RBRACKET_CHR: + case RCURLY_CHR: + mode = 'w'; // back to wildcard mode + continue; + + // ALL OTHER NON-SPECIAL CHARACTERS + default: +regchar: // handle regular char + switch (mode) { + case LBRACKET_CHR: + // create new wildcard + ++nwildcards; + // copy in prefix + strcpy(wildcards[nwildcards - 1], wildprefix); + // append search char + chrcat(wildcards[nwildcards - 1], *in); + continue; + + case LCURLY_CHR: + if (nwildcards > 0) { + chrcat(wildcards[nwildcards - 1], *in); + } + continue; + + case 'n': + chrcat(name, *in); + continue; + + case 'w': + chrcat(wildprefix, *in); + for (t = 0; t < nwildcards; t++) { + chrcat(wildcards[t], *in); + } + continue; + } + break; + } + } +} + +// SET 'CURRENTLY SELECTED FILTER' +void Fl_My_Native_File_Chooser::filter_value(int i) +{ + _ofn_ptr->nFilterIndex = i + 1; +} + +// RETURN VALUE OF 'CURRENTLY SELECTED FILTER' +int Fl_My_Native_File_Chooser::filter_value() const +{ + return (_ofn_ptr->nFilterIndex ? _ofn_ptr->nFilterIndex - 1 : _nfilters + 1); +} + +// PRESET FILENAME FOR 'SAVE AS' CHOOSER +void Fl_My_Native_File_Chooser::preset_file(const char *val) +{ + _preset_file = strfree(_preset_file); + _preset_file = strnew(val); +} + +// GET PRESET FILENAME FOR 'SAVE AS' CHOOSER +const char *Fl_My_Native_File_Chooser::preset_file() const +{ + return (_preset_file); +} + +int Fl_My_Native_File_Chooser::filters() const +{ + return (_nfilters); +} + +static char *wchartoutf8(LPCWSTR in) +{ + static char *out = NULL; + static int lchar = 0; + if (in == NULL) { + return NULL; + } + int utf8len = WideCharToMultiByte(CP_UTF8, 0, in, -1, NULL, 0, NULL, NULL); + if (utf8len > lchar) { + lchar = utf8len; + out = (char *)realloc(out, lchar * sizeof(char)); + } + WideCharToMultiByte(CP_UTF8, 0, in, -1, out, utf8len, NULL, NULL); + return out; +} + +static LPCWSTR utf8towchar(const char *in) +{ + static WCHAR *wout = NULL; + static int lwout = 0; + if (in == NULL) { + return NULL; + } + int wlen = MultiByteToWideChar(CP_UTF8, 0, in, -1, NULL, 0); + if (wlen > lwout) { + lwout = wlen; + wout = (WCHAR *)realloc(wout, lwout * sizeof(WCHAR)); + } + MultiByteToWideChar(CP_UTF8, 0, in, -1, wout, wlen); + return wout; +} + +#endif /*!FL_DOXYGEN*/ + +// +// End of "$Id$". +// diff --git a/src/FLTK/Fl_My_Native_File_Chooser_common.cxx b/src/FLTK/Fl_My_Native_File_Chooser_common.cxx new file mode 100644 index 0000000..e6f9c68 --- /dev/null +++ b/src/FLTK/Fl_My_Native_File_Chooser_common.cxx @@ -0,0 +1,84 @@ +// "$Id$" +// +// FLTK native OS file chooser widget +// +// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 2004 Greg Ercolano. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// + +#include +#include + +// COPY A STRING WITH 'new' +// Value can be NULL +// +static char *strnew(const char *val) +{ + if (val == NULL) { + return (NULL); + } + char *s = new char[strlen(val) + 1]; + strcpy(s, val); + return (s); +} + +// FREE STRING CREATED WITH strnew(), NULLS OUT STRING +// Value can be NULL +// +static char *strfree(char *val) +{ + if (val) { + delete[] val; + } + return (NULL); +} + +// 'DYNAMICALLY' APPEND ONE STRING TO ANOTHER +// Returns newly allocated string, or NULL +// if s && val == NULL. +// 's' can be NULL; returns a strnew(val). +// 'val' can be NULL; s is returned unmodified. +// +// Usage: +// char *s = strnew("foo"); // s = "foo" +// s = strapp(s, "bar"); // s = "foobar" +// +#if !defined(WIN32) +static char *strapp(char *s, const char *val) +{ + if (!val) { + return (s); // Nothing to append? return s + } + if (!s) { + return (strnew(val)); // New string? return copy of val + } + char *news = new char[strlen(s) + strlen(val) + 1]; + strcpy(news, s); + strcat(news, val); + delete[] s; // delete old string + return (news); // return new copy +} +#endif + +// APPEND A CHARACTER TO A STRING +// This does NOT allocate space for the new character. +// +static void chrcat(char *s, char c) +{ + char tmp[2] = {c, '\0'}; + strcat(s, tmp); +} + +// +// End of "$Id$". +// diff --git a/src/FLTK/Fl_vu_meter.cpp b/src/FLTK/Fl_vu_meter.cpp new file mode 100644 index 0000000..3f8403b --- /dev/null +++ b/src/FLTK/Fl_vu_meter.cpp @@ -0,0 +1,276 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "Fl_vu_meter.h" +#include "cfg.h" + +VUMeter::VUMeter(int X, int Y, int W, int H, const char *L) : Fl_Group(X, Y, W, H, L) +{ + channel_height = 13; + peak_bar_width = 2; + max_value = 0; + min_value = -54.0; + left_dB = -90; + right_dB = -90; + left_peak_dB = -90; + right_peak_dB = -90; + bg_color = color(); + width = w(); + height = h(); + x_origin = x(); + y_origin = y(); + left_chan_y1 = y_origin; + left_chan_y2 = left_chan_y1 + channel_height - 1; + right_chan_y1 = y_origin + height - channel_height; + right_chan_y2 = right_chan_y1 + channel_height - 1; + + solid_green = fl_rgb_color((uchar)0, (uchar)210, (uchar)0); + solid_yellow = fl_rgb_color((uchar)230, (uchar)230, (uchar)0); + solid_red = fl_rgb_color((uchar)200, (uchar)0, (uchar)0); + + tick_distance_dB = 6; + num_of_ticks = (0 - min_value) / tick_distance_dB; + tick_distance_px = width / num_of_ticks; + + vu_end_xpos = x_origin + width; +} + +void VUMeter::value(float left, float right, float left_peak, float right_peak) +{ + left_dB = left; + right_dB = right; + left_peak_dB = left_peak; + right_peak_dB = right_peak; + + redraw(); +} + +int VUMeter::dB_to_xpos(float dB) +{ + float dB_span = max_value - min_value; + + int xpos = (int)(x_origin + width / dB_span * (dB_span - abs(dB))); + + if (xpos < x_origin) { + xpos = x_origin; + } + + return xpos; +} + +void VUMeter::draw() +{ + Fl_Group::draw(); + + float offset = abs(min_value); + float left_vol = (left_dB + offset) / offset * width; + float right_vol = (right_dB + offset) / offset * width; + + int x1; + + double red, green, blue, gradient; + + // Clear whole widget area + fl_rectf(x_origin, y_origin, width, height, bg_color); + + if (cfg.gui.vu_mode == VU_MODE_SOLID) { + fl_color(cfg.gui.vu_low_color); + fl_rectf(x_origin, left_chan_y1, dB_to_xpos(left_dB) - x_origin, channel_height - 1); + + if (left_dB > cfg.gui.vu_mid_range_start) { + fl_color(cfg.gui.vu_mid_color); + fl_rectf(dB_to_xpos(cfg.gui.vu_mid_range_start), left_chan_y1, dB_to_xpos(left_dB) - dB_to_xpos(cfg.gui.vu_mid_range_start), channel_height - 1); + } + if (left_dB > cfg.gui.vu_high_range_start) { + fl_color(cfg.gui.vu_high_color); + fl_rectf(dB_to_xpos(cfg.gui.vu_high_range_start), left_chan_y1, dB_to_xpos(left_dB) - dB_to_xpos(cfg.gui.vu_high_range_start), channel_height - 1); + } + + fl_color(cfg.gui.vu_low_color); + fl_rectf(x_origin, right_chan_y1, dB_to_xpos(right_dB) - x_origin, channel_height - 1); + if (right_dB > cfg.gui.vu_mid_range_start) { + fl_color(cfg.gui.vu_mid_color); + fl_rectf(dB_to_xpos(cfg.gui.vu_mid_range_start), right_chan_y1, dB_to_xpos(right_dB) - dB_to_xpos(cfg.gui.vu_mid_range_start), channel_height - 1); + } + if (right_dB > cfg.gui.vu_high_range_start) { + fl_color(cfg.gui.vu_high_color); + fl_rectf(dB_to_xpos(cfg.gui.vu_high_range_start), right_chan_y1, dB_to_xpos(right_dB) - dB_to_xpos(cfg.gui.vu_high_range_start), + channel_height - 1); + } + } + else { // Gradient + int gradient_offset = 10; + for (int x_pos = 0; x_pos <= width - 2; x_pos += 1) { + x1 = x_origin + x_pos; + + // fl_color(bg_color); + if (left_vol > x_pos) { + if (x1 < dB_to_xpos(cfg.gui.vu_mid_range_start) - gradient_offset) { + fl_color(cfg.gui.vu_low_color); + } + else if (x1 < dB_to_xpos(cfg.gui.vu_mid_range_start)) { + uchar r1, g1, b1; + uchar r2, g2, b2; + uchar r, g, b; + int c1 = cfg.gui.vu_low_color; + int c2 = cfg.gui.vu_mid_color; + r1 = (c1 & 0xFF000000) >> 24; + g1 = (c1 & 0x00FF0000) >> 16; + b1 = (c1 & 0x0000FF00) >> 8; + r2 = (c2 & 0xFF000000) >> 24; + g2 = (c2 & 0x00FF0000) >> 16; + b2 = (c2 & 0x0000FF00) >> 8; + + // Interpolate color + int i = x1 - (dB_to_xpos(cfg.gui.vu_mid_range_start) - gradient_offset); + r = round(r1 + (float)i / gradient_offset * (r2 - r1)); + g = round(g1 + (float)i / gradient_offset * (g2 - g1)); + b = round(b1 + (float)i / gradient_offset * (b2 - b1)); + fl_color(fl_rgb_color(r, g, b)); + } + else if (x1 < dB_to_xpos(cfg.gui.vu_high_range_start) - gradient_offset) { + fl_color(cfg.gui.vu_mid_color); + } + else if (x1 < dB_to_xpos(cfg.gui.vu_high_range_start)) { + uchar r1, g1, b1; + uchar r2, g2, b2; + uchar r, g, b; + int c1 = cfg.gui.vu_mid_color; + int c2 = cfg.gui.vu_high_color; + int i = x1 - (dB_to_xpos(cfg.gui.vu_high_range_start) - gradient_offset); + r1 = (c1 & 0xFF000000) >> 24; + g1 = (c1 & 0x00FF0000) >> 16; + b1 = (c1 & 0x0000FF00) >> 8; + r2 = (c2 & 0xFF000000) >> 24; + g2 = (c2 & 0x00FF0000) >> 16; + b2 = (c2 & 0x0000FF00) >> 8; + + r = round(r1 + (float)i / gradient_offset * (r2 - r1)); + g = round(g1 + (float)i / gradient_offset * (g2 - g1)); + b = round(b1 + (float)i / gradient_offset * (b2 - b1)); + fl_color(fl_rgb_color(r, g, b)); + } + else { + fl_color(cfg.gui.vu_high_color); + } + fl_line(x1, left_chan_y1, x1, left_chan_y2); + } + + // fl_color(bg_color); + if (right_vol > x_pos) { + if (x1 < dB_to_xpos(cfg.gui.vu_mid_range_start) - gradient_offset) { + fl_color(cfg.gui.vu_low_color); + } + else if (x1 < dB_to_xpos(cfg.gui.vu_mid_range_start)) { + uchar r1, g1, b1; + uchar r2, g2, b2; + uchar r, g, b; + int c1 = cfg.gui.vu_low_color; + int c2 = cfg.gui.vu_mid_color; + r1 = (c1 & 0xFF000000) >> 24; + g1 = (c1 & 0x00FF0000) >> 16; + b1 = (c1 & 0x0000FF00) >> 8; + r2 = (c2 & 0xFF000000) >> 24; + g2 = (c2 & 0x00FF0000) >> 16; + b2 = (c2 & 0x0000FF00) >> 8; + + int i = x1 - (dB_to_xpos(cfg.gui.vu_mid_range_start) - gradient_offset); + r = round(r1 + (float)i / gradient_offset * (r2 - r1)); + g = round(g1 + (float)i / gradient_offset * (g2 - g1)); + b = round(b1 + (float)i / gradient_offset * (b2 - b1)); + fl_color(fl_rgb_color(r, g, b)); + } + else if (x1 < dB_to_xpos(cfg.gui.vu_high_range_start) - gradient_offset) { + fl_color(cfg.gui.vu_mid_color); + } + else if (x1 < dB_to_xpos(cfg.gui.vu_high_range_start)) { + uchar r1, g1, b1; + uchar r2, g2, b2; + uchar r, g, b; + int c1 = cfg.gui.vu_mid_color; + int c2 = cfg.gui.vu_high_color; + int i = x1 - (dB_to_xpos(cfg.gui.vu_high_range_start) - gradient_offset); + r1 = (c1 & 0xFF000000) >> 24; + g1 = (c1 & 0x00FF0000) >> 16; + b1 = (c1 & 0x0000FF00) >> 8; + r2 = (c2 & 0xFF000000) >> 24; + g2 = (c2 & 0x00FF0000) >> 16; + b2 = (c2 & 0x0000FF00) >> 8; + + r = round(r1 + (float)i / gradient_offset * (r2 - r1)); + g = round(g1 + (float)i / gradient_offset * (g2 - g1)); + b = round(b1 + (float)i / gradient_offset * (b2 - b1)); + fl_color(fl_rgb_color(r, g, b)); + } + else { + fl_color(cfg.gui.vu_high_color); + } + fl_line(x1, right_chan_y1, x1, right_chan_y2); + } + } + } + + int left_peak_pos, right_peak_pos; + + fl_color(FL_BLACK); + if (left_peak_dB >= left_dB) { + left_peak_pos = dB_to_xpos(left_peak_dB); + if (left_peak_pos >= vu_end_xpos) { + left_peak_pos -= peak_bar_width + 2; // The +2 assures that the peak bar is visible at 0 dB + } + + fl_rectf(left_peak_pos, left_chan_y1, peak_bar_width, channel_height - 1); + } + + if (right_peak_dB >= right_dB) { + right_peak_pos = dB_to_xpos(right_peak_dB); + if (right_peak_pos >= vu_end_xpos) { + right_peak_pos -= peak_bar_width + 2; + } + fl_rectf(right_peak_pos, right_chan_y1, peak_bar_width, channel_height - 1); + } + + fl_draw_box(FL_THIN_DOWN_FRAME, x_origin, left_chan_y1, width, channel_height, bg_color); + fl_draw_box(FL_THIN_DOWN_FRAME, x_origin, right_chan_y1, width, channel_height, bg_color); + fl_draw_box(FL_THIN_DOWN_FRAME, x_origin, y_origin, width, height, FL_DARK1); + + fl_color(FL_BLACK); + fl_font(FL_HELVETICA, 10); + +#if defined(__APPLE__) + fl_draw("L", x_origin - 9, y_origin + 8); + fl_draw("R", x_origin - 9, y_origin + height - 3); +#else + fl_draw("L", x_origin - 9, y_origin + 9); + fl_draw("R", x_origin - 9, y_origin + height - 2); +#endif + + int tick_pos; + char dB_val[4]; + fl_font(FL_HELVETICA, 9); + +#if defined(__APPLE__) + fl_draw("dB", x_origin - 13, y_origin + height / 2 + 2); +#else + fl_draw("dB", x_origin - 13, y_origin + height / 2 + 3); +#endif + for (int n = 1; n <= num_of_ticks; n++) { + tick_pos = x_origin + n * tick_distance_px; + + fl_line(tick_pos, y_origin, tick_pos, y_origin + 3); + fl_line(tick_pos, y_origin + height - 1, tick_pos, y_origin + height - 4); + + snprintf(dB_val, sizeof(dB_val), "%d", (int)min_value + n * tick_distance_dB); + +#if defined(__APPLE__) + fl_draw(dB_val, tick_pos - 5, y_origin + height / 2 + 2); +#else + fl_draw(dB_val, tick_pos - 5, y_origin + height / 2 + 3); +#endif + } +} diff --git a/src/FLTK/Fl_vu_meter.h b/src/FLTK/Fl_vu_meter.h new file mode 100644 index 0000000..74aafd2 --- /dev/null +++ b/src/FLTK/Fl_vu_meter.h @@ -0,0 +1,42 @@ +#ifndef FL_VU_METER_H +#define FL_VU_METER_H +#include +#include +#include +#include +#include +#include +#include + +class VUMeter : public Fl_Group { + public: + float left_dB, right_dB; + + private: + float left_peak_dB, right_peak_dB; + float min_value, max_value; + int channel_height; + int width, height; + int peak_bar_width; + int vu_end_xpos; + int x_origin, y_origin; + int left_chan_y1, left_chan_y2; + int right_chan_y1, right_chan_y2; + int tick_distance_dB; + int tick_distance_px; + int num_of_ticks; + Fl_Color solid_red; + Fl_Color solid_green; + Fl_Color solid_yellow; + + Fl_Color bg_color; + + public: + VUMeter(int X, int Y, int W, int H, const char *L = 0); + + void value(float left, float right, float left_peak, float right_peak); + int dB_to_xpos(float dB); + void draw(); +}; + +#endif // FL_VU_METER_H diff --git a/src/FLTK/fl_callbacks.cpp b/src/FLTK/fl_callbacks.cpp new file mode 100644 index 0000000..fd47a80 --- /dev/null +++ b/src/FLTK/fl_callbacks.cpp @@ -0,0 +1,6466 @@ +// FLTK callback functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +#include +#include + +#include +#include +#include +#include +#include + +#ifdef WIN32 +#define usleep(us) Sleep(us / 1000) +#include "tray_agent.h" +#else +#include +#endif + +#include +#include +#include + +#include + +#include "gettext.h" +#include "config.h" + +#include "FL/Fl_My_Native_File_Chooser.H" +// #include +// #define Fl_My_Native_File_Chooser Fl_Native_File_Chooser + +#include "cfg.h" +#include "butt.h" +#include "port_audio.h" +#include "port_midi.h" +#include "timer.h" +#include "shoutcast.h" +#include "icecast.h" +#include "webrtc.h" +#include "lame_encode.h" +#include "opus_encode.h" +#include "fl_callbacks.h" +#include "strfuncs.h" +#include "flgui.h" +#include "util.h" +#include "fl_timer_funcs.h" +#include "fl_funcs.h" +#include "update.h" +#include "command.h" +#include "url.h" +#include "atom.h" +#ifdef WITH_RADIOCO +#include "radioco.h" +#include "oauth.h" +#endif + +flgui *fl_g; +int display_info = STREAM_TIME; + +pthread_t pt_connect_detached; + +ATOM_NEW_INT(is_updating_song, 0); + +int ask_user = 0; +void *connect_thread(void *data) +{ + int ret; + int (*xc_connect)() = NULL; + + if (cfg.srv[cfg.selected_srv]->type == ICECAST) { + xc_connect = &ic_connect; + } +#ifdef HAVE_LIBDATACHANNEL + else if (cfg.srv[cfg.selected_srv]->type == WEBRTC) { + xc_connect = &webrtc_connect; + } +#endif + else { //(cfg.srv[cfg.selected_srv]->type == SHOUTCAST) + xc_connect = &sc_connect; + } + + // try to connect as long as xc_connect returns non-zero and try_to_connect == 1 + while (((ret = xc_connect()) != IC_OK) && (try_to_connect == 1)) { // xc_connect returns 0 when connected + // Stop connecting in case of a fatal error + if (ret == IC_ABORT) { + try_to_connect = 0; + break; + } + if (ret == IC_ASK) { + ask_user = 1; + while (ask_user_get_has_clicked() != 1) { + usleep(100 * 1000); // 100 ms + } + + if (ask_user_get_answer() == IC_ABORT) { + try_to_connect = 0; + ask_user_reset(); + break; + } + ask_user_reset(); + } + + usleep(100 * 1000); // 100ms + } + + // Reset display + if (recording == 0 && try_to_connect == 0) { + // Make sure this code runs on main thread (async) + Fl::awake([](void *) -> void { + fl_g->lcd->clear(); + fl_g->lcd->print((const uchar *)_("idle"), strlen(_("idle"))); + fl_g->sponsor_logo->show(); + fl_g->sponsor_logo->redraw(); + }); + } + else { + try_to_connect = 0; + } + + // Detach thread (free ressources) because no one will call pthread_join() on it + pthread_detach(pthread_self()); + + return NULL; +} + +// Print "Connecting..." on the LCD as long as we are trying to connect +void print_connecting_timeout(void *) +{ + static int dummy = 0; + + if (try_to_connect == 1) { + if (dummy == 0) { + print_lcd(_("connecting"), strlen(_("connecting")), 0, 1); + dummy++; + } + else if (dummy <= 3) { + print_lcd(".", 1, 0, 0); + dummy++; + } + else if (dummy > 3) { + dummy = 0; + } + else { + dummy++; + } + + Fl::repeat_timeout(0.25, &print_connecting_timeout); + } + else { + dummy = 0; + } +} + +void show_vu_tabs(void) +{ + fl_g->vu_tabs->show(); + fl_g->label_volume->hide(); +} +void hide_vu_tabs(void) +{ + fl_g->vu_tabs->hide(); + fl_g->label_volume->show(); +} + +void button_connect_cb(void) +{ + char text_buf[256]; + int codec_samplerate = 0; + + if (connected || try_to_connect) { + goto not_connected; + } + + if (cfg.main.num_of_srv < 1) { + print_info(_("Error: No server entry found.\nPlease add a server in the settings-window."), 1); + goto not_connected; + } + + if (!strcmp(cfg.audio.codec, "ogg") && (cfg.audio.bitrate < 48)) { + print_info(_("Error: ogg vorbis encoder doesn't support bitrates\n" + "lower than 48kbit"), + 1); + goto not_connected; + } + + if (cfg.srv[cfg.selected_srv]->type == SHOUTCAST) { + if ((!strcmp(cfg.audio.codec, "ogg")) || (!strcmp(cfg.audio.codec, "opus"))) { + snprintf(text_buf, sizeof(text_buf), _("Warning: %s is not supported by every Shoutcast version"), cfg.audio.codec); + print_info(text_buf, 1); + } + if (!strcmp(cfg.audio.codec, "flac")) { + print_info(_("Error: FLAC is not supported by ShoutCast"), 1); + goto not_connected; + } + } + + if (cfg.srv[cfg.selected_srv]->type == RADIOCO) { + if ((strcmp(cfg.audio.codec, "mp3")) && (strcmp(cfg.audio.codec, "aac"))) { + snprintf(text_buf, sizeof(text_buf), _("Error: Radio.co supports only mp3 and aac")); + print_info(text_buf, 1); + goto not_connected; + } + } + + if (cfg.srv[cfg.selected_srv]->type == WEBRTC) { + if (strcmp(cfg.audio.codec, "opus")) { + snprintf(text_buf, sizeof(text_buf), _("Error: WebRTC only supports opus")); + print_info(text_buf, 1); + return; + } + } + + if (cfg.srv[cfg.selected_srv]->type == WEBRTC) { + snprintf(text_buf, sizeof(text_buf), _("Connecting to %s via %s ..."), cfg.srv[cfg.selected_srv]->webrtc_whip, cfg.srv[cfg.selected_srv]->webrtc_ice); + } + else if (cfg.srv[cfg.selected_srv]->type == ICECAST) { + snprintf(text_buf, sizeof(text_buf), _("Connecting to %s:%u ..."), cfg.srv[cfg.selected_srv]->addr, cfg.srv[cfg.selected_srv]->port); + } + else { + snprintf(text_buf, sizeof(text_buf), _("Connecting to %s:%u (%u) ..."), cfg.srv[cfg.selected_srv]->addr, cfg.srv[cfg.selected_srv]->port + 1, + cfg.srv[cfg.selected_srv]->port); + } + + print_info(text_buf, 0); + + // Clear libsamplerate state + snd_reset_samplerate_conv(SND_STREAM); + + try_to_connect = 1; + if (pthread_create(&pt_connect_detached, NULL, connect_thread, NULL) != 0) { + print_info("Fatal error: Could not launch connect thread. Please restart BUTT", 1); + try_to_connect = 0; + goto not_connected; + } + Fl::add_timeout(0, &print_connecting_timeout); + + while (try_to_connect) { + if (ask_user == 1) { + ask_user_ask(); + ask_user = 0; + } + + usleep(10000); // 10 ms + Fl::wait(0); // update gui and parse user events + } + + if (!connected) { + goto not_connected; + } + + // we have to make sure that the first audio data + // the server sees are the ogg headers + if (!strcmp(cfg.audio.codec, "ogg")) { + vorbis_stream.header_written = 0; + vorbis_enc_write_header(&vorbis_stream); + codec_samplerate = vorbis_enc_get_samplerate(&vorbis_stream); + } + + if (!strcmp(cfg.audio.codec, "opus")) { + opus_enc_write_header(&opus_stream); + codec_samplerate = opus_enc_get_samplerate(&opus_stream); + } + + // Reset the internal flac frame counter to zero to + // make sure that the header is sent to the server upon next connect + if (!strcmp(cfg.audio.codec, "flac")) { + flac_enc_reinit(&flac_stream); + codec_samplerate = flac_enc_get_samplerate(&flac_stream); + } + + if (!strcmp(cfg.audio.codec, "mp3")) { + codec_samplerate = lame_enc_get_samplerate(&lame_stream); + } + +#ifdef HAVE_LIBFDK_AAC + if (!strcmp(cfg.audio.codec, "aac")) { + codec_samplerate = aac_enc_get_samplerate(&aac_stream); + } +#endif + + char bitrate_str[32]; + if (strcmp(cfg.audio.codec, "flac") == 0) { + snprintf(bitrate_str, sizeof(bitrate_str), "-"); + } + else { + snprintf(bitrate_str, sizeof(bitrate_str), "%dkbps", cfg.audio.bitrate); + } + + char server_type[32]; + switch (cfg.srv[cfg.selected_srv]->type) { + case ICECAST: + snprintf(server_type, sizeof(server_type), "Icecast"); + break; + case SHOUTCAST: + snprintf(server_type, sizeof(server_type), "Shoutcast"); + break; + case RADIOCO: + snprintf(server_type, sizeof(server_type), "Radio.co"); + break; + case WEBRTC: + snprintf(server_type, sizeof(server_type), "WebRTC"); + break; + default: + snprintf(server_type, sizeof(server_type), "Unknown"); + break; + } + + char samplerate_text[32]; + if (cfg.audio.samplerate == codec_samplerate) { + snprintf(samplerate_text, sizeof(samplerate_text), "%dHz", cfg.audio.samplerate); + } + else { + snprintf(samplerate_text, sizeof(samplerate_text), "%dHz -> %dHz", cfg.audio.samplerate, codec_samplerate); + } + + print_info(_("Connection established"), 0); + snprintf(text_buf, sizeof(text_buf), + "Settings:\n" + "Type:\t\t%s\n" + "Codec:\t\t%s\n" + "Bitrate:\t%s\n" + "Samplerate:\t%s\n", + server_type, cfg.audio.codec, bitrate_str, samplerate_text); + + if (cfg.srv[cfg.selected_srv]->type == ICECAST) { + snprintf(text_buf + strlen(text_buf), sizeof(text_buf) - strlen(text_buf), + "Mountpoint:\t%s\n" + "User:\t\t%s\n" + "SSL/TLS:\t%s\n", + cfg.srv[cfg.selected_srv]->mount, cfg.srv[cfg.selected_srv]->usr, cfg.srv[cfg.selected_srv]->tls == 0 ? _("no") : _("yes")); + } + snprintf(text_buf + strlen(text_buf), sizeof(text_buf) - strlen(text_buf), _("Device 1:\t%s\n"), cfg.audio.dev_name); + snprintf(text_buf + strlen(text_buf), sizeof(text_buf) - strlen(text_buf), _("Device 2:\t%s\n"), cfg.audio.dev2_name); + print_info(text_buf, 0); + + static int called_from_connect_cb = 1; + if (!cfg.main.song_update && !cfg.main.app_update) { + Fl::add_timeout(cfg.main.song_delay, &update_song, &called_from_connect_cb); + } + + deactivate_stream_ui_elements(); + + pa_new_frames = 0; + + // Just in case the record routine started a check_time timeout + // already + static int reset = 1; + Fl::remove_timeout(&display_info_timer); + Fl::add_timeout(0.1, &display_info_timer, &reset); + + Fl::remove_timeout(&is_connected_timer); + Fl::add_timeout(0.5, &is_connected_timer); + + if (cfg.main.song_update_url_active) { + Fl::remove_timeout(&song_url_timer); + Fl::add_timeout(cfg.main.song_update_url_interval, &song_url_timer); + } + + if (cfg.gui.show_listeners) { + Fl::remove_timeout(&request_listener_count_timer); + Fl::add_timeout(0.5, &request_listener_count_timer, &reset); + } + + if (cfg.main.song_update) { + Fl::remove_timeout(&songfile_timer); + Fl::add_timeout(0.5, &songfile_timer, &reset); + } + + if (cfg.main.app_update) { + current_track_app = getCurrentTrackFunctionFromId(cfg.main.app_update_service); + Fl::remove_timeout(&app_timer); + Fl::add_timeout(0.5, &app_timer, &reset); + } + + reset_stream_silence_detection_timer(); + + snd_start_streaming_thread(); + + if (cfg.rec.start_rec && !recording) { + button_record_cb(false); + } + + if (strlen(cfg.gui.window_title) == 0) { + snprintf(text_buf, sizeof(text_buf), _("Connected to: %s"), cfg.srv[cfg.selected_srv]->name); + fl_g->window_main->label(text_buf); + } + + fl_g->button_connect->color(fl_rgb_color(12, 179, 0)); + fl_g->button_connect->redraw(); + + display_info = cfg.gui.default_stream_info; + +#ifdef WIN32 + if (tray_agent_is_running(NULL) == 1) { + tray_agent_send_cmd(TA_CONNECT_STATE); + } +#endif + + return; + +not_connected: + reset_stream_signal_detection_timer(); + return; +} + +void button_cfg_cb(void) +{ + if (fl_g->window_cfg->shown()) { + fl_g->window_cfg->hide(); + Fl::remove_timeout(&cfg_win_pos_timer); + } + else { +#ifdef WIN32 + fl_g->window_cfg->position(fl_g->window_main->x() + fl_g->window_main->w() + 0, fl_g->window_main->y()); +#else + fl_g->window_cfg->position(fl_g->window_main->x() + fl_g->window_main->w(), fl_g->window_main->y()); +#endif + fl_g->window_cfg->show(); + fill_cfg_widgets(); + + if (cfg.gui.attach) { + Fl::add_timeout(0.1, &cfg_win_pos_timer); + } + } +} + +void button_mixer_cb(void) +{ + if (fl_g->window_mixer->shown()) { + fl_g->window_mixer->hide(); + } + else { +#ifdef WIN32 + fl_g->window_mixer->position(fl_g->window_main->x() - fl_g->window_mixer->w() + 0, fl_g->window_main->y()); +#else + fl_g->window_mixer->position(fl_g->window_main->x() - fl_g->window_mixer->w(), fl_g->window_main->y()); +#endif + fl_g->window_mixer->show(); + } +} + +// add new server +void button_add_srv_add_cb(void) +{ + int i, j, k; + int server_exists; + +#ifdef WITH_RADIOCO + if (fl_g->radio_add_srv_radioco->value()) { + if (fl_g->browser_add_srv_station_list->nchecked() == 0) { + return; + } + + radioco_stations_t stations; + radioco_get_station_list(&stations); + for (i = 0; i < stations.num_of_stations; i++) { + if (fl_g->browser_add_srv_station_list->checked(i + 1) == 0) { + continue; + } + + server_exists = 0; + // check if the name already exists + for (j = 0; j < cfg.main.num_of_srv; j++) { + if (!strcmp(stations.name[i], cfg.srv[j]->name)) { + server_exists = 1; + break; + } + } + if (server_exists == 1) { + // Update server credentials + cfg.srv[j]->addr = (char *)realloc(cfg.srv[j]->addr, strlen(stations.host[i]) + 1); + strcpy(cfg.srv[j]->addr, stations.host[i]); + + cfg.srv[j]->pwd = (char *)realloc(cfg.srv[j]->pwd, strlen(stations.password[i]) + 1); + strcpy(cfg.srv[j]->pwd, stations.password[i]); + + cfg.srv[j]->port = stations.port[i]; + continue; + } + + k = cfg.main.num_of_srv; + cfg.main.num_of_srv++; + + cfg.srv = (server_t **)realloc(cfg.srv, cfg.main.num_of_srv * sizeof(server_t *)); + cfg.srv[k] = (server_t *)malloc(sizeof(server_t)); + memset(cfg.srv[k], 0, sizeof(server_t)); + + cfg.srv[k]->name = (char *)malloc(strlen(stations.name[i]) + 1); + strcpy(cfg.srv[k]->name, stations.name[i]); + strrpl(&cfg.srv[k]->name, (char *)"[", (char *)"", MODE_ALL); + strrpl(&cfg.srv[k]->name, (char *)"]", (char *)"", MODE_ALL); + strrpl(&cfg.srv[k]->name, (char *)"/", (char *)"", MODE_ALL); + strrpl(&cfg.srv[k]->name, (char *)"\\", (char *)"", MODE_ALL); + strrpl(&cfg.srv[k]->name, (char *)";", (char *)"", MODE_ALL); + + cfg.srv[k]->addr = (char *)malloc(strlen(stations.host[i]) + 1); + strcpy(cfg.srv[k]->addr, stations.host[i]); + + cfg.srv[k]->pwd = (char *)malloc(strlen(stations.password[i]) + 1); + strcpy(cfg.srv[k]->pwd, stations.password[i]); + + cfg.srv[k]->port = stations.port[i]; + cfg.srv[k]->type = RADIOCO; + + if (cfg.main.num_of_srv > 1) { + cfg.main.srv_ent = (char *)realloc(cfg.main.srv_ent, strlen(cfg.main.srv_ent) + strlen(cfg.srv[k]->name) + 2); + sprintf(cfg.main.srv_ent + strlen(cfg.main.srv_ent), ";%s", cfg.srv[k]->name); + cfg.main.srv = (char *)realloc(cfg.main.srv, strlen(cfg.srv[k]->name) + 1); + } + else { + cfg.main.srv_ent = (char *)malloc(strlen(cfg.srv[k]->name) + 1); + sprintf(cfg.main.srv_ent, "%s", cfg.srv[k]->name); + cfg.main.srv = (char *)malloc(strlen(cfg.srv[k]->name) + 1); + } + + fl_g->choice_cfg_act_srv->add(cfg.srv[k]->name); + fl_g->choice_cfg_act_srv->redraw(); + strcpy(cfg.main.srv, cfg.srv[k]->name); + fl_g->choice_cfg_act_srv->value(k); + } + + // Activate del and edit buttons + fl_g->button_cfg_edit_srv->activate(); + fl_g->button_cfg_del_srv->activate(); + + fl_g->choice_cfg_act_srv->activate(); + + // make last added server the active server + choice_cfg_act_srv_cb(); + + fl_g->browser_add_srv_station_list->clear(); + + fl_g->window_add_srv->hide(); + + return; + } +#endif + + // figure out current server type + int server_type; + if (fl_g->radio_add_srv_shoutcast->value()) { + server_type = SHOUTCAST; + } + if (fl_g->radio_add_srv_icecast->value()) { + server_type = ICECAST; + } + if (fl_g->radio_add_srv_webrtc->value()) { + server_type = WEBRTC; + } + + // error checking + const char *listener_url = fl_g->input_add_srv_listener_url->value(); + if (strlen(listener_url) > 0) { + if (strncmp(listener_url, "http://", strlen("http://")) != 0 && strncmp(listener_url, "https://", strlen("https://")) != 0) { + fl_alert(_("The custom listener URL must start with http:// or https://")); + return; + } + } + + if (server_type == ICECAST) { + if (strlen(fl_g->input_add_srv_mount->value()) == 0) { + fl_alert(_("No mountpoint specified\nSetting mountpoint to \"stream\"")); + fl_g->input_add_srv_mount->value("stream"); + } + if (strlen(fl_g->input_add_srv_usr->value()) == 0) { + fl_alert(_("No user specified\nSetting user to \"source\"")); + fl_g->input_add_srv_usr->value("source"); + } + } + + if (strlen(listener_url) > 0) { + if (strstr(listener_url, "/status-json.xsl") == NULL && strstr(listener_url, "/7.xsl") == NULL && // + strstr(listener_url, "/stats?sid") == NULL && strstr(listener_url, "/7.html") == NULL) { + fl_alert(_("Unsupported listener URL.\nThe listener URL must end with status-json.xsl, 7.xsl, 7.html or contain stats?sid")); + return; + } + } + + if (strlen(fl_g->input_add_srv_name->value()) == 0) { + fl_alert(_("No name specified")); + return; + } + if (cfg.main.srv_ent != NULL) { + if (strlen(fl_g->input_add_srv_name->value()) + strlen(cfg.main.srv_ent) > 1000) { + fl_alert(_("The number of characters of all your server names exeeds 1000\n" + "Please reduce the number of characters of each server name")); + return; + } + } + if (strpbrk(fl_g->input_add_srv_name->value(), "[];\\/\n\r") != NULL) { + fl_alert(_("Newline characters and [];/\\ are not allowed within the server name")); + return; + } + + if (server_type != WEBRTC) { + if (strlen(fl_g->input_add_srv_addr->value()) == 0) { + fl_alert(_("No address specified")); + return; + } + if (strlen(fl_g->input_add_srv_pwd->value()) == 0) { + fl_alert(_("No password specified")); + return; + } + if (strlen(fl_g->input_add_srv_port->value()) == 0) { + fl_alert(_("No port specified")); + return; + } + else if ((atoi(fl_g->input_add_srv_port->value()) > 65535) || (atoi(fl_g->input_add_srv_port->value()) < 1)) { + fl_alert(_("Invalid port number\nThe port number must be between 1 and 65535")); + return; + } + } + if (server_type == WEBRTC) { + // TODO: validate that the ICE server URL is a valid format for rtcCreatePeerConnection() in libdatachannel + if (strlen(fl_g->input_webrtc_whip_url->value()) == 0) { + fl_alert(_("No WHIP URL specified")); + return; + } + // TODO: validate that the WHIP URL is in valid URL format + } + + // check if the name already exists + for (i = 0; i < cfg.main.num_of_srv; i++) { + if (!strcmp(fl_g->input_add_srv_name->value(), cfg.srv[i]->name)) { + fl_alert(_("Server name already exist!")); + return; + } + } + + i = cfg.main.num_of_srv; + cfg.main.num_of_srv++; + + cfg.srv = (server_t **)realloc(cfg.srv, cfg.main.num_of_srv * sizeof(server_t *)); + cfg.srv[i] = (server_t *)malloc(sizeof(server_t)); + memset(cfg.srv[i], 0, sizeof(server_t)); + + cfg.srv[i]->name = (char *)malloc(strlen(fl_g->input_add_srv_name->value()) + 1); + strcpy(cfg.srv[i]->name, fl_g->input_add_srv_name->value()); + + cfg.srv[i]->type = server_type; + if (server_type != WEBRTC) { + cfg.srv[i]->addr = (char *)malloc(strlen(fl_g->input_add_srv_addr->value()) + 1); + strcpy(cfg.srv[i]->addr, fl_g->input_add_srv_addr->value()); + + // strip leading http:// from addr + strrpl(&cfg.srv[i]->addr, (char *)"http://", (char *)"", MODE_ALL); + strrpl(&cfg.srv[i]->addr, (char *)"https://", (char *)"", MODE_ALL); + + cfg.srv[i]->pwd = (char *)malloc(strlen(fl_g->input_add_srv_pwd->value()) + 1); + strcpy(cfg.srv[i]->pwd, fl_g->input_add_srv_pwd->value()); + + cfg.srv[i]->port = atoi(fl_g->input_add_srv_port->value()); + + if (strlen(fl_g->input_add_srv_listener_url->value()) > 0) { + cfg.srv[i]->custom_listener_url = (char *)malloc(strlen(fl_g->input_add_srv_listener_url->value()) + 1); + strcpy(cfg.srv[i]->custom_listener_url, fl_g->input_add_srv_listener_url->value()); + } + + if (strlen(fl_g->input_add_srv_listener_mount->value()) > 0) { + cfg.srv[i]->custom_listener_mount = (char *)malloc(strlen(fl_g->input_add_srv_listener_mount->value()) + 1); + strcpy(cfg.srv[i]->custom_listener_mount, fl_g->input_add_srv_listener_mount->value()); + } + } + else { // WEBRTC + if (strlen(fl_g->input_webrtc_icesrv_url->value()) > 0) { + cfg.srv[i]->webrtc_ice = (char *)malloc(strlen(fl_g->input_webrtc_icesrv_url->value()) + 1); + strcpy(cfg.srv[i]->webrtc_ice, fl_g->input_webrtc_icesrv_url->value()); + } + + cfg.srv[i]->webrtc_whip = (char *)malloc(strlen(fl_g->input_webrtc_whip_url->value()) + 1); + strcpy(cfg.srv[i]->webrtc_whip, fl_g->input_webrtc_whip_url->value()); + + if (strlen(fl_g->input_webrtc_auth_token->value()) > 0) { + cfg.srv[i]->webrtc_auth = (char *)malloc(strlen(fl_g->input_webrtc_auth_token->value()) + 1); + strcpy(cfg.srv[i]->webrtc_auth, fl_g->input_webrtc_auth_token->value()); + } + } + + if (server_type == ICECAST) { + cfg.srv[i]->mount = (char *)malloc(strlen(fl_g->input_add_srv_mount->value()) + 1); + strcpy(cfg.srv[i]->mount, fl_g->input_add_srv_mount->value()); + + cfg.srv[i]->usr = (char *)malloc(strlen(fl_g->input_add_srv_usr->value()) + 1); + strcpy(cfg.srv[i]->usr, fl_g->input_add_srv_usr->value()); + + cfg.srv[i]->icecast_protocol = fl_g->check_add_srv_protocol->value(); + } + + cfg.srv[i]->tls = fl_g->check_add_srv_tls->value(); + + if (cfg.main.num_of_srv > 1) { + cfg.main.srv_ent = (char *)realloc(cfg.main.srv_ent, strlen(cfg.main.srv_ent) + strlen(cfg.srv[i]->name) + 2); + sprintf(cfg.main.srv_ent + strlen(cfg.main.srv_ent), ";%s", cfg.srv[i]->name); + cfg.main.srv = (char *)realloc(cfg.main.srv, strlen(cfg.srv[i]->name) + 1); + } + else { + cfg.main.srv_ent = (char *)malloc(strlen(cfg.srv[i]->name) + 1); + sprintf(cfg.main.srv_ent, "%s", cfg.srv[i]->name); + cfg.main.srv = (char *)malloc(strlen(cfg.srv[i]->name) + 1); + } + strcpy(cfg.main.srv, cfg.srv[i]->name); + + // reset the input fields and hide the window + fl_g->input_add_srv_name->value(""); + fl_g->input_add_srv_addr->value(""); + fl_g->input_add_srv_port->value(""); + fl_g->input_add_srv_pwd->value(""); + fl_g->input_add_srv_mount->value(""); + fl_g->input_add_srv_usr->value(""); + fl_g->window_add_srv->hide(); + fl_g->check_add_srv_tls->value(0); + fl_g->check_add_srv_protocol->value(ICECAST_PROTOCOL_PUT); + fl_g->input_webrtc_icesrv_url->value(""); + fl_g->input_webrtc_whip_url->value(""); + fl_g->input_webrtc_auth_token->value(""); + fl_g->input_add_srv_listener_url->value(""); + fl_g->input_add_srv_listener_mount->value(""); + + fl_g->choice_cfg_act_srv->add(cfg.srv[i]->name); + fl_g->choice_cfg_act_srv->redraw(); + + // Activate del and edit buttons + fl_g->button_cfg_edit_srv->activate(); + fl_g->button_cfg_del_srv->activate(); + + fl_g->choice_cfg_act_srv->activate(); + + // make added server the active server + fl_g->choice_cfg_act_srv->value(i); + choice_cfg_act_srv_cb(); +} + +void button_cfg_del_srv_cb(void) +{ + int i; + int diff; + + if (cfg.main.num_of_srv == 0) { + return; + } + + if (cfg.srv[cfg.selected_srv]->name != NULL) { + free(cfg.srv[cfg.selected_srv]->name); + } + + if (cfg.srv[cfg.selected_srv]->addr != NULL) { + free(cfg.srv[cfg.selected_srv]->addr); + } + + diff = cfg.main.num_of_srv - 1 - cfg.selected_srv; + for (i = 0; i < diff; i++) { + memcpy(cfg.srv[cfg.selected_srv + i], cfg.srv[cfg.selected_srv + i + 1], sizeof(server_t)); + } + + free(cfg.srv[cfg.main.num_of_srv - 1]); + + cfg.main.num_of_srv--; + + // rearrange the string that contains all server names + memset(cfg.main.srv_ent, 0, strlen(cfg.main.srv_ent)); + for (i = 0; i < (int)cfg.main.num_of_srv; i++) { + strcat(cfg.main.srv_ent, cfg.srv[i]->name); + + // the last entry doesn't have a trailing seperator ";" + if (i < (int)cfg.main.num_of_srv - 1) { + strcat(cfg.main.srv_ent, ";"); + } + } + + fl_g->choice_cfg_act_srv->remove(cfg.selected_srv); + fl_g->choice_cfg_act_srv->redraw(); // Yes we need this :-( + + if (cfg.main.num_of_srv == 0) { + fl_g->button_cfg_edit_srv->deactivate(); + fl_g->button_cfg_del_srv->deactivate(); + fl_g->choice_cfg_act_srv->deactivate(); + free(cfg.main.srv); + } + + if (cfg.selected_srv > 0) { + cfg.selected_srv--; + } + else { + cfg.selected_srv = 0; + } + + if (cfg.main.num_of_srv > 0) { + fl_g->choice_cfg_act_srv->value(cfg.selected_srv); + choice_cfg_act_srv_cb(); + } +} + +void button_cfg_del_icy_cb(void) +{ + int i; + int diff; + + if (cfg.main.num_of_icy == 0) { + return; + } + + if (cfg.icy[cfg.selected_icy]->name != NULL) { + free(cfg.icy[cfg.selected_icy]->name); + } + + if (cfg.icy[cfg.selected_icy]->genre != NULL) { + free(cfg.icy[cfg.selected_icy]->genre); + } + + if (cfg.icy[cfg.selected_icy]->url != NULL) { + free(cfg.icy[cfg.selected_icy]->url); + } + + if (cfg.icy[cfg.selected_icy]->irc != NULL) { + free(cfg.icy[cfg.selected_icy]->irc); + } + + if (cfg.icy[cfg.selected_icy]->icq != NULL) { + free(cfg.icy[cfg.selected_icy]->icq); + } + + if (cfg.icy[cfg.selected_icy]->aim != NULL) { + free(cfg.icy[cfg.selected_icy]->aim); + } + + if (cfg.icy[cfg.selected_icy]->pub != NULL) { + free(cfg.icy[cfg.selected_icy]->pub); + } + + diff = cfg.main.num_of_icy - 1 - cfg.selected_icy; + for (i = 0; i < diff; i++) { + memcpy(cfg.icy[cfg.selected_icy + i], cfg.icy[cfg.selected_icy + i + 1], sizeof(icy_t)); + } + + free(cfg.icy[cfg.main.num_of_icy - 1]); + + cfg.main.num_of_icy--; + + // recreate the string that contains all ICY names + memset(cfg.main.icy_ent, 0, strlen(cfg.main.icy_ent)); + for (i = 0; i < (int)cfg.main.num_of_icy; i++) { + strcat(cfg.main.icy_ent, cfg.icy[i]->name); + + // do not add a trailing seperator ";" to the last entry + if (i < (int)cfg.main.num_of_icy - 1) { + strcat(cfg.main.icy_ent, ";"); + } + } + + fl_g->choice_cfg_act_icy->remove(cfg.selected_icy); + fl_g->choice_cfg_act_icy->redraw(); + + if (cfg.main.num_of_icy == 0) { + fl_g->button_cfg_edit_icy->deactivate(); + fl_g->button_cfg_del_icy->deactivate(); + fl_g->choice_cfg_act_icy->deactivate(); + free(cfg.main.icy); + } + + if (cfg.selected_icy > 0) { + cfg.selected_icy--; + } + else { + cfg.selected_icy = 0; + } + + if (cfg.main.num_of_icy > 0) { + fl_g->choice_cfg_act_icy->value(cfg.selected_icy); + choice_cfg_act_icy_cb(); + } +} + +void button_disconnect_cb(bool ask) +{ + fl_g->label_current_listeners->hide(); + + if (!connected && recording) { + stop_recording(ask); // true = ask user if recording shall be stopped + } + + if (connected && recording && cfg.rec.stop_rec) { + stop_recording(false); // false = do not ask user + } + + if (!recording) { + fl_g->lcd->clear(); + fl_g->lcd->print((const uchar *)_("idle"), strlen(_("idle"))); + fl_g->sponsor_logo->show(); + fl_g->sponsor_logo->redraw(); + } + + // We are not trying to connect anymore + try_to_connect = 0; + disconnect = 1; + + reset_stream_signal_detection_timer(); + + activate_stream_ui_elements(); + + if (!recording) { + Fl::remove_timeout(&display_info_timer); + } + else { + display_info = REC_TIME; + } + + Fl::remove_timeout(&songfile_timer); + Fl::remove_timeout(&app_timer); + Fl::remove_timeout(&is_connected_timer); + Fl::remove_timeout(&reconnect_timer); + Fl::remove_timeout(&song_url_timer); + + if (connected) { + Fl::remove_timeout(&stream_silence_timer); + snd_stop_streaming_thread(); + + if (cfg.srv[cfg.selected_srv]->type == ICECAST) { + ic_disconnect(); + } +#ifdef HAVE_LIBDATACHANNEL + else if (cfg.srv[cfg.selected_srv]->type == WEBRTC) { + webrtc_disconnect(); + } +#endif + else { + sc_disconnect(); + } + + if (strlen(cfg.gui.window_title) == 0) { + fl_g->window_main->label(PACKAGE_STRING); + } + +#ifdef WIN32 + if (tray_agent_is_running(NULL) == 1) { + tray_agent_send_cmd(TA_CONNECT_STATE); + } +#endif + } + + fl_g->button_connect->color(FL_BACKGROUND_COLOR); + fl_g->button_connect->redraw(); + + disconnect = 0; +} + +bool stop_recording(bool ask) +{ + if (!recording) { + return false; + } + + if (ask == true) { + int rc = 0; + rc = fl_choice(_("stop recording?"), _("No"), _("Yes"), NULL); + if (rc == 0) // if NO pressed + return false; + } + + Fl::remove_timeout(&record_silence_timer); + snd_stop_recording_thread(); + + activate_rec_ui_elements(); + if (!connected) { + fl_g->lcd->clear(); + fl_g->lcd->print((const uchar *)_("idle"), strlen(_("idle"))); + fl_g->sponsor_logo->show(); + fl_g->sponsor_logo->redraw(); + Fl::remove_timeout(&display_info_timer); + } + else if (display_info == REC_TIME || display_info == REC_DATA) { + display_info = cfg.gui.default_stream_info; + } + + reset_record_signal_detection_timer(); + + fl_g->button_record->color(FL_BACKGROUND_COLOR); + fl_g->button_record->redraw(); + + return true; +} + +void button_record_cb(bool ask) +{ + char mode[4]; + int rc; + + if (recording) { + stop_recording(true); + return; + } + + if (strlen(cfg.rec.filename) == 0) { + fl_alert(_("No recording filename specified")); + goto not_recording; + } + + if (eval_record_path(0) != 0) { + goto not_recording; + } + + // check if the file already exists + if ((cfg.rec.overwrite_files == false) && (ask == true) && (fl_access(cfg.rec.path, F_OK)) == 0) { + rc = fl_choice(_("%s already exists!"), _("overwrite"), _("cancel"), _("append"), cfg.rec.path); + switch (rc) { + case 0: // overwrite pressed + strcpy(mode, "wb+"); + break; + case 1: // cancel pressed + fl_alert(_("Recording canceled")); + return; + break; + case 2: // append pressed + strcpy(mode, "ab"); + } + } + else { // selected file doesn't exist yet + strcpy(mode, "wb+"); + } + + if ((cfg.rec.fd = fl_fopen(cfg.rec.path, mode)) == NULL) { + fl_alert(_("Could not open:\n%s"), cfg.rec.path); + goto not_recording; + } + + timer_init(&rec_timer, 1.0); + timer_start(&rec_timer); + + // Clear libsamplerate state + snd_reset_samplerate_conv(SND_REC); + + // Allow the flac codec to access the file pointed to by cfg.rec.fd + if (!strcmp(cfg.rec.codec, "flac")) { + flac_enc_init(&flac_rec); + flac_enc_init_FILE(&flac_rec, cfg.rec.fd); + } + + // User may not change any record related audio settings while recording + deactivate_rec_ui_elements(); + + snd_start_recording_thread(); + + if (cfg.rec.split_time > 0) { + split_recording_file_timer(); + } + + reset_record_silence_detection_timer(); + Fl::remove_timeout(&record_signal_timer); + + if (!connected) { + display_info = REC_TIME; + Fl::add_timeout(0.1, &display_info_timer); + } + + fl_g->button_record->color(fl_rgb_color(255, 75, 75)); + fl_g->button_record->redraw(); + + return; + +not_recording: + reset_record_signal_detection_timer(); + return; +} + +void button_info_cb() +{ + if (!fl_g->info_visible) { + // Show info output... + + fl_g->window_main->size_range(fl_g->window_main->w(), 276, fl_g->window_main->w(), 0); + + if (cfg.gui.window_height > fl_g->info_output->y() + 10) { + fl_g->window_main->resize(fl_g->window_main->x(), fl_g->window_main->y(), fl_g->window_main->w(), cfg.gui.window_height); + } + else { + fl_g->window_main->resize(fl_g->window_main->x(), fl_g->window_main->y(), fl_g->window_main->w(), fl_g->info_output->y() + 190); + } + fl_g->info_output->show(); + fl_g->button_info->label(_("Hide log")); + fl_g->info_visible = 1; + } + else { + // Hide info output... + fl_g->window_main->size_range(fl_g->window_main->w(), fl_g->info_output->y() - 25, fl_g->window_main->w(), fl_g->info_output->y() - 25); + fl_g->info_output->hide(); + fl_g->window_main->resize(fl_g->window_main->x(), fl_g->window_main->y(), fl_g->window_main->w(), fl_g->info_output->y() - 25); + fl_g->button_info->label(_("Show log")); + fl_g->info_visible = 0; + } +} + +void choice_cfg_act_srv_cb(void) +{ + cfg.selected_srv = fl_g->choice_cfg_act_srv->value(); + + cfg.main.srv = (char *)realloc(cfg.main.srv, strlen(cfg.srv[cfg.selected_srv]->name) + 1); + + strcpy(cfg.main.srv, cfg.srv[cfg.selected_srv]->name); +} + +void choice_cfg_act_icy_cb(void) +{ + cfg.selected_icy = fl_g->choice_cfg_act_icy->value(); + + cfg.main.icy = (char *)realloc(cfg.main.icy, strlen(cfg.icy[cfg.selected_icy]->name) + 1); + + strcpy(cfg.main.icy, cfg.icy[cfg.selected_icy]->name); +} + +void button_cfg_add_srv_cb(void) +{ + fl_g->window_add_srv->label(_("Add Server")); + fl_g->radio_add_srv_shoutcast->setonly(); + fl_g->input_add_srv_mount->deactivate(); + fl_g->input_add_srv_usr->deactivate(); + + fl_g->check_add_srv_tls->deactivate(); + fl_g->frame_add_srv_tls->deactivate(); + fl_g->button_add_srv_revoke_cert->deactivate(); + fl_g->check_add_srv_protocol->show(); + fl_g->check_add_srv_protocol->deactivate(); + + fl_g->input_add_srv_pwd->input_type(FL_SECRET_INPUT); + fl_g->input_add_srv_pwd->redraw(); + fl_g->button_cfg_show_pw->label(_("Show")); + + fl_g->button_add_srv_save->hide(); + fl_g->button_add_srv_add->show(); + + fl_g->window_add_srv->position(fl_g->window_cfg->x(), fl_g->window_cfg->y()); + fl_g->input_add_srv_name->activate(); + fl_g->input_add_srv_name->take_focus(); + fl_g->window_add_srv->show(); + + fl_g->radio_add_srv_radioco->activate(); + + fl_g->input_add_srv_pwd->show(); + fl_g->input_add_srv_port->show(); + fl_g->input_add_srv_addr->show(); + fl_g->button_cfg_show_pw->show(); + fl_g->input_add_srv_mount->show(); + fl_g->input_add_srv_usr->show(); + fl_g->input_add_srv_listener_url->show(); + fl_g->input_add_srv_listener_mount->show(); + + fl_g->browser_add_srv_station_list->hide(); + fl_g->button_add_srv_get_stations->hide(); + fl_g->button_add_srv_select_all->hide(); + fl_g->button_add_srv_deselect_all->hide(); + + fl_g->input_webrtc_icesrv_url->hide(); + fl_g->input_webrtc_whip_url->hide(); + fl_g->input_webrtc_auth_token->hide(); +} + +void button_cfg_edit_srv_cb(void) +{ + char dummy[10]; + int srv; + + if (cfg.main.num_of_srv < 1) { + return; + } + + fl_g->window_add_srv->label(_("Edit Server")); + + srv = fl_g->choice_cfg_act_srv->value(); + + if (cfg.srv[srv]->type == RADIOCO) { + fl_message(_("Radio.co stations cannot be edited.")); + return; + } + + fl_g->input_add_srv_name->value(cfg.srv[srv]->name); + fl_g->input_add_srv_addr->value(cfg.srv[srv]->addr); + + if (cfg.srv[srv]->custom_listener_url != NULL) { + fl_g->input_add_srv_listener_url->value(cfg.srv[srv]->custom_listener_url); + } + + if (cfg.srv[srv]->custom_listener_mount != NULL) { + fl_g->input_add_srv_listener_mount->value(cfg.srv[srv]->custom_listener_mount); + } + + if (cfg.srv[srv]->type == SHOUTCAST) { + fl_g->radio_add_srv_shoutcast->setonly(); + radio_add_srv_shoutcast_cb(); + } + else if (cfg.srv[srv]->type == ICECAST) { + fl_g->radio_add_srv_icecast->setonly(); + radio_add_srv_icecast_cb(); + } + else if (cfg.srv[srv]->type == WEBRTC) { + fl_g->radio_add_srv_webrtc->setonly(); + radio_add_srv_webrtc_cb(); + } + + snprintf(dummy, 6, "%u", cfg.srv[srv]->port); + fl_g->input_add_srv_port->value(dummy); + fl_g->input_add_srv_pwd->value(cfg.srv[srv]->pwd); + + fl_g->input_add_srv_pwd->input_type(FL_SECRET_INPUT); + fl_g->input_add_srv_pwd->redraw(); + fl_g->button_cfg_show_pw->label(_("Show")); + + fl_g->radio_add_srv_radioco->deactivate(); + + if (cfg.srv[srv]->type == SHOUTCAST) { + fl_g->input_add_srv_mount->value(""); + fl_g->input_add_srv_mount->deactivate(); + fl_g->input_add_srv_usr->value(""); + fl_g->button_add_srv_revoke_cert->deactivate(); + } + else if (cfg.srv[srv]->type == ICECAST) { + fl_g->input_add_srv_mount->value(cfg.srv[srv]->mount); + fl_g->input_add_srv_usr->value(cfg.srv[srv]->usr); + + if ((cfg.srv[srv]->cert_hash != NULL) && (strlen(cfg.srv[srv]->cert_hash) == 64)) { + fl_g->button_add_srv_revoke_cert->activate(); + } + else { + fl_g->button_add_srv_revoke_cert->deactivate(); + } + } + else if (cfg.srv[srv]->type == WEBRTC) { + fl_g->input_add_srv_addr->value(""); + fl_g->input_add_srv_port->value(""); + fl_g->input_add_srv_pwd->value(""); + fl_g->input_add_srv_mount->value(""); + + if (cfg.srv[srv]->webrtc_ice != NULL) { + fl_g->input_webrtc_icesrv_url->value(cfg.srv[srv]->webrtc_ice); + } + + fl_g->input_webrtc_whip_url->value(cfg.srv[srv]->webrtc_whip); + + if (cfg.srv[srv]->webrtc_auth != NULL) { + fl_g->input_webrtc_auth_token->value(cfg.srv[srv]->webrtc_auth); + } + } + + fl_g->check_add_srv_tls->value(cfg.srv[srv]->tls); + fl_g->check_add_srv_protocol->value(cfg.srv[srv]->icecast_protocol); + + fl_g->input_add_srv_name->take_focus(); + + fl_g->button_add_srv_add->hide(); + fl_g->button_add_srv_save->show(); + + fl_g->window_add_srv->position(fl_g->window_cfg->x(), fl_g->window_cfg->y()); + fl_g->window_add_srv->show(); +} + +void button_cfg_add_icy_cb(void) +{ + fl_g->window_add_icy->label(_("Add Server Infos")); + + fl_g->button_add_icy_save->hide(); + fl_g->button_add_icy_add->show(); + fl_g->window_add_icy->position(fl_g->window_cfg->x(), fl_g->window_cfg->y()); + + // give the "name" input field the input focus + fl_g->input_add_icy_name->take_focus(); + + fl_g->window_add_icy->show(); +} + +void update_song(void *user_data) +{ + int prefix_len = 0; + int suffix_len = 0; + char text_buf[512]; + char song_buf[512]; + song_buf[0] = '\0'; + + int (*xc_update_song)(char *song_name) = NULL; + + int called_from_connect_cb; + if (user_data != NULL) { + called_from_connect_cb = *((int *)user_data); + } + else { + called_from_connect_cb = 0; + } + + if (!connected || cfg.main.song == NULL) { + return; + } + + if (cfg.srv[cfg.selected_srv]->type == WEBRTC) { + print_info(_("Song update failed: WebRTC does not support song names"), 0); + return; + } + + // Make sure that song update is not triggered from different places at the same time + if (atom_get_int(&is_updating_song) == 1) { + return; + } + atom_set_int(&is_updating_song, 1); + + if (cfg.main.song_prefix != NULL) { + prefix_len = strlen(cfg.main.song_prefix); + snprintf(song_buf, sizeof(song_buf), "%s", cfg.main.song_prefix); + } + + strncat(song_buf, cfg.main.song, sizeof(song_buf) - 1 - prefix_len); + + if (cfg.main.song_suffix != NULL) { + suffix_len = strlen(cfg.main.song_suffix); + strncat(song_buf, cfg.main.song_suffix, sizeof(song_buf) - 1 - prefix_len - suffix_len); + } + + if (!strcmp(cfg.audio.codec, "flac")) { + if (called_from_connect_cb == 0) { + flac_update_song_title(&flac_stream, song_buf); + } + else { + flac_set_initial_song_title(&flac_stream, song_buf); + } + } + + if (!strcmp(cfg.audio.codec, "opus")) { + opus_update_song_title(&opus_stream, song_buf); + } + + if (cfg.srv[cfg.selected_srv]->type == ICECAST) { + xc_update_song = &ic_update_song; + } + else { // if(cfg.srv[cfg.selected_srv]->type == SHOUTCAST) + xc_update_song = &sc_update_song; + } + + if (xc_update_song(song_buf) == 0) { + snprintf(text_buf, sizeof(text_buf), _("Updated songname to:\n%s\n"), song_buf); + + print_info(text_buf, 0); +#ifdef WIN32 + tray_agent_set_song(song_buf); + tray_agent_send_cmd(TA_SONG_UPDATE); +#endif + } + else { + print_info(_("Updating songname failed"), 1); + } + + atom_set_int(&is_updating_song, 0); +} + +void button_cfg_song_go_cb(void) +{ + cfg.main.song = (char *)realloc(cfg.main.song, strlen(fl_g->input_cfg_song->value()) + 1); + strcpy(cfg.main.song, fl_g->input_cfg_song->value()); + + Fl::add_timeout(cfg.main.song_delay, &update_song); + + // Set focus on the song input field and mark the whole text + fl_g->input_cfg_song->take_focus(); + fl_g->input_cfg_song->position(0); + fl_g->input_cfg_song->mark(fl_g->input_cfg_song->maximum_size()); +} + +void input_cfg_song_cb(void) +{ + if (strlen(fl_g->input_cfg_song->value()) == 0) { + if (cfg.main.song != NULL) { + free(cfg.main.song); + } + + cfg.main.song = NULL; + } +} + +void input_cfg_song_prefix_cb(void) +{ + if (strlen(fl_g->input_cfg_song_prefix->value()) == 0) { + if (cfg.main.song_prefix != NULL) { + free(cfg.main.song_prefix); + } + + cfg.main.song_prefix = NULL; + } + else { + cfg.main.song_prefix = (char *)realloc(cfg.main.song_prefix, strlen(fl_g->input_cfg_song_prefix->value()) + 1); + strcpy(cfg.main.song_prefix, fl_g->input_cfg_song_prefix->value()); + } +} +void input_cfg_song_suffix_cb(void) +{ + if (strlen(fl_g->input_cfg_song_suffix->value()) == 0) { + if (cfg.main.song_suffix != NULL) { + free(cfg.main.song_suffix); + } + + cfg.main.song_suffix = NULL; + } + else { + cfg.main.song_suffix = (char *)realloc(cfg.main.song_suffix, strlen(fl_g->input_cfg_song_suffix->value()) + 1); + strcpy(cfg.main.song_suffix, fl_g->input_cfg_song_suffix->value()); + } +} + +void input_cfg_buffer_cb(bool print_message) +{ + int ms; + char text_buf[256]; + + ms = fl_g->input_cfg_buffer->value(); + + if (ms < 1) { + return; + } + + cfg.audio.buffer_ms = ms; + snd_reopen_streams(); + + if (print_message) { + snprintf(text_buf, sizeof(text_buf), _("Audio buffer has been set to %d ms"), ms); + print_info(text_buf, 0); + } +} + +void choice_cfg_resample_mode_cb(void) +{ + cfg.audio.resample_mode = fl_g->choice_cfg_resample_mode->value(); + snd_reopen_streams(); + switch (cfg.audio.resample_mode) { + case SRC_SINC_BEST_QUALITY: + print_info("Changed resample quality to SINC_BEST_QUALITY", 0); + break; + case SRC_SINC_MEDIUM_QUALITY: + print_info("Changed resample quality to SINC_MEDIUM_QUALITY", 0); + break; + case SRC_SINC_FASTEST: + print_info("Changed resample quality to SINC_FASTEST", 0); + break; + case SRC_ZERO_ORDER_HOLD: + print_info("Changed resample quality to ZERO_ORDER_HOLD", 0); + break; + case SRC_LINEAR: + print_info("Changed resample quality to LINEAR", 0); + break; + default: + break; + } +} + +void radio_add_srv_shoutcast_cb(void) +{ + fl_g->input_add_srv_name->activate(); + + fl_g->input_add_srv_pwd->show(); + fl_g->input_add_srv_port->show(); + fl_g->input_add_srv_addr->show(); + fl_g->button_cfg_show_pw->show(); + + fl_g->input_add_srv_mount->show(); + fl_g->input_add_srv_usr->show(); + fl_g->input_add_srv_mount->deactivate(); + fl_g->input_add_srv_usr->deactivate(); + fl_g->input_add_srv_listener_url->show(); + fl_g->input_add_srv_listener_mount->show(); + fl_g->check_add_srv_tls->deactivate(); + fl_g->frame_add_srv_tls->deactivate(); + fl_g->check_add_srv_protocol->show(); + fl_g->check_add_srv_protocol->deactivate(); + + fl_g->browser_add_srv_station_list->hide(); + fl_g->button_add_srv_get_stations->hide(); + fl_g->button_add_srv_select_all->hide(); + fl_g->button_add_srv_deselect_all->hide(); + + fl_g->input_webrtc_icesrv_url->hide(); + fl_g->input_webrtc_whip_url->hide(); + fl_g->input_webrtc_auth_token->hide(); +} + +void radio_add_srv_icecast_cb(void) +{ + fl_g->input_add_srv_name->activate(); + + fl_g->input_add_srv_pwd->show(); + fl_g->input_add_srv_port->show(); + fl_g->input_add_srv_addr->show(); + fl_g->button_cfg_show_pw->show(); + fl_g->input_add_srv_mount->show(); + fl_g->input_add_srv_usr->show(); + fl_g->input_add_srv_listener_url->show(); + fl_g->input_add_srv_listener_mount->show(); + + fl_g->input_add_srv_mount->activate(); + fl_g->input_add_srv_usr->activate(); + + fl_g->input_add_srv_mount->value("stream"); + fl_g->input_add_srv_usr->value("source"); + +#ifdef HAVE_LIBSSL + fl_g->check_add_srv_tls->activate(); + fl_g->frame_add_srv_tls->activate(); +#else + fl_g->check_add_srv_tls->deactivate(); + fl_g->frame_add_srv_tls->deactivate(); +#endif + + fl_g->check_add_srv_protocol->show(); + fl_g->check_add_srv_protocol->activate(); + + fl_g->browser_add_srv_station_list->hide(); + fl_g->button_add_srv_get_stations->hide(); + fl_g->button_add_srv_select_all->hide(); + fl_g->button_add_srv_deselect_all->hide(); + + fl_g->input_webrtc_icesrv_url->hide(); + fl_g->input_webrtc_whip_url->hide(); + fl_g->input_webrtc_auth_token->hide(); +} + +void radio_add_srv_webrtc_cb(void) +{ + fl_g->input_add_srv_pwd->hide(); + fl_g->input_add_srv_port->hide(); + fl_g->input_add_srv_addr->hide(); + + fl_g->input_add_srv_mount->hide(); + fl_g->input_add_srv_usr->hide(); + fl_g->button_cfg_show_pw->hide(); + + fl_g->input_add_srv_name->activate(); + + fl_g->check_add_srv_tls->deactivate(); + fl_g->frame_add_srv_tls->deactivate(); + + fl_g->check_add_srv_protocol->hide(); + fl_g->check_add_srv_protocol->deactivate(); + + fl_g->browser_add_srv_station_list->hide(); + fl_g->button_add_srv_get_stations->hide(); + fl_g->button_add_srv_select_all->hide(); + fl_g->button_add_srv_deselect_all->hide(); + + fl_g->input_webrtc_icesrv_url->show(); + fl_g->input_webrtc_whip_url->show(); + fl_g->input_webrtc_auth_token->show(); + + fl_g->input_add_srv_listener_url->hide(); + fl_g->input_add_srv_listener_mount->hide(); +} + +void radio_add_srv_radioco_cb(void) +{ + fl_g->input_add_srv_pwd->hide(); + fl_g->input_add_srv_port->hide(); + fl_g->input_add_srv_addr->hide(); + + fl_g->input_add_srv_mount->hide(); + fl_g->input_add_srv_usr->hide(); + fl_g->button_cfg_show_pw->hide(); + + fl_g->input_add_srv_name->deactivate(); + + fl_g->check_add_srv_tls->deactivate(); + fl_g->frame_add_srv_tls->deactivate(); + + fl_g->check_add_srv_protocol->deactivate(); + + fl_g->browser_add_srv_station_list->show(); + fl_g->button_add_srv_get_stations->show(); + fl_g->button_add_srv_select_all->show(); + fl_g->button_add_srv_deselect_all->show(); + + fl_g->input_webrtc_icesrv_url->hide(); + fl_g->input_webrtc_whip_url->hide(); + fl_g->input_webrtc_auth_token->hide(); + + fl_g->input_add_srv_listener_url->hide(); + fl_g->input_add_srv_listener_mount->hide(); +} + +void button_add_srv_get_stations_cb(void) +{ +#ifdef WITH_RADIOCO + if (fl_choice(_("butt will open Radio.co in a new browser window.\n\n" + "Login to Radio.co and allow butt access to your account."), + _("Cancel"), _("OK"), NULL) == 0) { // Cancel + return; + } + + radioco_request_access(); + + Fl::add_timeout(1, &wait_for_radioco_timer); +#endif +} + +void button_add_srv_select_all_cb(void) +{ + fl_g->browser_add_srv_station_list->check_all(); +} +void button_add_srv_deselect_all_cb(void) +{ + fl_g->browser_add_srv_station_list->check_none(); +} + +void button_add_srv_show_pwd_cb(void) +{ + if (fl_g->input_add_srv_pwd->input_type() == FL_SECRET_INPUT) { + fl_g->input_add_srv_pwd->input_type(FL_NORMAL_INPUT); + fl_g->input_add_srv_pwd->redraw(); + fl_g->button_cfg_show_pw->label(_("Hide")); + } + else { + fl_g->input_add_srv_pwd->input_type(FL_SECRET_INPUT); + fl_g->input_add_srv_pwd->redraw(); + fl_g->button_cfg_show_pw->label(_("Show")); + } +} + +void button_add_srv_revoke_cert_cb(void) +{ + int srv; + srv = fl_g->choice_cfg_act_srv->value(); + + if (cfg.srv[srv]->cert_hash != NULL) { + free(cfg.srv[srv]->cert_hash); + cfg.srv[srv]->cert_hash = NULL; + fl_g->button_add_srv_revoke_cert->deactivate(); + } + else { + fl_alert(_("Could not revoke trust for certificate")); + } +} + +// Called if the Save button was pressed after editing a server +void button_add_srv_save_cb(void) +{ + int i; + + if (cfg.main.num_of_srv < 1) { + return; + } + + int srv_num = fl_g->choice_cfg_act_srv->value(); + + // figure out current server type + int server_type; + if (fl_g->radio_add_srv_shoutcast->value()) { + server_type = SHOUTCAST; + } + if (fl_g->radio_add_srv_icecast->value()) { + server_type = ICECAST; + } + if (fl_g->radio_add_srv_webrtc->value()) { + server_type = WEBRTC; + } + + // error checking + const char *listener_url = fl_g->input_add_srv_listener_url->value(); + if (strlen(listener_url) > 0) { + if (strncmp(listener_url, "http://", strlen("http://")) != 0 && strncmp(listener_url, "https://", strlen("https://")) != 0) { + fl_alert(_("The custom listener URL must start with http:// or https://")); + return; + } + } + + if (server_type == ICECAST) { + if (strlen(fl_g->input_add_srv_mount->value()) == 0) { + fl_alert(_("No mountpoint specified\nSetting mountpoint to \"stream\"")); + fl_g->input_add_srv_mount->value("stream"); + } + if (strlen(fl_g->input_add_srv_usr->value()) == 0) { + fl_alert(_("No user specified\nSetting user to \"source\"")); + fl_g->input_add_srv_usr->value("source"); + } + } + + if (strlen(listener_url) > 0) { + if (strstr(listener_url, "/status-json.xsl") == NULL && strstr(listener_url, "/7.xsl") == NULL && // + strstr(listener_url, "/stats?sid") == NULL && strstr(listener_url, "/7.html") == NULL) { + fl_alert(_("Unsupported listener URL.\nThe listener URL must end with status-json.xsl, 7.xsl, 7.html or contain stats?sid")); + return; + } + } + + if (strlen(fl_g->input_add_srv_name->value()) == 0) { + fl_alert(_("No name specified")); + return; + } + if (cfg.main.srv_ent != NULL) { + if (strlen(fl_g->input_add_srv_name->value()) + strlen(cfg.main.srv_ent) > 1000) { + fl_alert(_("The number of characters of all your server names exeeds 1000\n" + "Please reduce the number of characters of each server name")); + return; + } + } + if (strpbrk(fl_g->input_add_srv_name->value(), "[];\\/\n\r") != NULL) { + fl_alert(_("Newline characters and [];/\\ are not allowed within the server name")); + return; + } + if (server_type != WEBRTC) { + if (strlen(fl_g->input_add_srv_addr->value()) == 0) { + fl_alert(_("No address specified")); + return; + } + if (strlen(fl_g->input_add_srv_pwd->value()) == 0) { + fl_alert(_("No password specified")); + return; + } + if (strlen(fl_g->input_add_srv_port->value()) == 0) { + fl_alert(_("No port specified")); + return; + } + else if ((atoi(fl_g->input_add_srv_port->value()) > 65535) || (atoi(fl_g->input_add_srv_port->value()) < 1)) { + fl_alert(_("Invalid port number\nThe port number must be between 1 and 65535")); + return; + } + } + if (server_type == WEBRTC) { + // TODO: validate that the ICE server URL is a valid format for rtcCreatePeerConnection() in libdatachannel + if (strlen(fl_g->input_webrtc_whip_url->value()) == 0) { + fl_alert(_("No WHIP URL specified")); + return; + } + // TODO: validate that the WHIP URL is in valid URL format + } + + // check if the name already exists + for (i = 0; i < cfg.main.num_of_srv; i++) { + if (i == srv_num) // don't check name against it self + continue; + if (!strcmp(fl_g->input_add_srv_name->value(), cfg.srv[i]->name)) { + fl_alert(_("Server name already exist!")); + return; + } + } + + // update current server name + cfg.srv[srv_num]->name = (char *)realloc(cfg.srv[srv_num]->name, sizeof(char) * strlen(fl_g->input_add_srv_name->value()) + 1); + + strcpy(cfg.srv[srv_num]->name, fl_g->input_add_srv_name->value()); + + // rewrite the string that contains all server names + // first get the needed memory space + + int len = 0; + for (int i = 0; i < cfg.main.num_of_srv; i++) { + len += strlen(cfg.srv[i]->name) + 1; + } + // allocate enough memory + cfg.main.srv_ent = (char *)realloc(cfg.main.srv_ent, sizeof(char) * len + 1); + + memset(cfg.main.srv_ent, 0, len); + // now append the server strings + for (int i = 0; i < cfg.main.num_of_srv; i++) { + strcat(cfg.main.srv_ent, cfg.srv[i]->name); + if (i < cfg.main.num_of_srv - 1) { + strcat(cfg.main.srv_ent, ";"); + } + } + + // update current server type + cfg.srv[srv_num]->type = server_type; + + // update current server address + cfg.srv[srv_num]->addr = (char *)realloc(cfg.srv[srv_num]->addr, sizeof(char) * strlen(fl_g->input_add_srv_addr->value()) + 1); + + strcpy(cfg.srv[srv_num]->addr, fl_g->input_add_srv_addr->value()); + + // strip leading http:// from addr + strrpl(&cfg.srv[srv_num]->addr, (char *)"http://", (char *)"", MODE_ALL); + strrpl(&cfg.srv[srv_num]->addr, (char *)"https://", (char *)"", MODE_ALL); + + // update current server port + cfg.srv[srv_num]->port = (unsigned int)atoi(fl_g->input_add_srv_port->value()); + + // update current server password + cfg.srv[srv_num]->pwd = (char *)realloc(cfg.srv[srv_num]->pwd, strlen(fl_g->input_add_srv_pwd->value()) + 1); + + strcpy(cfg.srv[srv_num]->pwd, fl_g->input_add_srv_pwd->value()); + + // update current server mountpoint and user + if (cfg.srv[srv_num]->type == ICECAST) { + cfg.srv[srv_num]->mount = (char *)realloc(cfg.srv[srv_num]->mount, sizeof(char) * strlen(fl_g->input_add_srv_mount->value()) + 1); + strcpy(cfg.srv[srv_num]->mount, fl_g->input_add_srv_mount->value()); + + cfg.srv[srv_num]->usr = (char *)realloc(cfg.srv[srv_num]->usr, sizeof(char) * strlen(fl_g->input_add_srv_usr->value()) + 1); + strcpy(cfg.srv[srv_num]->usr, fl_g->input_add_srv_usr->value()); + + cfg.srv[srv_num]->icecast_protocol = fl_g->check_add_srv_protocol->value(); + } + + cfg.srv[srv_num]->tls = fl_g->check_add_srv_tls->value(); + + // update the current webrtc urls + if (cfg.srv[srv_num]->type == WEBRTC) { + cfg.srv[srv_num]->webrtc_ice = (char *)realloc(cfg.srv[srv_num]->webrtc_ice, sizeof(char) * strlen(fl_g->input_webrtc_icesrv_url->value()) + 1); + strcpy(cfg.srv[srv_num]->webrtc_ice, fl_g->input_webrtc_icesrv_url->value()); + + cfg.srv[srv_num]->webrtc_whip = (char *)realloc(cfg.srv[srv_num]->webrtc_whip, sizeof(char) * strlen(fl_g->input_webrtc_whip_url->value()) + 1); + strcpy(cfg.srv[srv_num]->webrtc_whip, fl_g->input_webrtc_whip_url->value()); + + cfg.srv[srv_num]->webrtc_auth = (char *)realloc(cfg.srv[srv_num]->webrtc_auth, sizeof(char) * strlen(fl_g->input_webrtc_auth_token->value()) + 1); + strcpy(cfg.srv[srv_num]->webrtc_auth, fl_g->input_webrtc_auth_token->value()); + } + + cfg.srv[srv_num]->custom_listener_url = + (char *)realloc(cfg.srv[srv_num]->custom_listener_url, sizeof(char) * strlen(fl_g->input_add_srv_listener_url->value()) + 1); + strcpy(cfg.srv[srv_num]->custom_listener_url, fl_g->input_add_srv_listener_url->value()); + + cfg.srv[srv_num]->custom_listener_mount = + (char *)realloc(cfg.srv[srv_num]->custom_listener_mount, sizeof(char) * strlen(fl_g->input_add_srv_listener_mount->value()) + 1); + strcpy(cfg.srv[srv_num]->custom_listener_mount, fl_g->input_add_srv_listener_mount->value()); + + fl_g->choice_cfg_act_srv->replace(srv_num, cfg.srv[srv_num]->name); + fl_g->choice_cfg_act_srv->redraw(); + + // reset the input fields and hide the window + fl_g->input_add_srv_name->value(""); + fl_g->input_add_srv_addr->value(""); + fl_g->input_add_srv_port->value(""); + fl_g->input_add_srv_pwd->value(""); + fl_g->input_add_srv_mount->value(""); + fl_g->input_add_srv_usr->value(""); + fl_g->check_add_srv_tls->value(0); + fl_g->input_add_srv_listener_url->value(""); + fl_g->input_add_srv_listener_mount->value(""); + fl_g->check_add_srv_protocol->value(ICECAST_PROTOCOL_PUT); + fl_g->input_webrtc_icesrv_url->value(""); + fl_g->input_webrtc_whip_url->value(""); + fl_g->input_webrtc_auth_token->value(""); + + fl_g->window_add_srv->hide(); + + choice_cfg_act_srv_cb(); +} + +void button_add_icy_save_cb(void) +{ + int i; + + if (cfg.main.num_of_icy < 1) { + return; + } + + int icy_num = fl_g->choice_cfg_act_icy->value(); + int len = 0; + + if (strlen(fl_g->input_add_icy_name->value()) == 0) { + fl_alert(_("No name specified")); + return; + } + if (cfg.main.icy_ent != NULL) { + if (strlen(fl_g->input_add_icy_name->value()) + strlen(cfg.main.icy_ent) > 1000) { + fl_alert(_("The number of characters of all your icy names exeeds 1000\n" + "Please reduce the count of characters of each icy name")); + return; + } + } + if (strpbrk(fl_g->input_add_icy_name->value(), "[];\\/\n\r") != NULL) { + fl_alert(_("Newline characters and [];/\\ are not allowed within the icy name")); + return; + } + + // check if the name already exists + for (i = 0; i < cfg.main.num_of_icy; i++) { + if (i == icy_num) // don't check name against it self + continue; + if (!strcmp(fl_g->input_add_icy_name->value(), cfg.icy[i]->name)) { + fl_alert(_("Icy name already exist!")); + return; + } + } + + // update current icy name + cfg.icy[icy_num]->name = (char *)realloc(cfg.icy[icy_num]->name, sizeof(char) * strlen(fl_g->input_add_icy_name->value()) + 1); + + strcpy(cfg.icy[icy_num]->name, fl_g->input_add_icy_name->value()); + + // rewrite the string that contains all server names + // first get the needed memory space + for (int i = 0; i < cfg.main.num_of_icy; i++) + len += strlen(cfg.icy[i]->name) + 1; + // reserve enough memory + cfg.main.icy_ent = (char *)realloc(cfg.main.icy_ent, sizeof(char) * len + 1); + + memset(cfg.main.icy_ent, 0, len); + // now append the server strings + for (int i = 0; i < cfg.main.num_of_icy; i++) { + strcat(cfg.main.icy_ent, cfg.icy[i]->name); + if (i < cfg.main.num_of_icy - 1) { + strcat(cfg.main.icy_ent, ";"); + } + } + + cfg.icy[icy_num]->desc = (char *)realloc(cfg.icy[icy_num]->desc, strlen(fl_g->input_add_icy_desc->value()) + 1); + strcpy(cfg.icy[icy_num]->desc, fl_g->input_add_icy_desc->value()); + + cfg.icy[icy_num]->genre = (char *)realloc(cfg.icy[icy_num]->genre, strlen(fl_g->input_add_icy_genre->value()) + 1); + strcpy(cfg.icy[icy_num]->genre, fl_g->input_add_icy_genre->value()); + + cfg.icy[icy_num]->url = (char *)realloc(cfg.icy[icy_num]->url, strlen(fl_g->input_add_icy_url->value()) + 1); + strcpy(cfg.icy[icy_num]->url, fl_g->input_add_icy_url->value()); + + cfg.icy[icy_num]->icq = (char *)realloc(cfg.icy[icy_num]->icq, strlen(fl_g->input_add_icy_icq->value()) + 1); + strcpy(cfg.icy[icy_num]->icq, fl_g->input_add_icy_icq->value()); + + cfg.icy[icy_num]->irc = (char *)realloc(cfg.icy[icy_num]->irc, strlen(fl_g->input_add_icy_irc->value()) + 1); + strcpy(cfg.icy[icy_num]->irc, fl_g->input_add_icy_irc->value()); + + cfg.icy[icy_num]->aim = (char *)realloc(cfg.icy[icy_num]->aim, strlen(fl_g->input_add_icy_aim->value()) + 1); + strcpy(cfg.icy[icy_num]->aim, fl_g->input_add_icy_aim->value()); + + sprintf(cfg.icy[icy_num]->pub, "%d", fl_g->check_add_icy_pub->value()); + + cfg.icy[icy_num]->expand_variables = fl_g->check_expand_variables->value(); + + fl_g->input_add_icy_name->value(""); + fl_g->input_add_icy_desc->value(""); + fl_g->input_add_icy_url->value(""); + fl_g->input_add_icy_genre->value(""); + fl_g->input_add_icy_irc->value(""); + fl_g->input_add_icy_icq->value(""); + fl_g->input_add_icy_aim->value(""); + fl_g->check_add_icy_pub->value(0); + fl_g->check_expand_variables->value(0); + + fl_g->window_add_icy->hide(); + + fl_g->choice_cfg_act_icy->replace(icy_num, cfg.icy[icy_num]->name); + fl_g->choice_cfg_act_icy->redraw(); + choice_cfg_act_icy_cb(); +} + +/* +void choice_cfg_edit_srv_cb(void) +{ + char dummy[10]; + int server = fl_g->choice_cfg_edit_srv->value(); + + fl_g->input_cfg_addr->value(cfg.srv[server]->addr); + + snprintf(dummy, 6, "%u", cfg.srv[server]->port); + fl_g->input_cfg_port->value(dummy); + fl_g->input_cfg_passwd->value(cfg.srv[server]->pwd); + + if(cfg.srv[server]->type == SHOUTCAST) { + fl_g->input_cfg_mount->value(""); + fl_g->input_cfg_mount->deactivate(); + fl_g->radio_cfg_shoutcast->value(1); + fl_g->radio_cfg_icecast->value(0); + } + else //if(cfg.srv[server]->type == ICECAST) + { + fl_g->input_cfg_mount->value(cfg.srv[server]->mount); + fl_g->input_cfg_mount->activate(); + fl_g->radio_cfg_icecast->value(1); + fl_g->radio_cfg_shoutcast->value(0); + } +} +*/ + +void choice_cfg_bitrate_cb(void) +{ + int rc; + int old_br; + int sel_br; + int codec_idx; + int num_of_bitrates; + int *br_list; + char text_buf[256]; + + codec_idx = fl_g->choice_cfg_codec->value(); + num_of_bitrates = get_bitrate_list_for_codec(codec_idx, &br_list); + + old_br = cfg.audio.bitrate; + for (int i = 0; i < num_of_bitrates; i++) { + if (br_list[i] == cfg.audio.bitrate) { + old_br = i; + } + } + + sel_br = fl_g->choice_cfg_bitrate->value(); + cfg.audio.bitrate = br_list[sel_br]; + lame_stream.bitrate = br_list[sel_br]; + vorbis_stream.bitrate = br_list[sel_br]; +#ifdef HAVE_LIBFDK_AAC + aac_stream.bitrate = br_list[sel_br]; +#endif + opus_stream.bitrate = br_list[sel_br] * 1000; + + if (codec_idx == CHOICE_MP3) { + rc = lame_enc_reinit(&lame_stream); + if (rc != 0) { + print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1); + fl_g->choice_cfg_bitrate->value(old_br); + fl_g->choice_cfg_bitrate->redraw(); + cfg.audio.bitrate = br_list[old_br]; + lame_stream.bitrate = br_list[old_br]; + lame_enc_reinit(&lame_stream); + print_info(_("The previous values have been set\n"), 1); + return; + } + } + if (codec_idx == CHOICE_OGG) { + rc = vorbis_enc_reinit(&vorbis_stream); + if (rc != 0) { + print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1); + cfg.audio.bitrate = br_list[old_br]; + vorbis_stream.bitrate = br_list[old_br]; + fl_g->choice_cfg_bitrate->value(old_br); + fl_g->choice_cfg_bitrate->redraw(); + vorbis_enc_reinit(&vorbis_stream); + print_info(_("The previous values have been set\n"), 1); + return; + } + } + + if (codec_idx == CHOICE_OPUS) { + rc = opus_enc_reinit(&opus_stream); + if (rc != 0) { + print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1); + cfg.audio.bitrate = br_list[old_br]; + opus_stream.bitrate = br_list[old_br] * 1000; + fl_g->choice_cfg_bitrate->value(old_br); + fl_g->choice_cfg_bitrate->redraw(); + opus_enc_reinit(&opus_stream); + print_info(_("The previous values have been set\n"), 1); + return; + } + } + +#ifdef HAVE_LIBFDK_AAC + if (codec_idx == CHOICE_AAC) { + rc = aac_enc_reinit(&aac_stream); + if (rc != 0) { + print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1); + cfg.audio.bitrate = br_list[old_br]; + aac_stream.bitrate = br_list[old_br]; + fl_g->choice_cfg_bitrate->value(old_br); + fl_g->choice_cfg_bitrate->redraw(); + aac_enc_reinit(&aac_stream); + print_info(_("The previous values have been set\n"), 1); + return; + } + } +#endif + + snprintf(text_buf, sizeof(text_buf), _("Stream bitrate set to: %dk"), cfg.audio.bitrate); + print_info(text_buf, 0); +} + +void button_stream_codec_settings_cb(void) +{ + fl_g->window_stream_codec_settings->position(fl_g->window_cfg->x(), fl_g->window_cfg->y()); + + switch (fl_g->choice_cfg_codec->value()) { + case CHOICE_MP3: + fl_g->tabs_stream_codec_settings->value(fl_g->tab_stream_mp3); + break; + case CHOICE_OGG: + fl_g->tabs_stream_codec_settings->value(fl_g->tab_stream_ogg); + break; + case CHOICE_OPUS: + fl_g->tabs_stream_codec_settings->value(fl_g->tab_stream_opus); + break; + case CHOICE_AAC: + fl_g->tabs_stream_codec_settings->value(fl_g->tab_stream_aac); + break; + case CHOICE_FLAC: + fl_g->tabs_stream_codec_settings->value(fl_g->tab_stream_flac); + break; + } + fl_g->window_stream_codec_settings->show(); +} + +void button_rec_codec_settings_cb(void) +{ + fl_g->window_rec_codec_settings->position(fl_g->window_cfg->x(), fl_g->window_cfg->y()); + switch (fl_g->choice_rec_codec->value()) { + case CHOICE_MP3: + fl_g->tabs_rec_codec_settings->value(fl_g->tab_rec_mp3); + break; + case CHOICE_OGG: + fl_g->tabs_rec_codec_settings->value(fl_g->tab_rec_ogg); + break; + case CHOICE_OPUS: + fl_g->tabs_rec_codec_settings->value(fl_g->tab_rec_opus); + break; + case CHOICE_AAC: + fl_g->tabs_rec_codec_settings->value(fl_g->tab_rec_aac); + break; + case CHOICE_FLAC: + fl_g->tabs_rec_codec_settings->value(fl_g->tab_rec_flac); + break; + case CHOICE_WAV: + fl_g->tabs_rec_codec_settings->value(fl_g->tab_rec_wav); + break; + } + fl_g->window_rec_codec_settings->show(); +} + +void choice_rec_bitrate_cb(void) +{ + int rc; + int old_br; + int sel_br; + int codec_idx; + int num_of_bitrates; + int *br_list; + char text_buf[256]; + + codec_idx = fl_g->choice_rec_codec->value(); + num_of_bitrates = get_bitrate_list_for_codec(codec_idx, &br_list); + + old_br = cfg.rec.bitrate; + for (int i = 0; i < num_of_bitrates; i++) { + if (br_list[i] == cfg.rec.bitrate) { + old_br = i; + } + } + + sel_br = fl_g->choice_rec_bitrate->value(); + cfg.rec.bitrate = br_list[sel_br]; + lame_rec.bitrate = br_list[sel_br]; + vorbis_rec.bitrate = br_list[sel_br]; + opus_rec.bitrate = br_list[sel_br] * 1000; +#ifdef HAVE_LIBFDK_AAC + aac_rec.bitrate = br_list[sel_br]; +#endif + + if (fl_g->choice_rec_codec->value() == CHOICE_MP3) { + rc = lame_enc_reinit(&lame_rec); + if (rc != 0) { + print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1); + cfg.rec.bitrate = br_list[old_br]; + fl_g->choice_rec_bitrate->value(old_br); + fl_g->choice_rec_bitrate->redraw(); + lame_rec.bitrate = br_list[old_br]; + lame_enc_reinit(&lame_rec); + print_info(_("The previous values have been set"), 1); + return; + } + } + if (fl_g->choice_rec_codec->value() == CHOICE_OGG) { + rc = vorbis_enc_reinit(&vorbis_rec); + if (rc != 0) { + print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1); + cfg.rec.bitrate = br_list[old_br]; + vorbis_rec.bitrate = br_list[old_br]; + fl_g->choice_rec_bitrate->value(old_br); + fl_g->choice_rec_bitrate->redraw(); + vorbis_enc_reinit(&vorbis_rec); + print_info(_("The previous values have been set"), 1); + return; + } + } + + if (fl_g->choice_rec_codec->value() == CHOICE_OPUS) { + rc = opus_enc_reinit(&opus_rec); + if (rc != 0) { + print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1); + cfg.rec.bitrate = br_list[old_br]; + opus_rec.bitrate = br_list[old_br] * 1000; + fl_g->choice_rec_bitrate->value(old_br); + fl_g->choice_rec_bitrate->redraw(); + opus_enc_reinit(&opus_rec); + print_info(_("The previous values have been set"), 1); + return; + } + } + +#ifdef HAVE_LIBFDK_AAC + if (fl_g->choice_rec_codec->value() == CHOICE_AAC) { + rc = aac_enc_reinit(&aac_rec); + if (rc != 0) { + print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1); + cfg.rec.bitrate = br_list[old_br]; + aac_rec.bitrate = br_list[old_br]; + fl_g->choice_rec_bitrate->value(old_br); + fl_g->choice_rec_bitrate->redraw(); + aac_enc_reinit(&aac_rec); + print_info(_("The previous values have been set"), 1); + return; + } + } +#endif + + snprintf(text_buf, sizeof(text_buf), _("Record bitrate set to: %dk"), cfg.rec.bitrate); + print_info(text_buf, 0); +} + +void choice_cfg_samplerate_cb() +{ + int rc; + int old_sr; + int sel_sr; + int *sr_list; + char text_buf[256]; + + sr_list = cfg.audio.pcm_list[cfg.audio.dev_num]->sr_list; + old_sr = cfg.audio.samplerate; + + for (int i = 0; sr_list[i] != 0; i++) { + if (sr_list[i] == cfg.audio.samplerate) { + old_sr = i; + } + } + + sel_sr = fl_g->choice_cfg_samplerate->value(); + + cfg.audio.samplerate = sr_list[sel_sr]; + + // Reinit streaming codecs + lame_stream.samplerate_in = sr_list[sel_sr]; + vorbis_stream.samplerate = sr_list[sel_sr]; + opus_stream.samplerate = sr_list[sel_sr]; +#ifdef HAVE_LIBFDK_AAC + aac_stream.samplerate = sr_list[sel_sr]; +#endif + flac_stream.samplerate = sr_list[sel_sr]; + + if (fl_g->choice_cfg_codec->value() == CHOICE_MP3) { + rc = lame_enc_reinit(&lame_stream); + if (rc != 0) { + print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1); + fl_g->choice_cfg_samplerate->value(old_sr); + fl_g->choice_cfg_samplerate->redraw(); + cfg.audio.samplerate = sr_list[old_sr]; + lame_stream.samplerate_in = sr_list[old_sr]; + lame_enc_reinit(&lame_stream); + print_info(_("The previous values have been set"), 1); + return; + } + } + if (fl_g->choice_cfg_codec->value() == CHOICE_OGG) { + rc = vorbis_enc_reinit(&vorbis_stream); + if (rc != 0) { + print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1); + cfg.audio.samplerate = sr_list[old_sr]; + vorbis_stream.samplerate = sr_list[old_sr]; + fl_g->choice_cfg_samplerate->value(old_sr); + fl_g->choice_cfg_samplerate->redraw(); + vorbis_enc_reinit(&vorbis_stream); + print_info(_("The previous values have been set"), 1); + return; + } + } + + if (fl_g->choice_cfg_codec->value() == CHOICE_OPUS) { + rc = opus_enc_reinit(&opus_stream); + if (rc != 0) { + print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1); + cfg.audio.samplerate = sr_list[old_sr]; + opus_stream.samplerate = sr_list[old_sr]; + fl_g->choice_cfg_samplerate->value(old_sr); + fl_g->choice_cfg_samplerate->redraw(); + opus_enc_reinit(&opus_stream); + print_info(_("The previous values have been set"), 1); + return; + } + } + +#ifdef HAVE_LIBFDK_AAC + if (fl_g->choice_cfg_codec->value() == CHOICE_AAC) { + rc = aac_enc_reinit(&aac_stream); + if (rc != 0) { + print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1); + cfg.audio.samplerate = sr_list[old_sr]; + aac_stream.samplerate = sr_list[old_sr]; + fl_g->choice_cfg_samplerate->value(old_sr); + fl_g->choice_cfg_samplerate->redraw(); + aac_enc_reinit(&aac_stream); + print_info(_("The previous values have been set"), 1); + return; + } + } +#endif + + if (fl_g->choice_cfg_codec->value() == CHOICE_FLAC) { + rc = flac_enc_reinit(&flac_stream); + if (rc != 0) { + print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1); + cfg.audio.samplerate = sr_list[old_sr]; + flac_stream.samplerate = sr_list[old_sr]; + fl_g->choice_cfg_samplerate->value(old_sr); + fl_g->choice_cfg_samplerate->redraw(); + flac_enc_reinit(&flac_stream); + print_info(_("The previous values have been set"), 1); + return; + } + } + + // Reinit record codecs + lame_rec.samplerate_in = sr_list[sel_sr]; + vorbis_rec.samplerate = sr_list[sel_sr]; + opus_rec.samplerate = sr_list[sel_sr]; +#ifdef HAVE_LIBFDK_AAC + aac_rec.samplerate = sr_list[sel_sr]; +#endif + flac_rec.samplerate = sr_list[sel_sr]; + + if (fl_g->choice_rec_codec->value() == CHOICE_MP3) { + rc = lame_enc_reinit(&lame_rec); + if (rc != 0) { + print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1); + cfg.audio.samplerate = sr_list[old_sr]; + lame_rec.samplerate_in = sr_list[old_sr]; + fl_g->choice_cfg_samplerate->value(old_sr); + fl_g->choice_cfg_samplerate->redraw(); + lame_enc_reinit(&lame_rec); + print_info(_("The previous values have been set"), 1); + return; + } + } + if (fl_g->choice_rec_codec->value() == CHOICE_OGG) { + rc = vorbis_enc_reinit(&vorbis_rec); + if (rc != 0) { + print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1); + cfg.audio.samplerate = sr_list[old_sr]; + vorbis_rec.samplerate = sr_list[old_sr]; + fl_g->choice_cfg_samplerate->value(old_sr); + fl_g->choice_cfg_samplerate->redraw(); + vorbis_enc_reinit(&vorbis_rec); + print_info(_("The previous values have been set"), 1); + return; + } + } + + if (fl_g->choice_rec_codec->value() == CHOICE_OPUS) { + rc = opus_enc_reinit(&opus_rec); + if (rc != 0) { + print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1); + cfg.audio.samplerate = sr_list[old_sr]; + opus_rec.samplerate = sr_list[old_sr]; + fl_g->choice_cfg_samplerate->value(old_sr); + fl_g->choice_cfg_samplerate->redraw(); + opus_enc_reinit(&opus_rec); + print_info(_("The previous values have been set"), 1); + return; + } + } + +#ifdef HAVE_LIBFDK_AAC + if (fl_g->choice_rec_codec->value() == CHOICE_AAC) { + rc = aac_enc_reinit(&aac_rec); + if (rc != 0) { + print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1); + cfg.audio.samplerate = sr_list[old_sr]; + aac_rec.samplerate = sr_list[old_sr]; + fl_g->choice_cfg_samplerate->value(old_sr); + fl_g->choice_cfg_samplerate->redraw(); + aac_enc_reinit(&aac_rec); + print_info(_("The previous values have been set"), 1); + return; + } + } +#endif + if (fl_g->choice_rec_codec->value() == CHOICE_FLAC) { + rc = flac_enc_reinit(&flac_rec); + if (rc != 0) { + print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1); + cfg.audio.samplerate = sr_list[old_sr]; + flac_rec.samplerate = sr_list[old_sr]; + fl_g->choice_cfg_samplerate->value(old_sr); + fl_g->choice_cfg_samplerate->redraw(); + flac_enc_reinit(&flac_rec); + print_info(_("The previous values have been set"), 1); + return; + } + } + + // The buffer size is dependand on the samplerate + input_cfg_buffer_cb(0); + + snprintf(text_buf, sizeof(text_buf), _("Samplerate set to: %dHz"), cfg.audio.samplerate); + print_info(text_buf, 0); + + snd_reopen_streams(); +} + +void choice_cfg_channel_stereo_cb(void) +{ + cfg.audio.channel = 2; + + // Reinit streaming codecs + lame_stream.channel = 2; + vorbis_stream.channel = 2; + opus_stream.channel = 2; +#ifdef HAVE_LIBFDK_AAC + aac_stream.channel = 2; +#endif + flac_stream.channel = 2; + + if (fl_g->choice_cfg_codec->value() == CHOICE_MP3) { + lame_enc_reinit(&lame_stream); + } + if (fl_g->choice_cfg_codec->value() == CHOICE_OGG) { + vorbis_enc_reinit(&vorbis_stream); + } + if (fl_g->choice_cfg_codec->value() == CHOICE_OPUS) { + opus_enc_reinit(&opus_stream); + } +#ifdef HAVE_LIBFDK_AAC + if (fl_g->choice_cfg_codec->value() == CHOICE_AAC) { + aac_enc_reinit(&aac_stream); + } +#endif + if (fl_g->choice_cfg_codec->value() == CHOICE_FLAC) { + flac_enc_reinit(&flac_stream); + } + + // Reinit recording codecs + lame_rec.channel = 2; + vorbis_rec.channel = 2; + opus_rec.channel = 2; +#ifdef HAVE_LIBFDK_AAC + aac_rec.channel = 2; +#endif + flac_rec.channel = 2; + + if (fl_g->choice_rec_codec->value() == CHOICE_MP3) { + lame_enc_reinit(&lame_rec); + } + if (fl_g->choice_rec_codec->value() == CHOICE_OGG) { + vorbis_enc_reinit(&vorbis_rec); + } + if (fl_g->choice_rec_codec->value() == CHOICE_OPUS) { + opus_enc_reinit(&opus_rec); + } +#ifdef HAVE_LIBFDK_AAC + if (fl_g->choice_rec_codec->value() == CHOICE_AAC) { + aac_enc_reinit(&aac_rec); + } +#endif + if (fl_g->choice_rec_codec->value() == CHOICE_FLAC) { + flac_enc_reinit(&flac_rec); + } + + snd_reopen_streams(); + + print_info(_("Channels set to: stereo"), 0); +} + +void choice_cfg_channel_mono_cb(void) +{ + cfg.audio.channel = 1; + + // Reinit streaming codecs + lame_stream.channel = 1; + vorbis_stream.channel = 1; + opus_stream.channel = 1; +#ifdef HAVE_LIBFDK_AAC + aac_stream.channel = 1; +#endif + flac_stream.channel = 1; + + if (fl_g->choice_cfg_codec->value() == CHOICE_MP3) { + lame_enc_reinit(&lame_stream); + } + if (fl_g->choice_cfg_codec->value() == CHOICE_OGG) { + vorbis_enc_reinit(&vorbis_stream); + } + if (fl_g->choice_cfg_codec->value() == CHOICE_OPUS) { + opus_enc_reinit(&opus_stream); + } +#ifdef HAVE_LIBFDK_AAC + if (fl_g->choice_cfg_codec->value() == CHOICE_AAC) { + aac_enc_reinit(&aac_stream); + } +#endif + if (fl_g->choice_cfg_codec->value() == CHOICE_FLAC) { + flac_enc_reinit(&flac_stream); + } + + // Reinit recording codecs + lame_rec.channel = 1; + vorbis_rec.channel = 1; + opus_rec.channel = 1; +#ifdef HAVE_LIBFDK_AAC + aac_rec.channel = 1; +#endif + flac_rec.channel = 1; + + if (fl_g->choice_rec_codec->value() == CHOICE_MP3) { + lame_enc_reinit(&lame_rec); + } + if (fl_g->choice_rec_codec->value() == CHOICE_OGG) { + vorbis_enc_reinit(&vorbis_rec); + } + if (fl_g->choice_rec_codec->value() == CHOICE_OPUS) { + opus_enc_reinit(&opus_rec); + } +#ifdef HAVE_LIBFDK_AAC + if (fl_g->choice_rec_codec->value() == CHOICE_AAC) { + aac_enc_reinit(&aac_rec); + } +#endif + if (fl_g->choice_rec_codec->value() == CHOICE_FLAC) { + flac_enc_reinit(&flac_rec); + } + + snd_reopen_streams(); + + print_info(_("Channels set to: mono"), 0); +} + +void button_add_srv_cancel_cb(void) +{ +#ifdef WITH_RADIOCO + if (radioco_get_state() == RADIOCO_STATE_WAITING) { + radioco_cancel(); + } +#endif + + fl_g->input_add_srv_name->value(""); + fl_g->input_add_srv_addr->value(""); + fl_g->input_add_srv_port->value(""); + fl_g->input_add_srv_pwd->value(""); + fl_g->input_add_srv_mount->value(""); + fl_g->input_add_srv_usr->value(""); + fl_g->input_add_srv_listener_url->value(""); + fl_g->input_add_srv_listener_mount->value(""); + fl_g->input_webrtc_icesrv_url->value(""); + fl_g->input_webrtc_whip_url->value(""); + fl_g->input_webrtc_auth_token->value(""); + fl_g->check_add_srv_tls->value(0); + fl_g->check_add_srv_protocol->value(ICECAST_PROTOCOL_PUT); + fl_g->browser_add_srv_station_list->clear(); + fl_g->window_add_srv->hide(); +} + +void button_add_icy_add_cb(void) +{ + int i; + // error checking + if (strlen(fl_g->input_add_icy_name->value()) == 0) { + fl_alert(_("No name specified")); + return; + } + + if (cfg.main.icy_ent != NULL) { + if (strlen(fl_g->input_add_icy_name->value()) + strlen(cfg.main.icy_ent) > 1000) { + fl_alert(_("The number of characters of all your icy names exeeds 1000\n" + "Please reduce the number of characters of each icy name")); + return; + } + } + if (strpbrk(fl_g->input_add_icy_name->value(), "[];\\/\n\r") != NULL) { + fl_alert(_("Newline characters and [];/\\ are not allowed within the icy name")); + return; + } + + // check if the name already exists + for (i = 0; i < cfg.main.num_of_icy; i++) { + if (!strcmp(fl_g->input_add_icy_name->value(), cfg.icy[i]->name)) { + fl_alert(_("Server name already exist!")); + return; + } + } + + i = cfg.main.num_of_icy; + cfg.main.num_of_icy++; + + cfg.icy = (icy_t **)realloc(cfg.icy, cfg.main.num_of_icy * sizeof(icy_t *)); + cfg.icy[i] = (icy_t *)malloc(sizeof(icy_t)); + + cfg.icy[i]->name = (char *)malloc(strlen(fl_g->input_add_icy_name->value()) + 1); + strcpy(cfg.icy[i]->name, fl_g->input_add_icy_name->value()); + + cfg.icy[i]->desc = (char *)malloc(strlen(fl_g->input_add_icy_desc->value()) + 1); + strcpy(cfg.icy[i]->desc, fl_g->input_add_icy_desc->value()); + + cfg.icy[i]->url = (char *)malloc(strlen(fl_g->input_add_icy_url->value()) + 1); + strcpy(cfg.icy[i]->url, fl_g->input_add_icy_url->value()); + + cfg.icy[i]->genre = (char *)malloc(strlen(fl_g->input_add_icy_genre->value()) + 1); + strcpy(cfg.icy[i]->genre, fl_g->input_add_icy_genre->value()); + + cfg.icy[i]->irc = (char *)malloc(strlen(fl_g->input_add_icy_irc->value()) + 1); + strcpy(cfg.icy[i]->irc, fl_g->input_add_icy_irc->value()); + + cfg.icy[i]->icq = (char *)malloc(strlen(fl_g->input_add_icy_icq->value()) + 1); + strcpy(cfg.icy[i]->icq, fl_g->input_add_icy_icq->value()); + + cfg.icy[i]->aim = (char *)malloc(strlen(fl_g->input_add_icy_aim->value()) + 1); + strcpy(cfg.icy[i]->aim, fl_g->input_add_icy_aim->value()); + + cfg.icy[i]->pub = (char *)malloc(16 * sizeof(char)); + snprintf(cfg.icy[i]->pub, 15, "%d", fl_g->check_add_icy_pub->value()); + + if (cfg.main.num_of_icy > 1) { + cfg.main.icy_ent = (char *)realloc(cfg.main.icy_ent, strlen(cfg.main.icy_ent) + strlen(cfg.icy[i]->name) + 2); + sprintf(cfg.main.icy_ent + strlen(cfg.main.icy_ent), ";%s", cfg.icy[i]->name); + cfg.main.icy = (char *)realloc(cfg.main.icy, strlen(cfg.icy[i]->name) + 1); + } + else { + cfg.main.icy_ent = (char *)malloc(strlen(cfg.icy[i]->name) + 1); + sprintf(cfg.main.icy_ent, "%s", cfg.icy[i]->name); + cfg.main.icy = (char *)malloc(strlen(cfg.icy[i]->name) + 1); + } + strcpy(cfg.main.icy, cfg.icy[i]->name); + + cfg.icy[i]->expand_variables = fl_g->check_expand_variables->value(); + + fl_g->input_add_icy_name->value(""); + fl_g->input_add_icy_desc->value(""); + fl_g->input_add_icy_url->value(""); + fl_g->input_add_icy_genre->value(""); + fl_g->input_add_icy_irc->value(""); + fl_g->input_add_icy_icq->value(""); + fl_g->input_add_icy_aim->value(""); + fl_g->check_add_icy_pub->value(0); + fl_g->check_expand_variables->value(0); + + fl_g->window_add_icy->hide(); + + fl_g->choice_cfg_act_icy->add(cfg.icy[i]->name); + fl_g->choice_cfg_act_icy->redraw(); + + fl_g->button_cfg_edit_icy->activate(); + fl_g->button_cfg_del_icy->activate(); + + fl_g->choice_cfg_act_icy->activate(); + + // make added icy data the active icy entry + fl_g->choice_cfg_act_icy->value(i); + choice_cfg_act_icy_cb(); +} + +void button_add_icy_cancel_cb(void) +{ + fl_g->input_add_icy_name->value(""); + fl_g->input_add_icy_desc->value(""); + fl_g->input_add_icy_url->value(""); + fl_g->input_add_icy_genre->value(""); + fl_g->input_add_icy_irc->value(""); + fl_g->input_add_icy_icq->value(""); + fl_g->input_add_icy_aim->value(""); + fl_g->check_add_icy_pub->value(0); + fl_g->window_add_icy->hide(); +} + +void button_cfg_edit_icy_cb(void) +{ + if (cfg.main.num_of_icy < 1) { + return; + } + + int icy = fl_g->choice_cfg_act_icy->value(); + + fl_g->window_add_icy->label(_("Edit Server Infos")); + + fl_g->button_add_icy_add->hide(); + fl_g->button_add_icy_save->show(); + + fl_g->input_add_icy_name->value(cfg.icy[icy]->name); + fl_g->input_add_icy_desc->value(cfg.icy[icy]->desc); + fl_g->input_add_icy_genre->value(cfg.icy[icy]->genre); + fl_g->input_add_icy_url->value(cfg.icy[icy]->url); + fl_g->input_add_icy_irc->value(cfg.icy[icy]->irc); + fl_g->input_add_icy_icq->value(cfg.icy[icy]->icq); + fl_g->input_add_icy_aim->value(cfg.icy[icy]->aim); + + if (!strcmp(cfg.icy[icy]->pub, "1")) { + fl_g->check_add_icy_pub->value(1); + } + else { + fl_g->check_add_icy_pub->value(0); + } + + fl_g->check_expand_variables->value(cfg.icy[icy]->expand_variables); + + fl_g->window_add_icy->position(fl_g->window_cfg->x(), fl_g->window_cfg->y()); + + // give the "name" input field the input focus + fl_g->input_add_icy_name->take_focus(); + fl_g->window_add_icy->show(); +} + +void choice_cfg_dev_cb(void) +{ + char info_buf[256]; + int new_dev_num = fl_g->choice_cfg_dev->value(); + int prev_dev_num = cfg.audio.dev_num; + + if (cfg.audio.dev2_num >= 0 && cfg.audio.pcm_list[cfg.audio.dev2_num]->is_asio && cfg.audio.pcm_list[new_dev_num]->is_asio) { + fl_alert(_( + "Primary and secondary audio device are both ASIO devices.\nYou can not use two ASIO devices at the same time.\nPlease select a different device.\n")); + // Fall back to previous selected secondary device + fl_g->choice_cfg_dev->value(prev_dev_num); + return; + } + + // save current device name to config struct + cfg.audio.dev_name = (char *)realloc(cfg.audio.dev_name, strlen(cfg.audio.pcm_list[new_dev_num]->name) + 1); + strcpy(cfg.audio.dev_name, cfg.audio.pcm_list[new_dev_num]->name); + + // In case the previous selected audio device had only 1 input channel but the new selected audio device has more than 1, + // select channel 1 and 2 by default for the new device instead of 1 and 1 to prevent that the user unintentionally streams the + // left channel in both stereo channels + if ((cfg.audio.pcm_list[new_dev_num]->num_of_channels > 1) && (cfg.audio.left_ch == 1) && cfg.audio.right_ch == 1) { + cfg.audio.left_ch = 1; + cfg.audio.right_ch = 2; + } + + cfg.audio.dev_num = new_dev_num; + update_samplerates_list(); + if (snd_reopen_streams() != 0) { + fl_alert(_("butt could not open selected audio device.\nPlease try another device.\n")); + + // Fall back to previous selected primary device + fl_g->choice_cfg_dev2->value(prev_dev_num); + cfg.audio.dev_num = prev_dev_num; + cfg.audio.dev_name = (char *)realloc(cfg.audio.dev_name, strlen(fl_g->choice_cfg_dev->text()) + 1); + strcpy(cfg.audio.dev_name, fl_g->choice_cfg_dev->text()); + update_samplerates_list(); + if (snd_reopen_streams() != 0) { + return; + } + } + + update_channel_lists(); + + snprintf(info_buf, sizeof(info_buf), _("Primary device:\n%s\n"), cfg.audio.dev_name); + print_info(info_buf, 1); +} + +void choice_cfg_dev2_cb(void) +{ + char info_buf[256]; + int new_dev2_num = fl_g->choice_cfg_dev2->value() - 1; + int prev_dev2_num = cfg.audio.dev2_num; + + if (new_dev2_num == -1) { + cfg.audio.dev2_name = (char *)realloc(cfg.audio.dev2_name, strlen(fl_g->choice_cfg_dev2->text()) + 1); + strcpy(cfg.audio.dev2_name, fl_g->choice_cfg_dev2->text()); + } + else { + if (cfg.audio.pcm_list[new_dev2_num]->is_asio && cfg.audio.pcm_list[cfg.audio.dev_num]->is_asio) { + fl_alert(_( + "Primary and secondary audio device are both ASIO devices.\nYou can not use two ASIO devices at the same time.\nPlease select a different device.\n")); + // Fall back to previous selected secondary device + fl_g->choice_cfg_dev2->value(prev_dev2_num + 1); + return; + } + + cfg.audio.dev2_name = (char *)realloc(cfg.audio.dev2_name, strlen(cfg.audio.pcm_list[new_dev2_num]->name) + 1); + strcpy(cfg.audio.dev2_name, cfg.audio.pcm_list[new_dev2_num]->name); + + // In case the previous selected audio device had only 1 input channel but the new selected audio device has more than 1, + // select channel 1 and 2 by default for the new device instead of 1 and 1 to prevent that the user unintentionally streams the + // left channel in both stereo channels + if ((cfg.audio.pcm_list[new_dev2_num]->num_of_channels > 1) && (cfg.audio.left_ch2 == 1) && cfg.audio.right_ch2 == 1) { + cfg.audio.left_ch2 = 1; + cfg.audio.right_ch2 = 2; + } + } + + cfg.audio.dev2_num = new_dev2_num; + if (snd_reopen_streams() != 0) { + fl_alert(_("butt could not open secondary audio device.\nPlease try another device.\n")); + + // Fall back to previous selected secondary device + fl_g->choice_cfg_dev2->value(prev_dev2_num + 1); + cfg.audio.dev2_num = prev_dev2_num; + cfg.audio.dev2_name = (char *)realloc(cfg.audio.dev2_name, strlen(fl_g->choice_cfg_dev2->text()) + 1); + strcpy(cfg.audio.dev2_name, fl_g->choice_cfg_dev2->text()); + if (snd_reopen_streams() != 0) { + return; + } + } + + update_channel_lists(); + + snprintf(info_buf, sizeof(info_buf), _("Secondary device:\n%s\n"), cfg.audio.dev2_name); + print_info(info_buf, 1); +} + +void button_cfg_rescan_devices_cb(void) +{ + if (connected || recording) { + return; + } + + fl_g->choice_cfg_dev->deactivate(); + fl_g->choice_cfg_dev2->deactivate(); + fl_g->button_cfg_rescan_devices->deactivate(); + Fl::check(); // Force UI update + + int dev_count; + char *current_device = strdup(cfg.audio.pcm_list[cfg.audio.dev_num]->name); + char *current_device2 = NULL; + if (cfg.audio.dev2_num >= 0) { + current_device2 = strdup(cfg.audio.pcm_list[cfg.audio.dev2_num]->name); + } + + snd_close_streams(); + + // Portaudio must be terminated and initialized again to detect new/missing devices + snd_close_portaudio(); + snd_free_device_list(cfg.audio.pcm_list, cfg.audio.dev_count); + snd_init(); + + cfg.audio.pcm_list = snd_get_devices(&dev_count); + cfg.audio.dev_count = dev_count; + + fl_g->choice_cfg_dev->clear(); + fl_g->choice_cfg_dev2->clear(); + fl_g->choice_cfg_dev->textsize(14); + fl_g->choice_cfg_dev2->textsize(14); + + fl_g->choice_cfg_dev2->add(_("None")); + for (int i = 0; i < cfg.audio.dev_count; i++) { + unsigned long dev_name_len = strlen(cfg.audio.pcm_list[i]->name) + 10; + char *dev_name = (char *)malloc(dev_name_len); + + snprintf(dev_name, dev_name_len, "%d: %s", i, cfg.audio.pcm_list[i]->name); + fl_g->choice_cfg_dev->add(dev_name); + fl_g->choice_cfg_dev2->add(dev_name); + free(dev_name); + } + + cfg.audio.dev_num = snd_get_dev_num_by_name(current_device); + free(current_device); + + if (current_device2 != NULL) { + cfg.audio.dev2_num = snd_get_dev_num_by_name(current_device2); + free(current_device2); + } + + snd_open_streams(); + + fl_g->choice_cfg_dev->value(cfg.audio.dev_num); + fl_g->choice_cfg_dev2->value(cfg.audio.dev2_num + 1); + fl_g->choice_cfg_dev->take_focus(); + + fl_g->choice_cfg_dev->activate(); + fl_g->choice_cfg_dev2->activate(); + fl_g->button_cfg_rescan_devices->activate(); +} + +void radio_cfg_ID_cb(void) +{ + cfg.audio.dev_remember = REMEMBER_BY_ID; +} + +void radio_cfg_name_cb(void) +{ + cfg.audio.dev_remember = REMEMBER_BY_NAME; + // save current device names to config struct + cfg.audio.dev_name = (char *)realloc(cfg.audio.dev_name, strlen(cfg.audio.pcm_list[cfg.audio.dev_num]->name) + 1); + strcpy(cfg.audio.dev_name, cfg.audio.pcm_list[cfg.audio.dev_num]->name); + + if (cfg.audio.dev2_num >= 0) { + cfg.audio.dev2_name = (char *)realloc(cfg.audio.dev2_name, strlen(cfg.audio.pcm_list[cfg.audio.dev2_num]->name) + 1); + strcpy(cfg.audio.dev2_name, cfg.audio.pcm_list[cfg.audio.dev2_num]->name); + } +} + +void choice_cfg_left_channel_cb(void) +{ + cfg.audio.left_ch = fl_g->choice_cfg_left_channel->value() + 1; +} + +void choice_cfg_right_channel_cb(void) +{ + cfg.audio.right_ch = fl_g->choice_cfg_right_channel->value() + 1; +} + +void choice_cfg_left_channel2_cb(void) +{ + cfg.audio.left_ch2 = fl_g->choice_cfg_left_channel2->value() + 1; +} + +void choice_cfg_right_channel2_cb(void) +{ + cfg.audio.right_ch2 = fl_g->choice_cfg_right_channel2->value() + 1; +} + +void choice_cfg_codec_mp3_cb(void) +{ + update_stream_bitrate_list(CHOICE_MP3); + lame_stream.bitrate = cfg.audio.bitrate; + + if (lame_enc_reinit(&lame_stream) != 0) { + print_info(_("MP3 encoder doesn't support current\n" + "Sample-/Bitrate combination"), + 1); + + if (!strcmp(cfg.audio.codec, "ogg")) { + fl_g->choice_cfg_codec->value(CHOICE_OGG); + } + else if (!strcmp(cfg.audio.codec, "opus")) { + fl_g->choice_cfg_codec->value(CHOICE_OPUS); + } + else if (!strcmp(cfg.audio.codec, "aac")) { + fl_g->choice_cfg_codec->value(CHOICE_AAC); + } + else if (!strcmp(cfg.audio.codec, "flac")) { + fl_g->choice_cfg_codec->value(CHOICE_FLAC); + } + + return; + } + + strcpy(cfg.audio.codec, "mp3"); + print_info(_("Stream codec set to mp3"), 0); + + fl_g->choice_cfg_bitrate->activate(); + fl_g->choice_cfg_bitrate->show(); +} + +void choice_cfg_codec_ogg_cb(void) +{ + update_stream_bitrate_list(CHOICE_OGG); + vorbis_stream.bitrate = cfg.audio.bitrate; + + if (vorbis_enc_reinit(&vorbis_stream) != 0) { + print_info(_("OGG Vorbis encoder doesn't support current\n" + "Sample-/Bitrate combination"), + 1); + + if (!strcmp(cfg.audio.codec, "mp3")) { + fl_g->choice_cfg_codec->value(CHOICE_MP3); + } + else if (!strcmp(cfg.audio.codec, "opus")) { + fl_g->choice_cfg_codec->value(CHOICE_OPUS); + } + else if (!strcmp(cfg.audio.codec, "aac")) { + fl_g->choice_cfg_codec->value(CHOICE_AAC); + } + else if (!strcmp(cfg.audio.codec, "flac")) { + fl_g->choice_cfg_codec->value(CHOICE_FLAC); + } + + return; + } + + strcpy(cfg.audio.codec, "ogg"); + print_info(_("Stream codec set to ogg/vorbis"), 0); + fl_g->choice_cfg_bitrate->activate(); + fl_g->choice_cfg_bitrate->show(); +} + +void choice_cfg_codec_opus_cb(void) +{ + update_stream_bitrate_list(CHOICE_OPUS); + opus_stream.bitrate = cfg.audio.bitrate * 1000; + + if (opus_enc_reinit(&opus_stream) != 0) { + print_info(_("Opus encoder doesn't support current\n" + "Sample-/Bitrate combination"), + 1); + + if (!strcmp(cfg.audio.codec, "mp3")) { + fl_g->choice_cfg_codec->value(CHOICE_MP3); + } + else if (!strcmp(cfg.audio.codec, "ogg")) { + fl_g->choice_cfg_codec->value(CHOICE_OGG); + } + else if (!strcmp(cfg.audio.codec, "aac")) { + fl_g->choice_cfg_codec->value(CHOICE_AAC); + } + else if (!strcmp(cfg.audio.codec, "flac")) { + fl_g->choice_cfg_codec->value(CHOICE_FLAC); + } + + return; + } + + print_info(_("Stream codec set to opus"), 0); + strcpy(cfg.audio.codec, "opus"); + fl_g->choice_cfg_bitrate->activate(); + fl_g->choice_cfg_bitrate->show(); +} + +void choice_cfg_codec_aac_cb(void) +{ +#ifdef HAVE_LIBFDK_AAC + if (g_aac_lib_available == 0) { + fl_g->window_missing_aac_lib->position(fl_g->window_cfg->x(), fl_g->window_cfg->y() + fl_g->window_cfg->h() / 2); + fl_g->window_missing_aac_lib->show(); + if (!strcmp(cfg.audio.codec, "ogg")) { + fl_g->choice_cfg_codec->value(CHOICE_OGG); + } + else if (!strcmp(cfg.audio.codec, "opus")) { + fl_g->choice_cfg_codec->value(CHOICE_OPUS); + } + else if (!strcmp(cfg.audio.codec, "mp3")) { + fl_g->choice_cfg_codec->value(CHOICE_MP3); + } + else if (!strcmp(cfg.audio.codec, "flac")) { + fl_g->choice_cfg_codec->value(CHOICE_FLAC); + } + + return; + } + + update_stream_bitrate_list(CHOICE_AAC); + aac_stream.bitrate = cfg.audio.bitrate; + + if (aac_enc_reinit(&aac_stream) != 0) { + print_info(_("AAC encoder doesn't support current\n" + "Sample-/Bitrate combination"), + 1); + + if (!strcmp(cfg.audio.codec, "ogg")) { + fl_g->choice_cfg_codec->value(CHOICE_OGG); + } + else if (!strcmp(cfg.audio.codec, "opus")) { + fl_g->choice_cfg_codec->value(CHOICE_OPUS); + } + else if (!strcmp(cfg.audio.codec, "mp3")) { + fl_g->choice_cfg_codec->value(CHOICE_MP3); + } + else if (!strcmp(cfg.audio.codec, "flac")) { + fl_g->choice_cfg_codec->value(CHOICE_FLAC); + } + + return; + } + + strcpy(cfg.audio.codec, "aac"); + print_info(_("Stream codec set to aac"), 0); + fl_g->choice_cfg_bitrate->activate(); + fl_g->choice_cfg_bitrate->show(); + +#endif +} + +void choice_cfg_codec_flac_cb(void) +{ + if (flac_enc_reinit(&flac_stream) != 0) { + print_info(_("ERROR: While initializing flac settings"), 1); + + if (!strcmp(cfg.audio.codec, "mp3")) { + fl_g->choice_rec_codec->value(CHOICE_MP3); + } + else if (!strcmp(cfg.audio.codec, "ogg")) { + fl_g->choice_rec_codec->value(CHOICE_OGG); + } + else if (!strcmp(cfg.audio.codec, "opus")) { + fl_g->choice_rec_codec->value(CHOICE_OPUS); + } + else if (!strcmp(cfg.audio.codec, "aac")) { + fl_g->choice_rec_codec->value(CHOICE_AAC); + } + + return; + } + strcpy(cfg.audio.codec, "flac"); + print_info(_("Stream codec set to flac"), 0); + + fl_g->choice_cfg_bitrate->hide(); + fl_g->window_cfg->redraw(); +} + +void choice_rec_codec_mp3_cb(void) +{ + update_rec_bitrate_list(CHOICE_MP3); + lame_rec.bitrate = cfg.rec.bitrate; + + if (lame_enc_reinit(&lame_rec) != 0) { + print_info(_("MP3 encoder doesn't support current\n" + "Sample-/Bitrate combination"), + 1); + + // fall back to old rec codec + if (!strcmp(cfg.rec.codec, "ogg")) { + fl_g->choice_rec_codec->value(CHOICE_OGG); + } + else if (!strcmp(cfg.rec.codec, "wav")) { + fl_g->choice_rec_codec->value(CHOICE_WAV); + } + else if (!strcmp(cfg.rec.codec, "opus")) { + fl_g->choice_rec_codec->value(CHOICE_OPUS); + } + else if (!strcmp(cfg.rec.codec, "aac")) { + fl_g->choice_rec_codec->value(CHOICE_AAC); + } + else if (!strcmp(cfg.rec.codec, "flac")) { + fl_g->choice_rec_codec->value(CHOICE_FLAC); + } + + return; + } + strcpy(cfg.rec.codec, "mp3"); + + // check if the extension of the filename matches + // the current selected codec + test_file_extension(); + + print_info(_("Record codec set to mp3"), 0); + fl_g->choice_rec_bitrate->activate(); + fl_g->choice_rec_bitrate->show(); +} + +void choice_rec_codec_ogg_cb(void) +{ + update_rec_bitrate_list(CHOICE_OGG); + vorbis_rec.bitrate = cfg.rec.bitrate; + + if (vorbis_enc_reinit(&vorbis_rec) != 0) { + print_info(_("OGG Vorbis encoder doesn't support current\n" + "Sample-/Bitrate combination"), + 1); + + if (!strcmp(cfg.rec.codec, "mp3")) { + fl_g->choice_rec_codec->value(CHOICE_MP3); + } + else if (!strcmp(cfg.rec.codec, "wav")) { + fl_g->choice_rec_codec->value(CHOICE_WAV); + } + else if (!strcmp(cfg.rec.codec, "opus")) { + fl_g->choice_rec_codec->value(CHOICE_OPUS); + } + else if (!strcmp(cfg.rec.codec, "aac")) { + fl_g->choice_rec_codec->value(CHOICE_AAC); + } + else if (!strcmp(cfg.rec.codec, "flac")) { + fl_g->choice_rec_codec->value(CHOICE_FLAC); + } + + return; + } + strcpy(cfg.rec.codec, "ogg"); + + // check if the extension of the filename matches + // the current selected codec + test_file_extension(); + + print_info(_("Record codec set to ogg/vorbis"), 0); + fl_g->choice_rec_bitrate->activate(); + fl_g->choice_rec_bitrate->show(); +} + +void choice_rec_codec_opus_cb(void) +{ + update_rec_bitrate_list(CHOICE_OPUS); + opus_rec.bitrate = cfg.rec.bitrate * 1000; + + if (opus_enc_reinit(&opus_rec) != 0) { + print_info(_("Opus encoder doesn't support current\n" + "Sample-/Bitrate combination"), + 1); + + if (!strcmp(cfg.rec.codec, "mp3")) { + fl_g->choice_rec_codec->value(CHOICE_MP3); + } + else if (!strcmp(cfg.rec.codec, "wav")) { + fl_g->choice_rec_codec->value(CHOICE_WAV); + } + else if (!strcmp(cfg.rec.codec, "ogg")) { + fl_g->choice_rec_codec->value(CHOICE_OGG); + } + else if (!strcmp(cfg.rec.codec, "aac")) { + fl_g->choice_rec_codec->value(CHOICE_AAC); + } + else if (!strcmp(cfg.rec.codec, "flac")) { + fl_g->choice_rec_codec->value(CHOICE_FLAC); + } + + return; + } + strcpy(cfg.rec.codec, "opus"); + + // check if the extension of the filename matches + // the current selected codec + test_file_extension(); + + print_info(_("Record codec set to opus"), 0); + fl_g->choice_rec_bitrate->activate(); + fl_g->choice_rec_bitrate->show(); +} + +void choice_rec_codec_aac_cb(void) +{ +#ifdef HAVE_LIBFDK_AAC + if (g_aac_lib_available == 0) { + fl_g->window_missing_aac_lib->position(fl_g->window_cfg->x(), fl_g->window_cfg->y() + fl_g->window_cfg->h() / 2); + fl_g->window_missing_aac_lib->show(); + + if (!strcmp(cfg.rec.codec, "ogg")) { + fl_g->choice_rec_codec->value(CHOICE_OGG); + } + else if (!strcmp(cfg.rec.codec, "opus")) { + fl_g->choice_rec_codec->value(CHOICE_OPUS); + } + else if (!strcmp(cfg.rec.codec, "mp3")) { + fl_g->choice_rec_codec->value(CHOICE_MP3); + } + else if (!strcmp(cfg.rec.codec, "flac")) { + fl_g->choice_rec_codec->value(CHOICE_FLAC); + } + else if (!strcmp(cfg.rec.codec, "wav")) { + fl_g->choice_rec_codec->value(CHOICE_WAV); + } + + return; + } + + update_rec_bitrate_list(CHOICE_AAC); + aac_rec.bitrate = cfg.rec.bitrate; + if (aac_enc_reinit(&aac_rec) != 0) { + print_info(_("AAC encoder doesn't support current\n" + "Sample-/Bitrate combination"), + 1); + + // fall back to old rec codec + if (!strcmp(cfg.rec.codec, "ogg")) { + fl_g->choice_rec_codec->value(CHOICE_OGG); + } + else if (!strcmp(cfg.rec.codec, "wav")) { + fl_g->choice_rec_codec->value(CHOICE_WAV); + } + else if (!strcmp(cfg.rec.codec, "opus")) { + fl_g->choice_rec_codec->value(CHOICE_OPUS); + } + else if (!strcmp(cfg.rec.codec, "flac")) { + fl_g->choice_rec_codec->value(CHOICE_FLAC); + } + else if (!strcmp(cfg.rec.codec, "mp3")) { + fl_g->choice_rec_codec->value(CHOICE_MP3); + } + + return; + } + strcpy(cfg.rec.codec, "aac"); + + // check if the extension of the filename matches + // the current selected codec + test_file_extension(); + + print_info(_("Record codec set to aac"), 0); + fl_g->choice_rec_bitrate->activate(); + fl_g->choice_rec_bitrate->show(); + +#endif +} + +void choice_rec_codec_flac_cb(void) +{ + if (flac_enc_reinit(&flac_rec) != 0) { + print_info(_("ERROR: While initializing flac settings"), 1); + + if (!strcmp(cfg.rec.codec, "mp3")) { + fl_g->choice_rec_codec->value(CHOICE_MP3); + } + else if (!strcmp(cfg.rec.codec, "ogg")) { + fl_g->choice_rec_codec->value(CHOICE_OGG); + } + else if (!strcmp(cfg.rec.codec, "opus")) { + fl_g->choice_rec_codec->value(CHOICE_OPUS); + } + else if (!strcmp(cfg.rec.codec, "wav")) { + fl_g->choice_rec_codec->value(CHOICE_WAV); + } + else if (!strcmp(cfg.rec.codec, "aac")) { + fl_g->choice_rec_codec->value(CHOICE_AAC); + } + + return; + } + strcpy(cfg.rec.codec, "flac"); + + // check if the extension of the filename matches + // the current selected codec + test_file_extension(); + + print_info(_("Record codec set to flac"), 0); + fl_g->choice_rec_bitrate->hide(); + fl_g->window_cfg->redraw(); +} + +void choice_rec_codec_wav_cb(void) +{ + fl_g->choice_rec_bitrate->hide(); + fl_g->window_cfg->redraw(); + + strcpy(cfg.rec.codec, "wav"); + + // check if the extension of the filename matches + // the current selected codec + test_file_extension(); + + print_info(_("Record codec set to wav"), 0); +} + +void input_tls_cert_file_cb(void) +{ + cfg.tls.cert_file = (char *)realloc(cfg.tls.cert_file, strlen(fl_g->input_tls_cert_file->value()) + 1); + + strcpy(cfg.tls.cert_file, fl_g->input_tls_cert_file->value()); + fl_g->input_tls_cert_file->tooltip(cfg.tls.cert_file); +} + +void input_tls_cert_dir_cb(void) +{ + int len = strlen(fl_g->input_tls_cert_dir->value()); + + cfg.tls.cert_dir = (char *)realloc(cfg.tls.cert_dir, len + 2); + + strcpy(cfg.tls.cert_dir, fl_g->input_tls_cert_dir->value()); + +#ifdef WIN32 // Replace all "Windows slashes" with "unix slashes" + strrpl(&cfg.tls.cert_dir, (char *)"\\", (char *)"/", MODE_ALL); +#endif + + // Append an '/' if there isn't one + if ((len > 0) && (cfg.tls.cert_dir[len - 1] != '/')) { + strcat(cfg.tls.cert_dir, "/"); + } + + fl_g->input_tls_cert_dir->value(cfg.tls.cert_dir); + fl_g->input_tls_cert_dir->tooltip(cfg.tls.cert_dir); +} + +void button_tls_browse_file_cb(void) +{ + Fl_My_Native_File_Chooser nfc; + nfc.title(_("Select certificate file...")); + nfc.type(Fl_My_Native_File_Chooser::BROWSE_FILE); + + switch (nfc.show()) { + case -1: + fl_alert(_("ERROR: %s"), nfc.errmsg()); + break; + case 1: + break; // cancel pressed + default: + fl_g->input_tls_cert_file->value(nfc.filename()); + input_tls_cert_file_cb(); + } +} + +void button_tls_browse_dir_cb(void) +{ + Fl_My_Native_File_Chooser nfc; + nfc.title(_("Select certificate directory...")); + nfc.type(Fl_My_Native_File_Chooser::BROWSE_DIRECTORY); + nfc.options(Fl_My_Native_File_Chooser::NEW_FOLDER); + + nfc.directory(fl_g->input_tls_cert_dir->value()); + + switch (nfc.show()) { + case -1: + fl_alert(_("ERROR: %s"), nfc.errmsg()); // error + break; + case 1: + break; // cancel pressed + default: + fl_g->input_tls_cert_dir->value(nfc.filename()); + input_tls_cert_dir_cb(); + break; + } +} + +void ILM216_cb(void) +{ + if (Fl::event_button() == 1) // left mouse button + { + // change the display mode only when connected or recording + // this will prevent confusing the user + if (!connected && !recording) { + return; + } + + switch (display_info) { + case STREAM_TIME: + if (recording) { + display_info = REC_TIME; + } + else { + display_info = SENT_DATA; + cfg.gui.default_stream_info = display_info; + } + break; + + case REC_TIME: + if (connected) { + display_info = SENT_DATA; + cfg.gui.default_stream_info = display_info; + } + else { + display_info = REC_DATA; + } + break; + + case SENT_DATA: + display_info = STREAM_STATE; + cfg.gui.default_stream_info = display_info; + break; + + case STREAM_STATE: + if (recording) { + display_info = REC_DATA; + } + else { + display_info = STREAM_TIME; + cfg.gui.default_stream_info = display_info; + } + break; + + case REC_DATA: + if (connected) { + display_info = STREAM_TIME; + cfg.gui.default_stream_info = display_info; + } + else { + display_info = REC_TIME; + } + } + } + /* if(Fl::event_button() == 3) //right mouse button + { + uchar r, g, b; + + Fl_Color bg, txt; + bg = (Fl_Color)cfg.main.bg_color; + txt = (Fl_Color)cfg.main.txt_color; + + //Set the r g b values the color_chooser should start with + r = (bg & 0xFF000000) >> 24; + g = (bg & 0x00FF0000) >> 16; + b = (bg & 0x0000FF00) >> 8; + + fl_color_chooser((const char*)"select background color", r, g, b); + + //The color_chooser changes the r, g, b, values to selected color + cfg.main.bg_color = fl_rgb_color(r, g, b); + + fl_g->lcd->redraw(); + + r = (txt & 0xFF000000) >> 24; + g = (txt & 0x00FF0000) >> 16; + b = (txt & 0x0000FF00) >> 8; + + fl_color_chooser((const char*)"select text color", r, g, b); + cfg.main.txt_color = fl_rgb_color(r, g, b); + + fl_g->lcd->redraw(); + + + }*/ +} + +void button_rec_browse_cb(void) +{ + Fl_My_Native_File_Chooser nfc; + nfc.title(_("Record to...")); + nfc.type(Fl_My_Native_File_Chooser::BROWSE_DIRECTORY); + nfc.options(Fl_My_Native_File_Chooser::NEW_FOLDER); + + nfc.directory(fl_g->input_rec_folder->value()); + + switch (nfc.show()) { + case -1: + fl_alert(_("ERROR: %s"), nfc.errmsg()); // error + break; + case 1: + break; // cancel + default: + fl_g->input_rec_folder->value(nfc.filename()); + input_rec_folder_cb(); + + break; + } +} +void button_rec_split_now_cb(void) +{ + if (recording) { + split_recording_file(); + } + else { + fl_alert(_("File splitting only works if recording is active.")); + } +} + +void input_rec_filename_cb(void) +{ + char *tooltip; + + cfg.rec.filename = (char *)realloc(cfg.rec.filename, strlen(fl_g->input_rec_filename->value()) + 1); + + strcpy(cfg.rec.filename, fl_g->input_rec_filename->value()); + + // check if the extension of the filename matches + // the current selected codec + test_file_extension(); + + tooltip = strdup(cfg.rec.filename); + + expand_string(&tooltip); + + fl_g->input_rec_filename->copy_tooltip(tooltip); + + free(tooltip); +} + +void input_rec_folder_cb(void) +{ + char *tooltip; + int len = strlen(fl_g->input_rec_folder->value()); + + cfg.rec.folder = (char *)realloc(cfg.rec.folder, len + 2); + + strcpy(cfg.rec.folder, fl_g->input_rec_folder->value()); + +#ifdef WIN32 // Replace all "Windows slashes" with "unix slashes" + char *p; + p = cfg.rec.folder; + while (*p != '\0') { + if (*p == '\\') { + *p = '/'; + } + p++; + } +#endif + + // Append an '/' if there isn't one + if (cfg.rec.folder[len - 1] != '/') { + strcat(cfg.rec.folder, "/"); + } + + fl_g->input_rec_folder->value(cfg.rec.folder); + + tooltip = strdup(cfg.rec.folder); + expand_string(&tooltip); + fl_g->input_rec_folder->copy_tooltip(tooltip); + free(tooltip); +} + +void input_log_filename_cb(void) +{ + cfg.main.log_file = (char *)realloc(cfg.main.log_file, strlen(fl_g->input_log_filename->value()) + 1); + + strcpy(cfg.main.log_file, fl_g->input_log_filename->value()); + fl_g->input_log_filename->tooltip(cfg.main.log_file); +} + +void button_cfg_browse_songfile_cb(void) +{ + Fl_My_Native_File_Chooser nfc; + nfc.title(_("Select Songfile")); + nfc.type(Fl_My_Native_File_Chooser::BROWSE_FILE); + switch (nfc.show()) { + case -1: + fl_alert(_("ERROR: %s"), nfc.errmsg()); + break; + case 1: + break; // cancel + default: + fl_g->input_cfg_song_file->value(nfc.filename()); + input_cfg_song_file_cb(); + } +} + +void input_cfg_song_file_cb(void) +{ + int len = strlen(fl_g->input_cfg_song_file->value()); + + cfg.main.song_path = (char *)realloc(cfg.main.song_path, len + 1); + + strcpy(cfg.main.song_path, fl_g->input_cfg_song_file->value()); + +#ifdef WIN32 // Replace all "Windows slashes" with "unix slashes" + char *p; + p = cfg.main.song_path; + while (*p != '\0') { + if (*p == '\\') { + *p = '/'; + } + p++; + } +#endif + + fl_g->input_cfg_song_file->value(cfg.main.song_path); + fl_g->input_cfg_song_file->tooltip(cfg.main.song_path); +} + +void check_gui_attach_cb(void) +{ + if (fl_g->check_gui_attach->value()) { + cfg.gui.attach = 1; + Fl::add_timeout(0.1, &cfg_win_pos_timer); + } + else { + cfg.gui.attach = 0; + Fl::remove_timeout(&cfg_win_pos_timer); + } +} + +void check_gui_ontop_cb(void) +{ + if (fl_g->check_gui_ontop->value()) { + fl_g->window_main->stay_on_top(1); + fl_g->window_cfg->stay_on_top(1); + cfg.gui.ontop = 1; + } + else { + fl_g->window_main->stay_on_top(0); + fl_g->window_cfg->stay_on_top(0); + cfg.gui.ontop = 0; + } +} +void check_gui_hide_log_window_cb(void) +{ + if (fl_g->check_gui_hide_log_window->value()) { + cfg.gui.hide_log_window = 1; + } + else { + cfg.gui.hide_log_window = 0; + } +} + +void check_gui_remember_pos_cb(void) +{ + if (fl_g->check_gui_remember_pos->value()) { + cfg.gui.remember_pos = 1; + } + else { + cfg.gui.remember_pos = 0; + } +} + +void check_gui_lcd_auto_cb(void) +{ + if (fl_g->check_gui_lcd_auto->value()) { + cfg.gui.lcd_auto = 1; + } + else { + cfg.gui.lcd_auto = 0; + } +} + +void check_gui_start_minimized_cb(void) +{ + cfg.gui.start_minimized = fl_g->check_gui_start_minimized->value(); +} + +void check_gui_disable_gain_slider_cb(void) +{ + cfg.gui.disable_gain_slider = fl_g->check_gui_disable_gain_slider->value(); + + if (cfg.gui.disable_gain_slider) { + fl_g->slider_gain->deactivate(); + fl_g->label_n24dB->deactivate(); + fl_g->label_p24dB->deactivate(); + fl_g->slider_gain->tooltip(_("Gain control is disabled. Enable in Settings->GUI")); + } + else { + fl_g->slider_gain->activate(); + fl_g->label_n24dB->activate(); + fl_g->label_p24dB->activate(); + fl_g->slider_gain->tooltip(_("Master Gain")); + } +} + +void check_gui_show_listeners_cb(void) +{ + cfg.gui.show_listeners = fl_g->check_gui_show_listeners->value(); + + if (connected) { + if (cfg.gui.show_listeners) { + static int reset = 1; + Fl::remove_timeout(&request_listener_count_timer); + Fl::add_timeout(0.5, &request_listener_count_timer, &reset); + } + else { + Fl::remove_timeout(&request_listener_count_timer); + fl_g->label_current_listeners->hide(); + } + } +} + +void input_gui_listeners_update_rate_cb(void) +{ + if (fl_g->input_gui_listeners_update_rate->value() < 1) { + fl_g->input_gui_listeners_update_rate->value(1); + } + + cfg.gui.listeners_update_rate = fl_g->input_gui_listeners_update_rate->value(); + + if (cfg.gui.show_listeners) { + static int reset = 1; + Fl::remove_timeout(&request_listener_count_timer); + Fl::add_timeout(0.5, &request_listener_count_timer, &reset); + } +} + +void color_chooser(const char *text, int &cfg_color) +{ + uchar r, g, b; + Fl_Color c; + c = (Fl_Color)cfg_color; + + // Set the r g b values the color_chooser should start with + r = (c & 0xFF000000) >> 24; + g = (c & 0x00FF0000) >> 16; + b = (c & 0x0000FF00) >> 8; + + fl_color_chooser(text, r, g, b); + + // The fl_color_chooser sets the r, g, b values to the selected color + cfg_color = fl_rgb_color(r, g, b); +} + +void button_gui_bg_color_cb(void) +{ + color_chooser(_("select background color"), cfg.main.bg_color); + + fl_g->button_gui_bg_color->color(cfg.main.bg_color, fl_lighter((Fl_Color)cfg.main.bg_color)); + fl_g->button_gui_bg_color->redraw(); + fl_g->lcd->redraw(); + fl_g->sponsor_logo->redraw(); +} + +void button_gui_text_color_cb(void) +{ + color_chooser(_("select text color"), cfg.main.txt_color); + + fl_g->button_gui_text_color->color(cfg.main.txt_color, fl_lighter((Fl_Color)cfg.main.txt_color)); + fl_g->button_gui_text_color->redraw(); + fl_g->lcd->redraw(); + fl_g->sponsor_logo->redraw(); +} + +void button_gui_vu_low_color_cb(void) +{ + color_chooser("", cfg.gui.vu_low_color); + + fl_g->button_gui_vu_low_color->color(cfg.gui.vu_low_color, fl_lighter((Fl_Color)cfg.gui.vu_low_color)); + fl_g->button_gui_vu_low_color->redraw(); +} + +void button_gui_vu_mid_color_cb(void) +{ + color_chooser("", cfg.gui.vu_mid_color); + + fl_g->button_gui_vu_mid_color->color(cfg.gui.vu_mid_color, fl_lighter((Fl_Color)cfg.gui.vu_mid_color)); + fl_g->button_gui_vu_mid_color->redraw(); +} +void button_gui_vu_high_color_cb(void) +{ + color_chooser("", cfg.gui.vu_high_color); + + fl_g->button_gui_vu_high_color->color(cfg.gui.vu_high_color, fl_lighter((Fl_Color)cfg.gui.vu_high_color)); + fl_g->button_gui_vu_high_color->redraw(); +} +void input_gui_vu_mid_range_start_cb(void) +{ + if (fl_g->input_gui_vu_mid_range_start->value() < -54) { + fl_alert(_("Value must be a number between -54 and 0")); + fl_g->input_gui_vu_mid_range_start->value(cfg.gui.vu_mid_range_start); + } + if (fl_g->input_gui_vu_mid_range_start->value() > 0) { + fl_alert(_("Value must be a number between -54 and 0")); + fl_g->input_gui_vu_mid_range_start->value(cfg.gui.vu_mid_range_start); + } + + cfg.gui.vu_mid_range_start = fl_g->input_gui_vu_mid_range_start->value(); +} +void input_gui_vu_high_range_start_cb(void) +{ + if (fl_g->input_gui_vu_high_range_start->value() < -54) { + fl_alert(_("Value must be a number between -54 and 0")); + fl_g->input_gui_vu_high_range_start->value(cfg.gui.vu_high_range_start); + } + if (fl_g->input_gui_vu_high_range_start->value() > 0) { + fl_alert(_("Value must be a number between -54 and 0")); + fl_g->input_gui_vu_high_range_start->value(cfg.gui.vu_high_range_start); + } + + cfg.gui.vu_high_range_start = fl_g->input_gui_vu_high_range_start->value(); +} + +void choice_gui_language_cb(void) +{ + lang_id_to_str(fl_g->choice_gui_language->value(), &cfg.gui.lang_str, LANG_MAPPING_NEW); + fl_alert(_("Please restart butt to apply new language.")); +} + +void radio_gui_vu_gradient_cb(void) +{ + cfg.gui.vu_mode = VU_MODE_GRADIENT; +} +void radio_gui_vu_solid_cb(void) +{ + cfg.gui.vu_mode = VU_MODE_SOLID; +} + +void check_gui_always_show_vu_tabs_cb(void) +{ + cfg.gui.always_show_vu_tabs = fl_g->check_gui_always_show_vu_tabs->value(); + + if (cfg.gui.always_show_vu_tabs == 0) { + fl_g->invisible_tab_box->enable(); + hide_vu_tabs(); + } + else { + fl_g->invisible_tab_box->disable(); + show_vu_tabs(); + } +} + +void input_gui_window_title_cb(void) +{ + cfg.gui.window_title = (char *)realloc(cfg.gui.window_title, strlen(fl_g->input_gui_window_title->value()) + 1); + strcpy(cfg.gui.window_title, fl_g->input_gui_window_title->value()); + + if (strlen(cfg.gui.window_title) > 0) { + fl_g->window_main->label(cfg.gui.window_title); + } + else { + fl_g->window_main->label(PACKAGE_STRING); + } +} + +void check_cfg_overwrite_existing_files_cb(void) +{ + cfg.rec.overwrite_files = fl_g->check_cfg_overwrite_existing_files->value(); +} + +void check_cfg_auto_start_rec_cb(void) +{ + cfg.rec.start_rec = fl_g->check_cfg_auto_start_rec->value(); + fl_g->lcd->redraw(); // update the little record icon + fl_g->sponsor_logo->redraw(); +} + +void check_cfg_auto_stop_rec_cb(void) +{ + cfg.rec.stop_rec = fl_g->check_cfg_auto_stop_rec->value(); +} + +void check_cfg_rec_after_launch_cb(void) +{ + cfg.rec.rec_after_launch = fl_g->check_cfg_rec_after_launch->value(); +} + +void check_cfg_rec_hourly_cb(void) +{ + // cfg.rec.start_rec_hourly = fl_g->check_cfg_rec_hourly->value(); +} + +void check_cfg_connect_cb(void) +{ + cfg.main.connect_at_startup = fl_g->check_cfg_connect->value(); +} + +void check_cfg_force_reconnecting_cb(void) +{ + cfg.main.force_reconnecting = fl_g->check_cfg_force_reconnecting->value(); +} + +void input_cfg_present_level_cb(void) +{ + if (fl_g->input_cfg_present_level->value() < -90) { + fl_alert(_("Value must be a number between -90.0 and 0")); + fl_g->input_cfg_present_level->value(-cfg.audio.signal_level); + } + + if (fl_g->input_cfg_present_level->value() > 0) { + fl_alert(_("Value must be a number between -90.0 and 0")); + fl_g->input_cfg_present_level->value(-cfg.audio.signal_level); + } + + cfg.audio.signal_level = -fl_g->input_cfg_present_level->value(); +} + +void input_cfg_absent_level_cb(void) +{ + if (fl_g->input_cfg_absent_level->value() < -90) { + fl_alert(_("Value must be a number between -90.0 and 0")); + fl_g->input_cfg_absent_level->value(-cfg.audio.silence_level); + } + + if (fl_g->input_cfg_absent_level->value() > 0) { + fl_alert(_("Value must be a number between -90.0 and 0")); + fl_g->input_cfg_absent_level->value(-cfg.audio.silence_level); + } + + cfg.audio.silence_level = -fl_g->input_cfg_absent_level->value(); +} + +void check_stream_signal_cb(void) +{ + cfg.main.signal_detection = fl_g->check_stream_signal->value(); + + if (cfg.main.signal_detection == 1) { + if (fl_g->input_cfg_signal->value() < 0.1) { + fl_g->input_cfg_signal->value(1); + cfg.main.signal_threshold = fl_g->input_cfg_signal->value(); + } + reset_stream_signal_detection_timer(); + } + else { + Fl::remove_timeout(&stream_signal_timer); + } +} + +void check_stream_silence_cb(void) +{ + cfg.main.silence_detection = fl_g->check_stream_silence->value(); + + if (cfg.main.silence_detection == 1) { + if (fl_g->input_cfg_silence->value() < 0.1) { + fl_g->input_cfg_silence->value(1); + cfg.main.silence_threshold = fl_g->input_cfg_silence->value(); + } + reset_stream_silence_detection_timer(); + } + else { + Fl::remove_timeout(&stream_silence_timer); + } +} + +void input_cfg_signal_cb(void) +{ + // Values < 0.1 are not allowed + if (fl_g->input_cfg_signal->value() < 0.1) { + fl_g->input_cfg_signal->value(0.1); + } + + reset_stream_signal_detection_timer(); + cfg.main.signal_threshold = fl_g->input_cfg_signal->value(); +} + +void input_cfg_silence_cb(void) +{ + // Values < 0.1 are not allowed + if (fl_g->input_cfg_silence->value() < 0.1) { + fl_g->input_cfg_silence->value(0.1); + } + + reset_stream_silence_detection_timer(); + cfg.main.silence_threshold = fl_g->input_cfg_silence->value(); +} + +void input_cfg_reconnect_delay_cb(void) +{ + cfg.main.reconnect_delay = fl_g->input_cfg_reconnect_delay->value(); +} + +void check_rec_signal_cb(void) +{ + cfg.rec.signal_detection = fl_g->check_rec_signal->value(); + + if (cfg.rec.signal_detection == 1) { + if (fl_g->input_rec_signal->value() < 0.1) { + fl_g->input_rec_signal->value(1); + cfg.rec.signal_threshold = fl_g->input_rec_signal->value(); + } + reset_record_signal_detection_timer(); + } + else { + Fl::remove_timeout(&record_signal_timer); + } +} + +void check_rec_silence_cb(void) +{ + cfg.rec.silence_detection = fl_g->check_rec_silence->value(); + + if (cfg.rec.silence_detection == 1) { + if (fl_g->input_rec_silence->value() < 0.1) { + fl_g->input_rec_silence->value(1); + cfg.rec.silence_threshold = fl_g->input_rec_silence->value(); + } + Fl::remove_timeout(&record_silence_timer); + Fl::add_timeout(1, &record_silence_timer); + } + else { + Fl::remove_timeout(&record_silence_timer); + } +} + +void input_rec_signal_cb(void) +{ + // Values < 0.1 are not allowed + if (fl_g->input_rec_signal->value() < 0.1) { + fl_g->input_rec_signal->value(0.1); + } + + reset_record_signal_detection_timer(); + cfg.rec.signal_threshold = fl_g->input_rec_signal->value(); +} + +void input_rec_silence_cb(void) +{ + // Values < 0.1 are not allowed + if (fl_g->input_rec_silence->value() < 0.1) { + fl_g->input_rec_silence->value(0.1); + } + + reset_record_silence_detection_timer(); + cfg.rec.silence_threshold = fl_g->input_rec_silence->value(); +} + +void check_song_update_active_cb(void) +{ + if (fl_g->check_song_update_active->value()) { + if (connected) { + static int reset = 1; + Fl::remove_timeout(&songfile_timer); + Fl::add_timeout(0.1, &songfile_timer, &reset); + } + cfg.main.song_update = 1; + } + else { + Fl::remove_timeout(&songfile_timer); + if (cfg.main.song != NULL) { + free(cfg.main.song); + cfg.main.song = NULL; + } + cfg.main.song_update = 0; + } +} + +void check_read_last_line_cb(void) +{ + cfg.main.read_last_line = fl_g->check_read_last_line->value(); +} + +void check_sync_to_full_hour_cb(void) +{ + if (fl_g->check_sync_to_full_hour->value()) { + cfg.rec.sync_to_hour = 1; + } + else { + cfg.rec.sync_to_hour = 0; + } +} + +void slider_gain_cb(void *called_by) +{ + char str[10]; + float gain_db; + + if (called_by != (void *)CB_CALLED_BY_MIDI) { + cfg.midi.commands[MIDI_CMD_MASTER_GAIN].picked_up = 0; + } + + // Without redrawing the main window the slider knob is not redrawn correctly + fl_g->window_main->redraw(); + + gain_db = (float)fl_g->slider_gain->value(); + + snprintf(str, 10, "%+.1f dB", gain_db); + fl_g->text_mixer_master_volume->copy_label(str); + fl_g->slider_mixer_master_gain->value_cb2("dB"); + + if (gain_db > -0.1 && gain_db < 0.1) { + cfg.main.gain = 1; + fl_g->slider_gain->value(0); + fl_g->slider_mixer_master_gain->value(0); + } + else { + cfg.main.gain = util_db_to_factor(gain_db); + fl_g->slider_mixer_master_gain->value(gain_db); + } + + fl_g->slider_gain->value_cb2("dB"); +} + +void vu_tabs_cb(void) +{ + const char *active_tab = fl_g->vu_tabs->value()->label(); + if (!strcmp(active_tab, _("Streaming"))) { + fl_g->label_volume->label(_("Streaming volume")); + snd_set_vu_level_type(SND_STREAM); + } + else { + fl_g->label_volume->label(_("Recording volume")); + snd_set_vu_level_type(SND_REC); + } +} + +void input_rec_split_time_cb(void) +{ + // Values < 0 are not allowed + if (fl_g->input_rec_split_time->value() < 0) { + fl_g->input_rec_split_time->value(0); + } + + cfg.rec.split_time = fl_g->input_rec_split_time->value(); +} + +void button_cfg_export_cb(void) +{ + char *filename; + + Fl_My_Native_File_Chooser nfc; + + nfc.title(_("Export to...")); + nfc.type(Fl_My_Native_File_Chooser::BROWSE_SAVE_FILE); + nfc.options(Fl_My_Native_File_Chooser::NEW_FOLDER); + + switch (nfc.show()) { + case -1: + fl_alert(_("ERROR: %s"), nfc.errmsg()); // error + return; + break; + case 1: + return; // cancel + break; + default: + filename = (char *)nfc.filename(); + } + + cfg_write_file(filename); +} + +void button_cfg_import_cb(void) +{ + char *filename; + char info_buf[256]; + + Fl_My_Native_File_Chooser nfc; + nfc.title(_("Import...")); + nfc.type(Fl_My_Native_File_Chooser::BROWSE_FILE); + + switch (nfc.show()) { + case -1: + fl_alert(_("ERROR: %s"), nfc.errmsg()); // error + return; + break; + case 1: + return; // cancel + break; + default: + filename = (char *)nfc.filename(); + break; + } + + // read config and initialize config struct + if (cfg_set_values(filename) != 0) { + snprintf(info_buf, sizeof(info_buf), _("Could not import config %s"), filename); + print_info(info_buf, 1); + return; + } + + // re-initialize some stuff after config has been successfully imported + init_main_gui_and_audio(); + fill_cfg_widgets(); + if (snd_reopen_streams() != 0) { + fl_alert(_("butt could not open selected audio device.\nPlease try another device.\n")); + return; + } + update_channel_lists(); + + snprintf(info_buf, sizeof(info_buf), _("Config imported %s"), filename); + print_info(info_buf, 1); +} + +void check_update_at_startup_cb(void) +{ + cfg.main.check_for_update = fl_g->check_update_at_startup->value(); +} + +void check_start_agent_cb(void) +{ + cfg.main.start_agent = fl_g->check_start_agent->value(); +} + +void button_start_agent_cb(void) +{ +#ifdef WIN32 + if (tray_agent_is_running(NULL) == 0) { + if (tray_agent_start() == 0) { + tray_agent_send_cmd(TA_START); + Fl::add_timeout(1, &has_agent_been_started_timer); + } + } + else { + fl_alert("butt agent is already running."); + } +#endif +} + +void button_stop_agent_cb(void) +{ +#ifdef WIN32 + if (tray_agent_is_running(NULL) == 1) { + tray_agent_stop(); + Fl::add_timeout(1, &has_agent_been_stopped_timer); + } + else { + fl_alert("butt agent is currently not running."); + } + +#endif +} + +void check_minimize_to_tray_cb(void) +{ + cfg.main.minimize_to_tray = fl_g->check_minimize_to_tray->value(); + + if (cfg.main.minimize_to_tray == 1) { + fl_g->window_main->minimize_to_tray = true; + } + else { + fl_g->window_main->minimize_to_tray = false; + } +} + +void button_cfg_check_for_updates_cb(void) +{ + int rc; + char uri[100]; + char *new_version; + int ret = update_check_for_new_version(); + + switch (ret) { + case UPDATE_NEW_VERSION: + new_version = update_get_version(); + rc = fl_choice(_("New version available: %s\nYou have version %s"), _("Cancel"), _("Get new version"), NULL, new_version, VERSION); + if (rc == 1) { + // snprintf(uri, sizeof(uri)-1, "https://sourceforge.net/projects/butt/files/butt/butt-%s/", new_version); + snprintf(uri, sizeof(uri) - 1, "https://danielnoethen.de/butt/index.html#_download"); + fl_open_uri(uri); + } + + break; + case UPDATE_SOCKET_ERROR: + fl_alert(_("Could not get update information.\nReason: Network error")); + break; + case UPDATE_ILLEGAL_ANSWER: + fl_alert(_("Could not get update information.\nReason: Unknown answer from server")); + break; + case UPDATE_UP_TO_DATE: + fl_alert(_("You have the latest version!")); + break; + default: + fl_alert(_("Could not get update information.\nReason: Unknown")); + break; + } +} + +void button_cfg_log_browse_cb(void) +{ + Fl_My_Native_File_Chooser nfc; + nfc.title(_("Select logfile...")); + nfc.type(Fl_My_Native_File_Chooser::BROWSE_SAVE_FILE); + nfc.options(Fl_My_Native_File_Chooser::NEW_FOLDER); + + switch (nfc.show()) { + case -1: + fl_alert(_("ERROR: %s"), nfc.errmsg()); + break; + case 1: + break; // cancel + default: + fl_g->input_log_filename->value(nfc.filename()); + input_log_filename_cb(); + } +} + +void window_main_close_cb(bool ask) +{ + if (ask && (connected || recording)) { + int ret; + if (connected) { + fl_message_title("Streaming"); + ret = fl_choice(_("butt is currently streaming.\n" + "Do you really want to close butt now?"), + _("no"), _("yes"), NULL); + } + else { + fl_message_title("Recording"); + ret = fl_choice(_("butt is currently recording.\n" + "Do you really want to close butt now?"), + _("no"), _("yes"), NULL); + } + + if (ret == 0) { + return; + } + } + + stop_recording(false); + button_disconnect_cb(false); + + command_stop_server(); + if (cfg.gui.remember_pos) { + cfg.gui.x_pos = fl_g->window_main->x_root(); + cfg.gui.y_pos = fl_g->window_main->y_root(); + cfg.gui.window_height = fl_g->window_main->h(); + } + + snd_close_streams(); + snd_close_portaudio(); + cfg_write_file(NULL); + url_cleanup_curl(); + exit(0); +} + +void check_cfg_use_app_cb(void) +{ + if (fl_g->check_cfg_use_app->value()) { + int app = fl_g->choice_cfg_app->value(); + current_track_app = getCurrentTrackFunctionFromId(app); + cfg.main.app_update = 1; + cfg.main.app_update_service = app; + + static int reset = 1; + Fl::remove_timeout(&app_timer); + Fl::add_timeout(0.1, &app_timer, &reset); + } + else { + cfg.main.app_update = 0; + Fl::remove_timeout(&app_timer); + + if (cfg.main.song != NULL) { + free(cfg.main.song); + cfg.main.song = NULL; + } + } +} + +void choice_cfg_app_cb(void) +{ + current_track_app = getCurrentTrackFunctionFromId(fl_g->choice_cfg_app->value()); + cfg.main.app_update_service = fl_g->choice_cfg_app->value(); +} + +void radio_cfg_artist_title_cb(void) +{ + cfg.main.app_artist_title_order = APP_ARTIST_FIRST; +} + +void radio_cfg_title_artist_cb(void) +{ + cfg.main.app_artist_title_order = APP_TITLE_FIRST; +} + +void input_cfg_song_url_cb(void) +{ + const char *http = "http://"; + const char *https = "https://"; + const char *url = fl_g->input_cfg_song_url->value(); + int len = strlen(url); + + // Check if the URL starts with either prefix + if (len > 0 && strncmp(url, http, strlen(http)) != 0 && strncmp(url, https, strlen(https)) != 0) { + fl_alert(_("The URL must start with either http:// or https://")); + fl_g->input_cfg_song_url->value(cfg.main.song_update_url); + } + + cfg.main.song_update_url = (char *)realloc(cfg.main.song_update_url, len + 1); + strcpy(cfg.main.song_update_url, url); + fl_g->input_cfg_song_url->tooltip(cfg.main.song_update_url); +} + +void input_cfg_url_update_song_interval_cb(void) +{ + if (fl_g->input_cfg_url_update_song_interval->value() < 1 || fl_g->input_cfg_url_update_song_interval->value() > 1000) { + fl_alert(_("Value must be a number between 1 and 1000")); + fl_g->input_cfg_url_update_song_interval->value(cfg.main.song_update_url_interval); + return; + } + + cfg.main.song_update_url_interval = fl_g->input_cfg_url_update_song_interval->value(); +} + +void check_cfg_update_from_url_cb(void) +{ + cfg.main.song_update_url_active = fl_g->check_cfg_update_from_url->value(); + + if (cfg.main.song_update_url_active) { + Fl::remove_timeout(&song_url_timer); + Fl::add_timeout(cfg.main.song_update_url_interval, &song_url_timer); + } + else { + Fl::remove_timeout(&song_url_timer); + } +} + +void choice_cfg_song_delay_cb(void) +{ + cfg.main.song_delay = 2 * fl_g->choice_cfg_song_delay->value(); +} + +void slider_mixer_primary_device_cb(double val, void *called_by) +{ + if (called_by != (void *)CB_CALLED_BY_MIDI) { + cfg.midi.commands[MIDI_CMD_PRIMARY_DEV_VOL].picked_up = 0; + } + + char str[10]; + snprintf(str, 10, "%+.1f dB", val); + fl_g->text_mixer_primary_device_volume->copy_label(str); + fl_g->slider_mixer_primary_device->value_cb2("dB"); // updates the tooltip + + if (val > -0.5 && val < 0.5) { + cfg.mixer.primary_device_gain = 1; + fl_g->slider_mixer_primary_device->value(0); + } + else { + cfg.mixer.primary_device_gain = util_db_to_factor(val); + } +} + +void slider_mixer_secondary_device_cb(double val, void *called_by) +{ + if (called_by != (void *)CB_CALLED_BY_MIDI) { + cfg.midi.commands[MIDI_CMD_SECONDARY_DEV_VOL].picked_up = 0; + } + + char str[10]; + snprintf(str, 10, "%+.1f dB", val); + fl_g->text_mixer_secondary_device_volume->copy_label(str); + fl_g->slider_mixer_secondary_device->value_cb2("dB"); + + if (val > -0.5 && val < 0.5) { + cfg.mixer.secondary_device_gain = 1; + fl_g->slider_mixer_secondary_device->value(0); + } + else { + cfg.mixer.secondary_device_gain = util_db_to_factor(val); + } +} + +void slider_mixer_streaming_gain_cb(double val, void *called_by) +{ + if (called_by != (void *)CB_CALLED_BY_MIDI) { + cfg.midi.commands[MIDI_CMD_STREAMING_GAIN].picked_up = 0; + } + + char str[10]; + snprintf(str, 10, "%+.1f dB", val); + fl_g->text_mixer_streaming_volume->copy_label(str); + fl_g->slider_mixer_streaming_gain->value_cb2("dB"); + + if (val > -0.5 && val < 0.5) { + cfg.mixer.streaming_gain = 1; + fl_g->slider_mixer_streaming_gain->value(0); + } + else { + cfg.mixer.streaming_gain = util_db_to_factor(val); + } +} + +void slider_mixer_recording_gain_cb(double val, void *called_by) +{ + if (called_by != (void *)CB_CALLED_BY_MIDI) { + cfg.midi.commands[MIDI_CMD_RECORDING_GAIN].picked_up = 0; + } + + char str[10]; + snprintf(str, 10, "%+.1f dB", val); + fl_g->text_mixer_recording_volume->copy_label(str); + fl_g->slider_mixer_recording_gain->value_cb2("dB"); + + if (val > -0.5 && val < 0.5) { + cfg.mixer.recording_gain = 1; + fl_g->slider_mixer_recording_gain->value(0); + } + else { + cfg.mixer.recording_gain = util_db_to_factor(val); + } +} +void slider_mixer_master_gain_cb(double val, void *called_by) +{ + if (called_by != (void *)CB_CALLED_BY_MIDI) { + cfg.midi.commands[MIDI_CMD_MASTER_GAIN].picked_up = 0; + } + + char str[10]; + snprintf(str, 10, "%+.1f dB", val); + fl_g->text_mixer_master_volume->copy_label(str); + fl_g->slider_mixer_master_gain->value_cb2("dB"); + + if (val > -0.5 && val < 0.5) { + cfg.main.gain = 1; + fl_g->slider_mixer_master_gain->value(0); + fl_g->slider_gain->value(0); + } + else { + cfg.main.gain = util_db_to_factor(val); + fl_g->slider_gain->value(val); + } + // Without redrawing the main window the slider knob is not redrawn correctly + fl_g->window_main->redraw(); +} + +void slider_mixer_cross_fader_cb(double val, void *called_by) +{ + if (called_by != (void *)CB_CALLED_BY_MIDI) { + cfg.midi.commands[MIDI_CMD_CROSS_FADER].picked_up = 0; + // TOOD: Check if soft takeover works for all sliders + } + + fl_g->slider_mixer_cross_fader->value_cb2(""); + + if (val > -3.0 && val < 3.0) { + cfg.mixer.cross_fader = 0; + fl_g->slider_mixer_cross_fader->value(0); + } + else { + cfg.mixer.cross_fader = val; + } + + if (cfg.mixer.cross_fader == 0) { + cfg.mixer.primary_X_fader = 1.0; + cfg.mixer.secondary_X_fader = 1.0; + } + else if (cfg.mixer.cross_fader < 0) { + cfg.mixer.primary_X_fader = 1.0; + cfg.mixer.secondary_X_fader = 1 + (val / 100.0); + } + else { + cfg.mixer.primary_X_fader = 1 - (val / 100.0); + cfg.mixer.secondary_X_fader = 1.0; + } + + // Without redrawing the mixer window the slider knob is not redrawn correctly + fl_g->window_mixer->redraw(); +} + +void button_mixer_mute_primary_device_cb(void) +{ + cfg.mixer.primary_device_muted = fl_g->button_mixer_mute_primary_device->value(); + if (cfg.mixer.primary_device_muted == 1) { + fl_g->slider_mixer_primary_device->deactivate(); + fl_g->text_mixer_primary_device_volume->deactivate(); + } + else { + fl_g->slider_mixer_primary_device->activate(); + fl_g->text_mixer_primary_device_volume->activate(); + } +} + +void button_mixer_mute_secondary_device_cb(void) +{ + cfg.mixer.secondary_device_muted = fl_g->button_mixer_mute_secondary_device->value(); + if (cfg.mixer.secondary_device_muted == 1) { + fl_g->slider_mixer_secondary_device->deactivate(); + fl_g->text_mixer_secondary_device_volume->deactivate(); + } + else { + fl_g->slider_mixer_secondary_device->activate(); + fl_g->text_mixer_secondary_device_volume->activate(); + } +} + +void button_mixer_reset_cb(void) +{ + slider_mixer_primary_device_cb(0, (void *)CB_CALLED_BY_CODE); + fl_g->slider_mixer_primary_device->value(0); + + slider_mixer_secondary_device_cb(0, (void *)CB_CALLED_BY_CODE); + fl_g->slider_mixer_secondary_device->value(0); + + slider_mixer_streaming_gain_cb(0, (void *)CB_CALLED_BY_CODE); + fl_g->slider_mixer_streaming_gain->value(0); + + slider_mixer_recording_gain_cb(0, (void *)CB_CALLED_BY_CODE); + fl_g->slider_mixer_recording_gain->value(0); + + slider_mixer_master_gain_cb(0, (void *)CB_CALLED_BY_CODE); + fl_g->slider_mixer_master_gain->value(0); + + slider_mixer_cross_fader_cb(0, (void *)CB_CALLED_BY_CODE); + fl_g->slider_mixer_cross_fader->value(0); + + if (cfg.mixer.primary_device_muted == 1) { + fl_g->button_mixer_mute_primary_device->value(0); + button_mixer_mute_primary_device_cb(); + } + + if (cfg.mixer.secondary_device_muted == 1) { + fl_g->button_mixer_mute_secondary_device->value(0); + button_mixer_mute_secondary_device_cb(); + } +} + +void check_stream_eq_cb(void) +{ + cfg.dsp.equalizer_stream = fl_g->check_stream_eq->value(); +} + +void check_rec_eq_cb(void) +{ + cfg.dsp.equalizer_rec = fl_g->check_rec_eq->value(); +} + +void choice_eq_preset_cb(void) +{ + int preset_id = fl_g->choice_eq_preset->value(); + const char *preset = fl_g->choice_eq_preset->text(preset_id); + + if (preset_id == 0) { // The string "Manual" is localized, therefore we check the id which will always be the first menu item + // dsp->loadEQPreset("Manual"); + slider_equalizer1_cb(cfg.dsp.eq_gain[0]); + fl_g->equalizerSlider1->value(cfg.dsp.eq_gain[0]); + + slider_equalizer2_cb(cfg.dsp.eq_gain[1]); + fl_g->equalizerSlider2->value(cfg.dsp.eq_gain[1]); + + slider_equalizer3_cb(cfg.dsp.eq_gain[2]); + fl_g->equalizerSlider3->value(cfg.dsp.eq_gain[2]); + + slider_equalizer4_cb(cfg.dsp.eq_gain[3]); + fl_g->equalizerSlider4->value(cfg.dsp.eq_gain[3]); + + slider_equalizer5_cb(cfg.dsp.eq_gain[4]); + fl_g->equalizerSlider5->value(cfg.dsp.eq_gain[4]); + + slider_equalizer6_cb(cfg.dsp.eq_gain[5]); + fl_g->equalizerSlider6->value(cfg.dsp.eq_gain[5]); + + slider_equalizer7_cb(cfg.dsp.eq_gain[6]); + fl_g->equalizerSlider7->value(cfg.dsp.eq_gain[6]); + + slider_equalizer8_cb(cfg.dsp.eq_gain[7]); + fl_g->equalizerSlider8->value(cfg.dsp.eq_gain[7]); + + slider_equalizer9_cb(cfg.dsp.eq_gain[8]); + fl_g->equalizerSlider9->value(cfg.dsp.eq_gain[8]); + + slider_equalizer10_cb(cfg.dsp.eq_gain[9]); + fl_g->equalizerSlider10->value(cfg.dsp.eq_gain[9]); + + cfg.dsp.eq_preset = (char *)realloc(cfg.dsp.eq_preset, strlen("Manual") + 1); + strcpy(cfg.dsp.eq_preset, "Manual"); + } + else { + double val; + char str[10]; + + val = streaming_dsp->getEQbandFromPreset(0, preset); + snprintf(str, sizeof(str), "%+.1f", val); + fl_g->equalizerGain1->copy_label(str); + fl_g->equalizerSlider1->value(val); + fl_g->equalizerSlider1->value_cb2("dB"); // updates the tooltip + streaming_dsp->setEQband(0, val); + recording_dsp->setEQband(0, val); + + val = streaming_dsp->getEQbandFromPreset(1, preset); + snprintf(str, sizeof(str), "%+.1f", val); + fl_g->equalizerGain2->copy_label(str); + fl_g->equalizerSlider2->value(val); + fl_g->equalizerSlider2->value_cb2("dB"); + streaming_dsp->setEQband(1, val); + recording_dsp->setEQband(1, val); + + val = streaming_dsp->getEQbandFromPreset(2, preset); + snprintf(str, sizeof(str), "%+.1f", val); + fl_g->equalizerGain3->copy_label(str); + fl_g->equalizerSlider3->value(val); + fl_g->equalizerSlider3->value_cb2("dB"); + streaming_dsp->setEQband(2, val); + recording_dsp->setEQband(2, val); + + val = streaming_dsp->getEQbandFromPreset(3, preset); + snprintf(str, sizeof(str), "%+.1f", val); + fl_g->equalizerGain4->copy_label(str); + fl_g->equalizerSlider4->value(val); + fl_g->equalizerSlider4->value_cb2("dB"); + streaming_dsp->setEQband(3, val); + recording_dsp->setEQband(3, val); + + val = streaming_dsp->getEQbandFromPreset(4, preset); + snprintf(str, sizeof(str), "%+.1f", val); + fl_g->equalizerGain5->copy_label(str); + fl_g->equalizerSlider5->value(val); + fl_g->equalizerSlider5->value_cb2("dB"); + streaming_dsp->setEQband(4, val); + recording_dsp->setEQband(4, val); + + val = streaming_dsp->getEQbandFromPreset(5, preset); + snprintf(str, sizeof(str), "%+.1f", val); + fl_g->equalizerGain6->copy_label(str); + fl_g->equalizerSlider6->value(val); + fl_g->equalizerSlider6->value_cb2("dB"); + streaming_dsp->setEQband(5, val); + recording_dsp->setEQband(5, val); + + val = streaming_dsp->getEQbandFromPreset(6, preset); + snprintf(str, sizeof(str), "%+.1f", val); + fl_g->equalizerGain7->copy_label(str); + fl_g->equalizerSlider7->value(val); + fl_g->equalizerSlider7->value_cb2("dB"); + streaming_dsp->setEQband(6, val); + recording_dsp->setEQband(6, val); + + val = streaming_dsp->getEQbandFromPreset(7, preset); + snprintf(str, sizeof(str), "%+.1f", val); + fl_g->equalizerGain8->copy_label(str); + fl_g->equalizerSlider8->value(val); + fl_g->equalizerSlider8->value_cb2("dB"); + streaming_dsp->setEQband(7, val); + recording_dsp->setEQband(7, val); + + val = streaming_dsp->getEQbandFromPreset(8, preset); + snprintf(str, sizeof(str), "%+.1f", val); + fl_g->equalizerGain9->copy_label(str); + fl_g->equalizerSlider9->value(val); + fl_g->equalizerSlider9->value_cb2("dB"); + streaming_dsp->setEQband(8, val); + recording_dsp->setEQband(8, val); + + val = streaming_dsp->getEQbandFromPreset(9, preset); + snprintf(str, sizeof(str), "%+.1f", val); + fl_g->equalizerGain10->copy_label(str); + fl_g->equalizerSlider10->value(val); + fl_g->equalizerSlider10->value_cb2("dB"); + streaming_dsp->setEQband(9, val); + recording_dsp->setEQband(9, val); + + cfg.dsp.eq_preset = (char *)realloc(cfg.dsp.eq_preset, strlen(preset) + 1); + strcpy(cfg.dsp.eq_preset, preset); + } +} + +void button_eq_reset_cb(void) +{ + fl_g->equalizerSlider1->value(0); + fl_g->equalizerSlider2->value(0); + fl_g->equalizerSlider3->value(0); + fl_g->equalizerSlider4->value(0); + fl_g->equalizerSlider5->value(0); + fl_g->equalizerSlider6->value(0); + fl_g->equalizerSlider7->value(0); + fl_g->equalizerSlider8->value(0); + fl_g->equalizerSlider9->value(0); + fl_g->equalizerSlider10->value(0); + slider_equalizer1_cb(0); + slider_equalizer2_cb(0); + slider_equalizer3_cb(0); + slider_equalizer4_cb(0); + slider_equalizer5_cb(0); + slider_equalizer6_cb(0); + slider_equalizer7_cb(0); + slider_equalizer8_cb(0); + slider_equalizer9_cb(0); + slider_equalizer10_cb(0); +} + +void slider_equalizer1_cb(double v) +{ + char str[10]; + + cfg.dsp.eq_gain[0] = v; + snprintf(str, 10, "%+.1f", v); + fl_g->equalizerGain1->copy_label(str); + fl_g->equalizerSlider1->value_cb2("dB"); // updates the tooltip + streaming_dsp->setEQband(0, v); + recording_dsp->setEQband(0, v); + + // If the an EQ slider is moved while a preset is selected we switch to manual mode + // and set the manual EQ sliders to the values of the preset + if (fl_g->choice_eq_preset->value() != 0) { + fl_g->choice_eq_preset->value(0); + read_eq_slider_values(); + cfg.dsp.eq_preset = (char *)realloc(cfg.dsp.eq_preset, strlen("Manual") + 1); + strcpy(cfg.dsp.eq_preset, "Manual"); + } +} + +void slider_equalizer2_cb(double v) +{ + char str[10]; + + cfg.dsp.eq_gain[1] = v; + snprintf(str, 10, "%+.1f", v); + fl_g->equalizerGain2->copy_label(str); + fl_g->equalizerSlider2->value_cb2("dB"); + streaming_dsp->setEQband(1, v); + recording_dsp->setEQband(1, v); + + if (fl_g->choice_eq_preset->value() != 0) { + fl_g->choice_eq_preset->value(0); + read_eq_slider_values(); + cfg.dsp.eq_preset = (char *)realloc(cfg.dsp.eq_preset, strlen("Manual") + 1); + strcpy(cfg.dsp.eq_preset, "Manual"); + } +} + +void slider_equalizer3_cb(double v) +{ + char str[10]; + + cfg.dsp.eq_gain[2] = v; + snprintf(str, 10, "%+.1f", v); + fl_g->equalizerGain3->copy_label(str); + fl_g->equalizerSlider3->value_cb2("dB"); + streaming_dsp->setEQband(2, v); + recording_dsp->setEQband(2, v); + + if (fl_g->choice_eq_preset->value() != 0) { + fl_g->choice_eq_preset->value(0); + read_eq_slider_values(); + cfg.dsp.eq_preset = (char *)realloc(cfg.dsp.eq_preset, strlen("Manual") + 1); + strcpy(cfg.dsp.eq_preset, "Manual"); + } +} + +void slider_equalizer4_cb(double v) +{ + char str[10]; + + cfg.dsp.eq_gain[3] = v; + snprintf(str, 10, "%+.1f", v); + fl_g->equalizerGain4->copy_label(str); + fl_g->equalizerSlider4->value_cb2("dB"); + streaming_dsp->setEQband(3, v); + recording_dsp->setEQband(3, v); + + if (fl_g->choice_eq_preset->value() != 0) { + fl_g->choice_eq_preset->value(0); + read_eq_slider_values(); + cfg.dsp.eq_preset = (char *)realloc(cfg.dsp.eq_preset, strlen("Manual") + 1); + strcpy(cfg.dsp.eq_preset, "Manual"); + } +} + +void slider_equalizer5_cb(double v) +{ + char str[10]; + + cfg.dsp.eq_gain[4] = v; + snprintf(str, 10, "%+.1f", v); + fl_g->equalizerGain5->copy_label(str); + fl_g->equalizerSlider5->value_cb2("dB"); + streaming_dsp->setEQband(4, v); + recording_dsp->setEQband(4, v); + + if (fl_g->choice_eq_preset->value() != 0) { + fl_g->choice_eq_preset->value(0); + read_eq_slider_values(); + cfg.dsp.eq_preset = (char *)realloc(cfg.dsp.eq_preset, strlen("Manual") + 1); + strcpy(cfg.dsp.eq_preset, "Manual"); + } +} + +void slider_equalizer6_cb(double v) +{ + char str[10]; + + cfg.dsp.eq_gain[5] = v; + snprintf(str, 10, "%+.1f", v); + fl_g->equalizerGain6->copy_label(str); + fl_g->equalizerSlider6->value_cb2("dB"); + streaming_dsp->setEQband(5, v); + recording_dsp->setEQband(5, v); + + if (fl_g->choice_eq_preset->value() != 0) { + fl_g->choice_eq_preset->value(0); + read_eq_slider_values(); + cfg.dsp.eq_preset = (char *)realloc(cfg.dsp.eq_preset, strlen("Manual") + 1); + strcpy(cfg.dsp.eq_preset, "Manual"); + } +} + +void slider_equalizer7_cb(double v) +{ + char str[10]; + + cfg.dsp.eq_gain[6] = v; + snprintf(str, 10, "%+.1f", v); + fl_g->equalizerGain7->copy_label(str); + fl_g->equalizerSlider7->value_cb2("dB"); + streaming_dsp->setEQband(6, v); + recording_dsp->setEQband(6, v); + + if (fl_g->choice_eq_preset->value() != 0) { + fl_g->choice_eq_preset->value(0); + read_eq_slider_values(); + cfg.dsp.eq_preset = (char *)realloc(cfg.dsp.eq_preset, strlen("Manual") + 1); + strcpy(cfg.dsp.eq_preset, "Manual"); + } +} + +void slider_equalizer8_cb(double v) +{ + char str[10]; + + cfg.dsp.eq_gain[7] = v; + snprintf(str, 10, "%+.1f", v); + fl_g->equalizerGain8->copy_label(str); + fl_g->equalizerSlider8->value_cb2("dB"); + streaming_dsp->setEQband(7, v); + recording_dsp->setEQband(7, v); + + if (fl_g->choice_eq_preset->value() != 0) { + fl_g->choice_eq_preset->value(0); + read_eq_slider_values(); + cfg.dsp.eq_preset = (char *)realloc(cfg.dsp.eq_preset, strlen("Manual") + 1); + strcpy(cfg.dsp.eq_preset, "Manual"); + } +} + +void slider_equalizer9_cb(double v) +{ + char str[10]; + + cfg.dsp.eq_gain[8] = v; + snprintf(str, 10, "%+.1f", v); + fl_g->equalizerGain9->copy_label(str); + fl_g->equalizerSlider9->value_cb2("dB"); + streaming_dsp->setEQband(8, v); + recording_dsp->setEQband(8, v); + + if (fl_g->choice_eq_preset->value() != 0) { + fl_g->choice_eq_preset->value(0); + read_eq_slider_values(); + cfg.dsp.eq_preset = (char *)realloc(cfg.dsp.eq_preset, strlen("Manual") + 1); + strcpy(cfg.dsp.eq_preset, "Manual"); + } +} + +void slider_equalizer10_cb(double v) +{ + char str[10]; + + cfg.dsp.eq_gain[9] = v; + snprintf(str, 10, "%+.1f", v); + fl_g->equalizerGain10->copy_label(str); + fl_g->equalizerSlider10->value_cb2("dB"); + streaming_dsp->setEQband(9, v); + recording_dsp->setEQband(9, v); + + if (fl_g->choice_eq_preset->value() != 0) { + fl_g->choice_eq_preset->value(0); + read_eq_slider_values(); + cfg.dsp.eq_preset = (char *)realloc(cfg.dsp.eq_preset, strlen("Manual") + 1); + strcpy(cfg.dsp.eq_preset, "Manual"); + } +} + +void check_stream_drc_cb(void) +{ + cfg.dsp.compressor_stream = fl_g->check_stream_drc->value(); + + if (cfg.dsp.compressor_stream == 0) { + fl_g->LED_comp_threshold->set_state(LED::LED_OFF); + } + + // Make sure compressor starts in a clean state + snd_reset_streaming_compressor(); +} + +void check_rec_drc_cb(void) +{ + cfg.dsp.compressor_rec = fl_g->check_rec_drc->value(); + + if (cfg.dsp.compressor_rec == 0) { + fl_g->LED_comp_threshold->set_state(LED::LED_OFF); + } + + snd_reset_recording_compressor(); +} + +void button_drc_reset_cb(void) +{ + fl_g->thresholdSlider->value(-20); + fl_g->ratioSlider->value(5); + fl_g->attackSlider->value(0.01); + fl_g->releaseSlider->value(1); + fl_g->makeupSlider->value(0); + slider_threshold_cb(-20); + slider_ratio_cb(5); + slider_attack_cb(0.01); + slider_release_cb(1); + slider_makeup_cb(0); +} + +void check_aggressive_mode_cb(void) +{ + cfg.dsp.aggressive_mode = fl_g->check_aggressive_mode->value(); + snd_reset_streaming_compressor(); + snd_reset_recording_compressor(); +} + +void slider_threshold_cb(double v) +{ + static char str[10]; + cfg.dsp.threshold = v; + snprintf(str, 10, "%+.1f", v); + fl_g->threshold->label(str); + fl_g->thresholdSlider->value_cb2("dBFS"); // updates the tooltip + + snd_reset_streaming_compressor(); + snd_reset_recording_compressor(); +} + +void slider_ratio_cb(double v) +{ + static char str[10]; + cfg.dsp.ratio = v; + snprintf(str, 10, "%.1f", v); + fl_g->ratio->label(str); + fl_g->ratioSlider->value_cb2(":1"); + + snd_reset_streaming_compressor(); + snd_reset_recording_compressor(); +} + +void slider_attack_cb(double v) +{ + static char str[10]; + cfg.dsp.attack = v; + snprintf(str, 10, "%.2fs", v); + fl_g->attack->label(str); + fl_g->attackSlider->value_cb2("s"); + + snd_reset_streaming_compressor(); + snd_reset_recording_compressor(); +} + +void slider_release_cb(double v) +{ + static char str[10]; + cfg.dsp.release = v; + snprintf(str, 10, "%.2fs", v); + fl_g->release->label(str); + fl_g->releaseSlider->value_cb2("s"); + + snd_reset_streaming_compressor(); + snd_reset_recording_compressor(); +} + +void slider_makeup_cb(double v) +{ + static char str[10]; + cfg.dsp.makeup_gain = v; + snprintf(str, 10, "%+.1f", v); + fl_g->makeup->label(str); + fl_g->makeupSlider->value_cb2("dB"); +} + +void choice_stream_mp3_enc_quality_cb(void) +{ + lame_enc test_enc; + + test_enc = lame_stream; + test_enc.gfp = NULL; + test_enc.enc_quality = fl_g->choice_stream_mp3_enc_quality->value(); + + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_stream.enc_quality = fl_g->choice_stream_mp3_enc_quality->value(); + lame_stream.enc_quality = fl_g->choice_stream_mp3_enc_quality->value(); + + lame_enc_reinit(&lame_stream); + lame_enc_close(&test_enc); + } + else { + printf("choice_stream_mp3_enc_quality_cb: Illegal value\n"); + } +} +void choice_stream_mp3_stereo_mode_cb(void) +{ + lame_enc test_enc; + + test_enc = lame_stream; + test_enc.gfp = NULL; + test_enc.stereo_mode = fl_g->choice_stream_mp3_stereo_mode->value() - 1; + + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_stream.stereo_mode = fl_g->choice_stream_mp3_stereo_mode->value(); + lame_stream.stereo_mode = fl_g->choice_stream_mp3_stereo_mode->value() - 1; + + lame_enc_reinit(&lame_stream); + lame_enc_close(&test_enc); + } + else { + printf("choice_stream_mp3_stereo_mode_cb: Illegal value\n"); + } +} +void choice_stream_mp3_bitrate_mode_cb(void) +{ + lame_enc test_enc; + + test_enc = lame_stream; + test_enc.gfp = NULL; + test_enc.bitrate_mode = fl_g->choice_stream_mp3_bitrate_mode->value(); + + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_stream.bitrate_mode = fl_g->choice_stream_mp3_bitrate_mode->value(); + lame_stream.bitrate_mode = fl_g->choice_stream_mp3_bitrate_mode->value(); + + lame_enc_reinit(&lame_stream); + lame_enc_close(&test_enc); + } + else { + printf("choice_stream_mp3_bitrate_mode_cb: Illegal value\n"); + } +} +void choice_stream_mp3_vbr_quality_cb(void) +{ + lame_enc test_enc; + + test_enc = lame_stream; + test_enc.gfp = NULL; + test_enc.vbr_quality = fl_g->choice_stream_mp3_vbr_quality->value(); + + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_stream.vbr_quality = fl_g->choice_stream_mp3_vbr_quality->value(); + lame_stream.vbr_quality = fl_g->choice_stream_mp3_vbr_quality->value(); + + lame_enc_reinit(&lame_stream); + lame_enc_close(&test_enc); + } + else { + printf("choice_stream_mp3_vbr_quality_cb: Illegal value\n"); + } +} +void choice_stream_mp3_vbr_min_bitrate_cb(void) +{ + int *br_list; + get_bitrate_list_for_codec(CHOICE_MP3, &br_list); + + lame_enc test_enc; + + test_enc = lame_stream; + test_enc.gfp = NULL; + test_enc.vbr_min_bitrate = br_list[fl_g->choice_stream_mp3_vbr_min_bitrate->value()]; + + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_stream.vbr_min_bitrate = br_list[fl_g->choice_stream_mp3_vbr_min_bitrate->value()]; + lame_stream.vbr_min_bitrate = br_list[fl_g->choice_stream_mp3_vbr_min_bitrate->value()]; + + lame_enc_reinit(&lame_stream); + lame_enc_close(&test_enc); + } + else { + printf("choice_stream_mp3_vbr_min_bitrate_cb: Illegal value\n"); + } +} +void choice_stream_mp3_vbr_max_bitrate_cb(void) +{ + int *br_list; + get_bitrate_list_for_codec(CHOICE_MP3, &br_list); + + lame_enc test_enc; + + test_enc = lame_stream; + test_enc.gfp = NULL; + test_enc.vbr_max_bitrate = br_list[fl_g->choice_stream_mp3_vbr_max_bitrate->value()]; + + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_stream.vbr_max_bitrate = br_list[fl_g->choice_stream_mp3_vbr_max_bitrate->value()]; + lame_stream.vbr_max_bitrate = br_list[fl_g->choice_stream_mp3_vbr_max_bitrate->value()]; + + lame_enc_reinit(&lame_stream); + lame_enc_close(&test_enc); + } + else { + printf("choice_stream_mp3_vbr_max_bitrate_cb: Illegal value\n"); + } +} + +void check_stream_mp3_force_min_bitrate_cb(void) +{ + cfg.mp3_codec_stream.vbr_force_min_bitrate = fl_g->check_stream_mp3_force_min_bitrate->value(); + lame_stream.vbr_force_min_bitrate = cfg.mp3_codec_stream.vbr_force_min_bitrate; + lame_enc_reinit(&lame_stream); +} + +void choice_stream_mp3_resampling_freq_cb(void) +{ + int val = fl_g->choice_stream_mp3_resampling_freq->value(); + + lame_enc test_enc; + test_enc = lame_stream; + test_enc.gfp = NULL; + + switch (val) { + case CHOICE_MP3_RESAMPLING_DISABLED: + test_enc.samplerate_out = test_enc.samplerate_in; + break; + case CHOICE_MP3_RESAMPLING_8000: + test_enc.samplerate_out = 8000; + break; + case CHOICE_MP3_RESAMPLING_11025: + test_enc.samplerate_out = 11025; + break; + case CHOICE_MP3_RESAMPLING_12000: + test_enc.samplerate_out = 12000; + break; + case CHOICE_MP3_RESAMPLING_16000: + test_enc.samplerate_out = 16000; + break; + case CHOICE_MP3_RESAMPLING_22050: + test_enc.samplerate_out = 22050; + break; + case CHOICE_MP3_RESAMPLING_24000: + test_enc.samplerate_out = 24000; + break; + case CHOICE_MP3_RESAMPLING_32000: + test_enc.samplerate_out = 32000; + break; + case CHOICE_MP3_RESAMPLING_44100: + test_enc.samplerate_out = 44100; + break; + case CHOICE_MP3_RESAMPLING_48000: + test_enc.samplerate_out = 48000; + break; + default: + printf("illegal resampling frequency provdided\n"); + return; + } + + if (lame_enc_init(&test_enc) == 0) { + if (val == CHOICE_MP3_RESAMPLING_DISABLED) { + cfg.mp3_codec_stream.resampling_freq = CHOICE_MP3_RESAMPLING_DISABLED; + } + else { + cfg.mp3_codec_stream.resampling_freq = test_enc.samplerate_out; + } + + lame_stream.samplerate_out = test_enc.samplerate_out; + + lame_enc_reinit(&lame_stream); + lame_enc_close(&test_enc); + } + else { + fl_alert(_("The encoder could not be initialized with the provided parameters.")); + } +} + +void check_stream_mp3_activate_lowpass_freq_cb(void) +{ + cfg.mp3_codec_stream.lowpass_freq_active = fl_g->check_stream_mp3_activate_lowpass_freq->value(); + cfg.mp3_codec_stream.lowpass_freq_active == 1 ? fl_g->input_stream_mp3_lowpass_freq->activate() : fl_g->input_stream_mp3_lowpass_freq->deactivate(); + + lame_stream.lowpass_freq = cfg.mp3_codec_stream.lowpass_freq * cfg.mp3_codec_stream.lowpass_freq_active; + lame_enc_reinit(&lame_stream); +} + +void input_stream_mp3_lowpass_freq_cb(void) +{ + float val = fl_g->input_stream_mp3_lowpass_freq->value(); + + if (val < 0.001 || val > 50.0) { + fl_alert(_("The value must be between 0.001 kHz and 50 kHz")); + fl_g->input_stream_mp3_lowpass_freq->value(cfg.mp3_codec_stream.lowpass_freq); + return; + } + + lame_enc test_enc; + test_enc = lame_stream; + test_enc.gfp = NULL; + test_enc.lowpass_freq = val; + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_stream.lowpass_freq = val; + lame_stream.lowpass_freq = val; + + lame_enc_reinit(&lame_stream); + lame_enc_close(&test_enc); + } + else { + fl_alert(_("The encoder could not be initialized with the provided parameters.")); + } +} + +void check_stream_mp3_activate_lowpass_width_cb(void) +{ + cfg.mp3_codec_stream.lowpass_width_active = fl_g->check_stream_mp3_activate_lowpass_width->value(); + cfg.mp3_codec_stream.lowpass_width_active == 1 ? fl_g->input_stream_mp3_lowpass_width->activate() : fl_g->input_stream_mp3_lowpass_width->deactivate(); + + lame_stream.lowpass_width = cfg.mp3_codec_stream.lowpass_width * cfg.mp3_codec_stream.lowpass_width_active; + lame_enc_reinit(&lame_stream); +} + +void input_stream_mp3_lowpass_width_cb(void) +{ + float val = fl_g->input_stream_mp3_lowpass_width->value(); + + if (val < 0.001 || val > 16.0) { + fl_alert(_("The value must be between 0.001 kHz and 16 kHz")); + fl_g->input_stream_mp3_lowpass_width->value(cfg.mp3_codec_stream.lowpass_width); + return; + } + + lame_enc test_enc; + test_enc = lame_stream; + test_enc.gfp = NULL; + test_enc.lowpass_width = val; + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_stream.lowpass_width = val; + lame_stream.lowpass_width = val; + + lame_enc_reinit(&lame_stream); + lame_enc_close(&test_enc); + } + else { + fl_alert(_("The encoder could not be initialized with the provided parameters.")); + } +} + +void check_stream_mp3_activate_highpass_freq_cb(void) +{ + cfg.mp3_codec_stream.highpass_freq_active = fl_g->check_stream_mp3_activate_highpass_freq->value(); + cfg.mp3_codec_stream.highpass_freq_active == 1 ? fl_g->input_stream_mp3_highpass_freq->activate() : fl_g->input_stream_mp3_highpass_freq->deactivate(); + + lame_stream.highpass_freq = cfg.mp3_codec_stream.highpass_freq * cfg.mp3_codec_stream.highpass_freq_active; + lame_enc_reinit(&lame_stream); +} + +void input_stream_mp3_highpass_freq_cb(void) +{ + float val = fl_g->input_stream_mp3_highpass_freq->value(); + + if (val < 0.001 || val > 16.0) { + fl_alert(_("The value must be between 0.001 kHz and 16 kHz")); + fl_g->input_stream_mp3_highpass_freq->value(cfg.mp3_codec_stream.highpass_freq); + return; + } + + lame_enc test_enc; + test_enc = lame_stream; + test_enc.gfp = NULL; + test_enc.highpass_freq = val; + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_stream.highpass_freq = val; + lame_stream.highpass_freq = val; + + lame_enc_reinit(&lame_stream); + lame_enc_close(&test_enc); + } + else { + fl_alert(_("The encoder could not be initialized with the provided parameters.")); + } +} + +void check_stream_mp3_activate_highpass_width_cb(void) +{ + cfg.mp3_codec_stream.highpass_width_active = fl_g->check_stream_mp3_activate_highpass_width->value(); + cfg.mp3_codec_stream.highpass_width_active == 1 ? fl_g->input_stream_mp3_highpass_width->activate() : fl_g->input_stream_mp3_highpass_width->deactivate(); + + lame_stream.highpass_width = cfg.mp3_codec_stream.highpass_width * cfg.mp3_codec_stream.highpass_width_active; + lame_enc_reinit(&lame_stream); +} + +void input_stream_mp3_highpass_width_cb(void) +{ + float val = fl_g->input_stream_mp3_highpass_width->value(); + + if (val < 0.001 || val > 16.0) { + fl_alert(_("The value must be between 0.001 kHz and 16 kHz")); + fl_g->input_stream_mp3_highpass_width->value(cfg.mp3_codec_stream.highpass_width); + return; + } + + lame_enc test_enc; + test_enc = lame_stream; + test_enc.gfp = NULL; + test_enc.highpass_width = val; + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_stream.highpass_width = val; + lame_stream.highpass_width = val; + + lame_enc_reinit(&lame_stream); + lame_enc_close(&test_enc); + } + else { + fl_alert(_("The encoder could not be initialized with the provided parameters.")); + } +} + +void choice_stream_vorbis_bitrate_mode_cb(void) +{ + vorbis_enc test_enc; + + test_enc = vorbis_stream; + test_enc.bitrate_mode = fl_g->choice_stream_vorbis_bitrate_mode->value(); + + if (vorbis_enc_init(&test_enc) == 0) { + cfg.vorbis_codec_stream.bitrate_mode = fl_g->choice_stream_vorbis_bitrate_mode->value(); + vorbis_stream.bitrate_mode = fl_g->choice_stream_vorbis_bitrate_mode->value(); + + vorbis_enc_reinit(&vorbis_stream); + vorbis_enc_close(&test_enc); + } + else { + fl_g->choice_stream_vorbis_bitrate_mode->value(cfg.vorbis_codec_stream.bitrate_mode); + printf("choice_stream_vorbis_bitrate_mode_cb: Illegal value\n"); + } +} + +void choice_stream_vorbis_vbr_quality_cb(void) +{ + vorbis_enc test_enc; + + test_enc = vorbis_stream; + test_enc.vbr_quality = 1.0 - (fl_g->choice_stream_vorbis_vbr_quality->value() * 0.1); + + if (vorbis_enc_init(&test_enc) == 0) { + cfg.vorbis_codec_stream.vbr_quality = fl_g->choice_stream_vorbis_vbr_quality->value(); + vorbis_stream.vbr_quality = 1.0 - (fl_g->choice_stream_vorbis_vbr_quality->value() * 0.1); + + vorbis_enc_reinit(&vorbis_stream); + vorbis_enc_close(&test_enc); + } + else { + fl_g->choice_stream_vorbis_vbr_quality->value(cfg.vorbis_codec_stream.vbr_quality); + printf("choice_stream_vorbis_vbr_quality_cb: Illegal value\n"); + } +} + +void choice_stream_vorbis_vbr_min_bitrate_cb(void) +{ + uint32_t i; + int num_of_bitrates; + int selected_bitrate; + int *br_list; + vorbis_enc test_enc; + + num_of_bitrates = get_bitrate_list_for_codec(CHOICE_OGG, &br_list); + + test_enc = vorbis_stream; + if (fl_g->choice_stream_vorbis_vbr_min_bitrate->value() > 0) { + selected_bitrate = br_list[fl_g->choice_stream_vorbis_vbr_min_bitrate->value() - 1]; + } + else { + selected_bitrate = 0; + } + + test_enc.vbr_min_bitrate = selected_bitrate; + + if (vorbis_enc_init(&test_enc) == 0) { + cfg.vorbis_codec_stream.vbr_min_bitrate = selected_bitrate; + vorbis_stream.vbr_min_bitrate = selected_bitrate; + + vorbis_enc_reinit(&vorbis_stream); + vorbis_enc_close(&test_enc); + } + else { // Set to old value + for (i = 0; i < num_of_bitrates; i++) { + if (cfg.vorbis_codec_stream.vbr_min_bitrate == br_list[i]) { + break; + } + } + fl_g->choice_stream_vorbis_vbr_min_bitrate->value(i + 1); + printf("choice_stream_vorbis_vbr_min_bitrate_cb: Illegal value\n"); + } +} + +void choice_stream_vorbis_vbr_max_bitrate_cb(void) +{ + uint32_t i; + int num_of_bitrates; + int selected_bitrate; + int *br_list; + vorbis_enc test_enc; + + num_of_bitrates = get_bitrate_list_for_codec(CHOICE_OGG, &br_list); + + test_enc = vorbis_stream; + + if (fl_g->choice_stream_vorbis_vbr_max_bitrate->value() > 0) { + selected_bitrate = br_list[fl_g->choice_stream_vorbis_vbr_max_bitrate->value() - 1]; + } + else { + selected_bitrate = 0; + } + test_enc.vbr_max_bitrate = selected_bitrate; + + if (vorbis_enc_init(&test_enc) == 0) { + cfg.vorbis_codec_stream.vbr_max_bitrate = selected_bitrate; + vorbis_stream.vbr_max_bitrate = selected_bitrate; + + vorbis_enc_reinit(&vorbis_stream); + vorbis_enc_close(&test_enc); + } + else { // set to old value + for (i = 0; i < num_of_bitrates; i++) { + if (cfg.vorbis_codec_stream.vbr_max_bitrate == br_list[i]) { + break; + } + } + fl_g->choice_stream_vorbis_vbr_max_bitrate->value(i + 1); + printf("choice_stream_vorbis_vbr_max_bitrate_cb: Illegal value\n"); + } +} + +void choice_stream_opus_bitrate_mode_cb(void) +{ + opus_enc test_enc; + + test_enc = opus_stream; + test_enc.bitrate_mode = fl_g->choice_stream_opus_bitrate_mode->value(); + + if (opus_enc_init(&test_enc) == 0) { + cfg.opus_codec_stream.bitrate_mode = fl_g->choice_stream_opus_bitrate_mode->value(); + opus_stream.bitrate_mode = fl_g->choice_stream_opus_bitrate_mode->value(); + + opus_enc_init(&opus_stream); + opus_enc_close(&test_enc); + } + else { + fl_g->choice_stream_opus_bitrate_mode->value(cfg.opus_codec_stream.bitrate_mode); + printf("choice_stream_opus_bitrate_mode_cb: Illegal value\n"); + } +} + +void choice_stream_opus_audio_type_cb(void) +{ + opus_enc test_enc; + + test_enc = opus_stream; + test_enc.audio_type = fl_g->choice_stream_opus_audio_type->value(); + + if (opus_enc_init(&test_enc) == 0) { + cfg.opus_codec_stream.audio_type = fl_g->choice_stream_opus_audio_type->value(); + opus_stream.audio_type = fl_g->choice_stream_opus_audio_type->value(); + + opus_enc_init(&opus_stream); + opus_enc_close(&test_enc); + } + else { + fl_g->choice_stream_opus_audio_type->value(cfg.opus_codec_stream.audio_type); + printf("choice_stream_opus_audio_type_cb: Illegal value\n"); + } +} + +void choice_stream_opus_quality_cb(void) +{ + opus_enc test_enc; + + test_enc = opus_stream; + test_enc.quality = fl_g->choice_stream_opus_quality->value(); + + if (opus_enc_init(&test_enc) == 0) { + cfg.opus_codec_stream.quality = fl_g->choice_stream_opus_quality->value(); + opus_stream.quality = fl_g->choice_stream_opus_quality->value(); + + opus_enc_init(&opus_stream); + opus_enc_close(&test_enc); + } + else { + fl_g->choice_stream_opus_quality->value(cfg.opus_codec_stream.quality); + printf("choice_stream_opus_quality_cb: Illegal value\n"); + } +} + +void choice_stream_opus_bandwidth_cb(void) +{ + opus_enc test_enc; + + test_enc = opus_stream; + test_enc.bandwidth = fl_g->choice_stream_opus_bandwidth->value(); + + if (opus_enc_init(&test_enc) == 0) { + cfg.opus_codec_stream.bandwidth = fl_g->choice_stream_opus_bandwidth->value(); + opus_stream.bandwidth = fl_g->choice_stream_opus_bandwidth->value(); + + opus_enc_init(&opus_stream); + opus_enc_close(&test_enc); + } + else { + fl_g->choice_stream_opus_bandwidth->value(cfg.opus_codec_stream.bandwidth); + printf("choice_stream_opus_bandwidth_cb: Illegal value\n"); + } +} + +void choice_stream_aac_profile_cb(void) +{ +#ifdef HAVE_LIBFDK_AAC + aac_enc test_enc; + + test_enc = aac_stream; + test_enc.profile = fl_g->choice_stream_aac_profile->value(); + + if (aac_enc_init(&test_enc) == 0) { + cfg.aac_codec_stream.profile = fl_g->choice_stream_aac_profile->value(); + aac_stream.profile = fl_g->choice_stream_aac_profile->value(); + + aac_enc_init(&aac_stream); + aac_enc_close(&test_enc); + } + else { + fl_g->choice_stream_aac_profile->value(cfg.aac_codec_stream.profile); + printf("choice_stream_aac_profile_cb: Illegal value\n"); + } +#endif +} + +void choice_stream_aac_afterburner_cb(void) +{ +#ifdef HAVE_LIBFDK_AAC + aac_enc test_enc; + + test_enc = aac_stream; + test_enc.afterburner = fl_g->choice_stream_aac_afterburner->value() == 0 ? 1 : 0; + + if (aac_enc_init(&test_enc) == 0) { + cfg.aac_codec_stream.afterburner = fl_g->choice_stream_aac_afterburner->value(); + aac_stream.afterburner = fl_g->choice_stream_aac_afterburner->value() == 0 ? 1 : 0; + + aac_enc_init(&aac_stream); + aac_enc_close(&test_enc); + } + else { + fl_g->choice_stream_aac_afterburner->value(cfg.aac_codec_stream.afterburner); + printf("choice_stream_aac_afterburner_cb: Illegal value\n"); + } +#endif +} + +void choice_stream_aac_bitrate_mode_cb(void) +{ +#ifdef HAVE_LIBFDK_AAC + aac_enc test_enc; + + test_enc = aac_stream; + test_enc.bitrate_mode = fl_g->choice_stream_aac_bitrate_mode->value(); + + if (aac_enc_init(&test_enc) == 0) { + cfg.aac_codec_stream.bitrate_mode = fl_g->choice_stream_aac_bitrate_mode->value(); + aac_stream.bitrate_mode = fl_g->choice_stream_aac_bitrate_mode->value(); + + aac_enc_init(&aac_stream); + aac_enc_close(&test_enc); + } + else { + fl_g->choice_stream_aac_bitrate_mode->value(cfg.aac_codec_stream.bitrate_mode); + printf("choice_stream_aac_bitrate_mode_cb: Illegal value\n"); + } +#endif +} + +void radio_stream_flac_bit_depth_16_cb(void) +{ + flac_enc test_enc; + + test_enc = flac_stream; + test_enc.bit_depth = 16; + + if (flac_enc_init(&test_enc) == 0) { + cfg.flac_codec_stream.bit_depth = test_enc.bit_depth; + flac_stream.bit_depth = test_enc.bit_depth; + + flac_enc_init(&flac_stream); + flac_enc_close(&test_enc); + } + else { + fl_g->radio_stream_flac_bit_depth_24->setonly(); + printf("radio_stream_flac_bit_depth_16_cb: Illegal value\n"); + } +} +void radio_stream_flac_bit_depth_24_cb(void) +{ + flac_enc test_enc; + + test_enc = flac_stream; + test_enc.bit_depth = 24; + + if (flac_enc_init(&test_enc) == 0) { + cfg.flac_codec_stream.bit_depth = test_enc.bit_depth; + flac_stream.bit_depth = test_enc.bit_depth; + + flac_enc_init(&flac_stream); + flac_enc_close(&test_enc); + } + else { + fl_g->radio_stream_flac_bit_depth_16->setonly(); + printf("radio_stream_flac_bit_depth_24: Illegal value\n"); + } +} + +void choice_rec_mp3_enc_quality_cb(void) +{ + lame_enc test_enc; + + test_enc = lame_rec; + test_enc.gfp = NULL; + test_enc.enc_quality = fl_g->choice_rec_mp3_enc_quality->value(); + + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_rec.enc_quality = fl_g->choice_rec_mp3_enc_quality->value(); + lame_rec.enc_quality = fl_g->choice_rec_mp3_enc_quality->value(); + + lame_enc_reinit(&lame_rec); + lame_enc_close(&test_enc); + } + else { + printf("choice_rec_mp3_enc_quality_cb: Illegal value\n"); + } +} +void choice_rec_mp3_stereo_mode_cb(void) +{ + lame_enc test_enc; + + test_enc = lame_rec; + test_enc.gfp = NULL; + test_enc.stereo_mode = fl_g->choice_rec_mp3_stereo_mode->value() - 1; + + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_rec.stereo_mode = fl_g->choice_rec_mp3_stereo_mode->value(); + lame_rec.stereo_mode = fl_g->choice_rec_mp3_stereo_mode->value() - 1; + + lame_enc_reinit(&lame_rec); + lame_enc_close(&test_enc); + } + else { + printf("choice_rec_mp3_stereo_mode_cb: Illegal value\n"); + } +} +void choice_rec_mp3_bitrate_mode_cb(void) +{ + lame_enc test_enc; + + test_enc = lame_rec; + test_enc.gfp = NULL; + test_enc.bitrate_mode = fl_g->choice_rec_mp3_bitrate_mode->value(); + + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_rec.bitrate_mode = fl_g->choice_rec_mp3_bitrate_mode->value(); + lame_rec.bitrate_mode = fl_g->choice_rec_mp3_bitrate_mode->value(); + + lame_enc_reinit(&lame_rec); + lame_enc_close(&test_enc); + } + else { + printf("choice_rec_mp3_bitrate_mode_cb: Illegal value\n"); + } +} +void choice_rec_mp3_vbr_quality_cb(void) +{ + lame_enc test_enc; + + test_enc = lame_rec; + test_enc.gfp = NULL; + test_enc.vbr_quality = fl_g->choice_rec_mp3_vbr_quality->value(); + + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_rec.vbr_quality = fl_g->choice_rec_mp3_vbr_quality->value(); + lame_rec.vbr_quality = fl_g->choice_rec_mp3_vbr_quality->value(); + + lame_enc_reinit(&lame_rec); + lame_enc_close(&test_enc); + } + else { + printf("choice_rec_mp3_vbr_quality_cb: Illegal value\n"); + } +} +void choice_rec_mp3_vbr_min_bitrate_cb(void) +{ + int *br_list; + get_bitrate_list_for_codec(CHOICE_MP3, &br_list); + + lame_enc test_enc; + + test_enc = lame_rec; + test_enc.gfp = NULL; + test_enc.vbr_min_bitrate = br_list[fl_g->choice_rec_mp3_vbr_min_bitrate->value()]; + + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_rec.vbr_min_bitrate = br_list[fl_g->choice_rec_mp3_vbr_min_bitrate->value()]; + lame_rec.vbr_min_bitrate = br_list[fl_g->choice_rec_mp3_vbr_min_bitrate->value()]; + + lame_enc_reinit(&lame_rec); + lame_enc_close(&test_enc); + } + else { + printf("choice_rec_mp3_vbr_min_bitrate_cb: Illegal value\n"); + } +} +void choice_rec_mp3_vbr_max_bitrate_cb(void) +{ + int *br_list; + get_bitrate_list_for_codec(CHOICE_MP3, &br_list); + + lame_enc test_enc; + + test_enc = lame_rec; + test_enc.gfp = NULL; + test_enc.vbr_max_bitrate = br_list[fl_g->choice_rec_mp3_vbr_max_bitrate->value()]; + + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_rec.vbr_max_bitrate = br_list[fl_g->choice_rec_mp3_vbr_max_bitrate->value()]; + lame_rec.vbr_max_bitrate = br_list[fl_g->choice_rec_mp3_vbr_max_bitrate->value()]; + + lame_enc_reinit(&lame_rec); + lame_enc_close(&test_enc); + } + else { + printf("choice_rec_mp3_vbr_max_bitrate_cb: Illegal value\n"); + } +} + +void check_rec_mp3_force_min_bitrate_cb(void) +{ + cfg.mp3_codec_rec.vbr_force_min_bitrate = fl_g->check_rec_mp3_force_min_bitrate->value(); + lame_rec.vbr_force_min_bitrate = cfg.mp3_codec_rec.vbr_force_min_bitrate; + lame_enc_reinit(&lame_rec); +} + +void choice_rec_mp3_resampling_freq_cb(void) +{ + int val = fl_g->choice_rec_mp3_resampling_freq->value(); + + lame_enc test_enc; + test_enc = lame_rec; + test_enc.gfp = NULL; + + switch (val) { + case CHOICE_MP3_RESAMPLING_DISABLED: + test_enc.samplerate_out = test_enc.samplerate_in; + break; + case CHOICE_MP3_RESAMPLING_8000: + test_enc.samplerate_out = 8000; + break; + case CHOICE_MP3_RESAMPLING_11025: + test_enc.samplerate_out = 11025; + break; + case CHOICE_MP3_RESAMPLING_12000: + test_enc.samplerate_out = 12000; + break; + case CHOICE_MP3_RESAMPLING_16000: + test_enc.samplerate_out = 16000; + break; + case CHOICE_MP3_RESAMPLING_22050: + test_enc.samplerate_out = 22050; + break; + case CHOICE_MP3_RESAMPLING_24000: + test_enc.samplerate_out = 24000; + break; + case CHOICE_MP3_RESAMPLING_32000: + test_enc.samplerate_out = 32000; + break; + case CHOICE_MP3_RESAMPLING_44100: + test_enc.samplerate_out = 44100; + break; + case CHOICE_MP3_RESAMPLING_48000: + test_enc.samplerate_out = 48000; + break; + default: + printf("illegal resampling frequency provdided\n"); + return; + } + + if (lame_enc_init(&test_enc) == 0) { + if (val == CHOICE_MP3_RESAMPLING_DISABLED) { + cfg.mp3_codec_rec.resampling_freq = CHOICE_MP3_RESAMPLING_DISABLED; + } + else { + cfg.mp3_codec_rec.resampling_freq = test_enc.samplerate_out; + } + + lame_rec.samplerate_out = test_enc.samplerate_out; + + lame_enc_reinit(&lame_rec); + lame_enc_close(&test_enc); + } + else { + fl_alert(_("The encoder could not be initialized with the provided parameters.")); + } +} + +void check_rec_mp3_activate_lowpass_freq_cb(void) +{ + cfg.mp3_codec_rec.lowpass_freq_active = fl_g->check_rec_mp3_activate_lowpass_freq->value(); + cfg.mp3_codec_rec.lowpass_freq_active == 1 ? fl_g->input_rec_mp3_lowpass_freq->activate() : fl_g->input_rec_mp3_lowpass_freq->deactivate(); + + lame_rec.lowpass_freq = cfg.mp3_codec_rec.lowpass_freq * cfg.mp3_codec_rec.lowpass_freq_active; + lame_enc_reinit(&lame_rec); +} + +void input_rec_mp3_lowpass_freq_cb(void) +{ + float val = fl_g->input_rec_mp3_lowpass_freq->value(); + + if (val < 0.001 || val > 50.0) { + fl_alert(_("The value must be between 0.001 kHz and 50 kHz")); + fl_g->input_rec_mp3_lowpass_freq->value(cfg.mp3_codec_rec.lowpass_freq); + return; + } + + lame_enc test_enc; + test_enc = lame_rec; + test_enc.gfp = NULL; + test_enc.lowpass_freq = val; + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_rec.lowpass_freq = val; + lame_rec.lowpass_freq = val; + + lame_enc_reinit(&lame_rec); + lame_enc_close(&test_enc); + } + else { + fl_alert(_("The encoder could not be initialized with the provided parameters.")); + } +} + +void check_rec_mp3_activate_lowpass_width_cb(void) +{ + cfg.mp3_codec_rec.lowpass_width_active = fl_g->check_rec_mp3_activate_lowpass_width->value(); + cfg.mp3_codec_rec.lowpass_width_active == 1 ? fl_g->input_rec_mp3_lowpass_width->activate() : fl_g->input_rec_mp3_lowpass_width->deactivate(); + + lame_rec.lowpass_width = cfg.mp3_codec_rec.lowpass_width * cfg.mp3_codec_rec.lowpass_width_active; + lame_enc_reinit(&lame_rec); +} + +void input_rec_mp3_lowpass_width_cb(void) +{ + float val = fl_g->input_rec_mp3_lowpass_width->value(); + + if (val < 0.001 || val > 16.0) { + fl_alert(_("The value must be between 0.001 kHz and 16 kHz")); + fl_g->input_rec_mp3_lowpass_width->value(cfg.mp3_codec_rec.lowpass_width); + return; + } + + lame_enc test_enc; + test_enc = lame_rec; + test_enc.gfp = NULL; + test_enc.lowpass_width = val; + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_rec.lowpass_width = val; + lame_rec.lowpass_width = val; + + lame_enc_reinit(&lame_rec); + lame_enc_close(&test_enc); + } + else { + fl_alert(_("The encoder could not be initialized with the provided parameters.")); + } +} + +void check_rec_mp3_activate_highpass_freq_cb(void) +{ + cfg.mp3_codec_rec.highpass_freq_active = fl_g->check_rec_mp3_activate_highpass_freq->value(); + cfg.mp3_codec_rec.highpass_freq_active == 1 ? fl_g->input_rec_mp3_highpass_freq->activate() : fl_g->input_rec_mp3_highpass_freq->deactivate(); + + lame_rec.highpass_freq = cfg.mp3_codec_rec.highpass_freq * cfg.mp3_codec_rec.highpass_freq_active; + lame_enc_reinit(&lame_rec); +} + +void input_rec_mp3_highpass_freq_cb(void) +{ + float val = fl_g->input_rec_mp3_highpass_freq->value(); + + if (val < 0.001 || val > 16.0) { + fl_alert(_("The value must be between 0.001 kHz and 16 kHz")); + fl_g->input_rec_mp3_highpass_freq->value(cfg.mp3_codec_rec.highpass_freq); + return; + } + + lame_enc test_enc; + test_enc = lame_rec; + test_enc.gfp = NULL; + test_enc.highpass_freq = val; + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_rec.highpass_freq = val; + lame_rec.highpass_freq = val; + + lame_enc_reinit(&lame_rec); + lame_enc_close(&test_enc); + } + else { + fl_alert(_("The encoder could not be initialized with the provided parameters.")); + } +} + +void check_rec_mp3_activate_highpass_width_cb(void) +{ + cfg.mp3_codec_rec.highpass_width_active = fl_g->check_rec_mp3_activate_highpass_width->value(); + cfg.mp3_codec_rec.highpass_width_active == 1 ? fl_g->input_rec_mp3_highpass_width->activate() : fl_g->input_rec_mp3_highpass_width->deactivate(); + + lame_rec.highpass_width = cfg.mp3_codec_rec.highpass_width * cfg.mp3_codec_rec.highpass_width_active; + lame_enc_reinit(&lame_rec); +} + +void input_rec_mp3_highpass_width_cb(void) +{ + float val = fl_g->input_rec_mp3_highpass_width->value(); + + if (val < 0.001 || val > 16.0) { + fl_alert(_("The value must be between 0.001 kHz and 16 kHz")); + fl_g->input_rec_mp3_highpass_width->value(cfg.mp3_codec_rec.highpass_width); + return; + } + + lame_enc test_enc; + test_enc = lame_rec; + test_enc.gfp = NULL; + test_enc.highpass_width = val; + if (lame_enc_init(&test_enc) == 0) { + cfg.mp3_codec_rec.highpass_width = val; + lame_rec.highpass_width = val; + + lame_enc_reinit(&lame_rec); + lame_enc_close(&test_enc); + } + else { + fl_alert(_("The encoder could not be initialized with the provided parameters.")); + } +} + +void choice_rec_vorbis_bitrate_mode_cb(void) +{ + vorbis_enc test_enc; + + test_enc = vorbis_rec; + test_enc.bitrate_mode = fl_g->choice_rec_vorbis_bitrate_mode->value(); + + if (vorbis_enc_init(&test_enc) == 0) { + cfg.vorbis_codec_rec.bitrate_mode = fl_g->choice_rec_vorbis_bitrate_mode->value(); + vorbis_rec.bitrate_mode = fl_g->choice_rec_vorbis_bitrate_mode->value(); + + vorbis_enc_reinit(&vorbis_rec); + vorbis_enc_close(&test_enc); + } + else { + fl_g->choice_rec_vorbis_bitrate_mode->value(cfg.vorbis_codec_rec.bitrate_mode); + printf("choice_rec_vorbis_bitrate_mode_cb: Illegal value\n"); + } +} + +void choice_rec_vorbis_vbr_quality_cb(void) +{ + vorbis_enc test_enc; + + test_enc = vorbis_rec; + test_enc.vbr_quality = 1.0 - (fl_g->choice_rec_vorbis_vbr_quality->value() * 0.1); + + if (vorbis_enc_init(&test_enc) == 0) { + cfg.vorbis_codec_rec.vbr_quality = fl_g->choice_rec_vorbis_vbr_quality->value(); + vorbis_rec.vbr_quality = 1.0 - (fl_g->choice_rec_vorbis_vbr_quality->value() * 0.1); + + vorbis_enc_reinit(&vorbis_rec); + vorbis_enc_close(&test_enc); + } + else { + fl_g->choice_rec_vorbis_vbr_quality->value(cfg.vorbis_codec_rec.vbr_quality); + printf("choice_rec_vorbis_vbr_quality_cb: Illegal value\n"); + } +} + +void choice_rec_vorbis_vbr_min_bitrate_cb(void) +{ + uint32_t i; + int num_of_bitrates; + int selected_bitrate; + int *br_list; + vorbis_enc test_enc; + + num_of_bitrates = get_bitrate_list_for_codec(CHOICE_OGG, &br_list); + + test_enc = vorbis_rec; + + if (fl_g->choice_rec_vorbis_vbr_min_bitrate->value() > 0) { + selected_bitrate = br_list[fl_g->choice_rec_vorbis_vbr_min_bitrate->value() - 1]; + } + else { + selected_bitrate = 0; + } + test_enc.vbr_min_bitrate = selected_bitrate; + + if (vorbis_enc_init(&test_enc) == 0) { + cfg.vorbis_codec_rec.vbr_min_bitrate = selected_bitrate; + vorbis_rec.vbr_min_bitrate = selected_bitrate; + + vorbis_enc_reinit(&vorbis_rec); + vorbis_enc_close(&test_enc); + } + else { + for (i = 0; i < num_of_bitrates; i++) { + if (cfg.vorbis_codec_rec.vbr_min_bitrate == br_list[i]) { + break; + } + } + fl_g->choice_rec_vorbis_vbr_min_bitrate->value(i + 1); + printf("choice_rec_vorbis_vbr_min_bitrate_cb: Illegal value\n"); + } +} + +void choice_rec_vorbis_vbr_max_bitrate_cb(void) +{ + uint32_t i; + int num_of_bitrates; + int selected_bitrate; + int *br_list; + vorbis_enc test_enc; + + num_of_bitrates = get_bitrate_list_for_codec(CHOICE_OGG, &br_list); + + test_enc = vorbis_rec; + + if (fl_g->choice_rec_vorbis_vbr_max_bitrate->value() > 0) { + selected_bitrate = br_list[fl_g->choice_rec_vorbis_vbr_max_bitrate->value() - 1]; + } + else { + selected_bitrate = 0; + } + test_enc.vbr_max_bitrate = selected_bitrate; + + if (vorbis_enc_init(&test_enc) == 0) { + cfg.vorbis_codec_rec.vbr_max_bitrate = selected_bitrate; + vorbis_rec.vbr_max_bitrate = selected_bitrate; + + vorbis_enc_reinit(&vorbis_rec); + vorbis_enc_close(&test_enc); + } + else { + for (i = 0; i < num_of_bitrates; i++) { + if (cfg.vorbis_codec_rec.vbr_max_bitrate == br_list[i]) { + break; + } + } + fl_g->choice_rec_vorbis_vbr_max_bitrate->value(i + 1); + printf("choice_rec_vorbis_vbr_max_bitrate_cb: Illegal value\n"); + } +} + +void choice_rec_opus_bitrate_mode_cb(void) +{ + opus_enc test_enc; + + test_enc = opus_rec; + test_enc.bitrate_mode = fl_g->choice_rec_opus_bitrate_mode->value(); + + if (opus_enc_init(&test_enc) == 0) { + cfg.opus_codec_rec.bitrate_mode = fl_g->choice_rec_opus_bitrate_mode->value(); + opus_rec.bitrate_mode = fl_g->choice_rec_opus_bitrate_mode->value(); + + opus_enc_init(&opus_rec); + opus_enc_close(&test_enc); + } + else { + fl_g->choice_rec_opus_bitrate_mode->value(cfg.opus_codec_rec.bitrate_mode); + printf("choice_rec_opus_bitrate_mode_cb: Illegal value\n"); + } +} + +void choice_rec_opus_audio_type_cb(void) +{ + opus_enc test_enc; + + test_enc = opus_rec; + test_enc.audio_type = fl_g->choice_rec_opus_audio_type->value(); + + if (opus_enc_init(&test_enc) == 0) { + cfg.opus_codec_rec.audio_type = fl_g->choice_rec_opus_audio_type->value(); + opus_rec.audio_type = fl_g->choice_rec_opus_audio_type->value(); + + opus_enc_init(&opus_rec); + opus_enc_close(&test_enc); + } + else { + fl_g->choice_rec_opus_audio_type->value(cfg.opus_codec_rec.audio_type); + printf("choice_rec_opus_audio_type_cb: Illegal value\n"); + } +} + +void choice_rec_opus_quality_cb(void) +{ + opus_enc test_enc; + + test_enc = opus_rec; + test_enc.quality = fl_g->choice_rec_opus_quality->value(); + + if (opus_enc_init(&test_enc) == 0) { + cfg.opus_codec_rec.quality = fl_g->choice_rec_opus_quality->value(); + opus_rec.quality = fl_g->choice_rec_opus_quality->value(); + + opus_enc_init(&opus_rec); + opus_enc_close(&test_enc); + } + else { + fl_g->choice_rec_opus_quality->value(cfg.opus_codec_rec.quality); + printf("choice_rec_opus_quality_cb: Illegal value\n"); + } +} + +void choice_rec_opus_bandwidth_cb(void) +{ + opus_enc test_enc; + + test_enc = opus_rec; + test_enc.bandwidth = fl_g->choice_rec_opus_bandwidth->value(); + + if (opus_enc_init(&test_enc) == 0) { + cfg.opus_codec_rec.bandwidth = fl_g->choice_rec_opus_bandwidth->value(); + opus_rec.bandwidth = fl_g->choice_rec_opus_bandwidth->value(); + + opus_enc_init(&opus_rec); + opus_enc_close(&test_enc); + } + else { + fl_g->choice_rec_opus_bandwidth->value(cfg.opus_codec_rec.bandwidth); + printf("choice_rec_opus_bandwidth_cb: Illegal value\n"); + } +} + +void choice_rec_aac_profile_cb(void) +{ +#ifdef HAVE_LIBFDK_AAC + aac_enc test_enc; + + test_enc = aac_rec; + test_enc.profile = fl_g->choice_rec_aac_profile->value(); + + if (aac_enc_init(&test_enc) == 0) { + cfg.aac_codec_rec.profile = fl_g->choice_rec_aac_profile->value(); + aac_rec.profile = fl_g->choice_rec_aac_profile->value(); + + aac_enc_init(&aac_rec); + aac_enc_close(&test_enc); + } + else { + fl_g->choice_rec_aac_profile->value(cfg.aac_codec_rec.profile); + printf("choice_rec_aac_profile_cb: Illegal value\n"); + } +#endif +} + +void choice_rec_aac_afterburner_cb(void) +{ +#ifdef HAVE_LIBFDK_AAC + aac_enc test_enc; + + test_enc = aac_rec; + test_enc.afterburner = fl_g->choice_rec_aac_afterburner->value() == 0 ? 1 : 0; + + if (aac_enc_init(&test_enc) == 0) { + cfg.aac_codec_rec.afterburner = fl_g->choice_rec_aac_afterburner->value(); + aac_rec.afterburner = fl_g->choice_rec_aac_afterburner->value() == 0 ? 1 : 0; + + aac_enc_init(&aac_rec); + aac_enc_close(&test_enc); + } + else { + fl_g->choice_rec_aac_afterburner->value(cfg.aac_codec_rec.afterburner); + printf("choice_rec_aac_afterburner_cb: Illegal value\n"); + } +#endif +} + +void choice_rec_aac_bitrate_mode_cb(void) +{ +#ifdef HAVE_LIBFDK_AAC + aac_enc test_enc; + + test_enc = aac_rec; + test_enc.bitrate_mode = fl_g->choice_rec_aac_bitrate_mode->value(); + + if (aac_enc_init(&test_enc) == 0) { + cfg.aac_codec_rec.bitrate_mode = fl_g->choice_rec_aac_bitrate_mode->value(); + aac_rec.bitrate_mode = fl_g->choice_rec_aac_bitrate_mode->value(); + + aac_enc_init(&aac_rec); + aac_enc_close(&test_enc); + } + else { + fl_g->choice_rec_aac_bitrate_mode->value(cfg.aac_codec_rec.bitrate_mode); + printf("choice_rec_aac_bitrate_mode_cb: Illegal value\n"); + } + +#endif +} + +void radio_rec_flac_bit_depth_16_cb(void) +{ + flac_enc test_enc; + + test_enc = flac_rec; + test_enc.bit_depth = 16; + + if (flac_enc_init(&test_enc) == 0) { + cfg.flac_codec_rec.bit_depth = test_enc.bit_depth; + flac_rec.bit_depth = test_enc.bit_depth; + + flac_enc_init(&flac_rec); + flac_enc_close(&test_enc); + } + else { + fl_g->radio_rec_flac_bit_depth_24->setonly(); + printf("radio_rec_flac_bit_depth_16_cb: Illegal value\n"); + } +} + +void radio_rec_flac_bit_depth_24_cb(void) +{ + flac_enc test_enc; + + test_enc = flac_rec; + test_enc.bit_depth = 24; + + if (flac_enc_init(&test_enc) == 0) { + cfg.flac_codec_rec.bit_depth = test_enc.bit_depth; + flac_rec.bit_depth = test_enc.bit_depth; + + flac_enc_init(&flac_rec); + flac_enc_close(&test_enc); + } + else { + fl_g->radio_rec_flac_bit_depth_16->setonly(); + printf("radio_rec_flac_bit_depth_24: Illegal value\n"); + } +} + +void radio_rec_wav_bit_depth_16_cb(void) +{ + cfg.wav_codec_rec.bit_depth = 16; +} +void radio_rec_wav_bit_depth_24_cb(void) +{ + cfg.wav_codec_rec.bit_depth = 24; +} +void radio_rec_wav_bit_depth_32_cb(void) +{ + cfg.wav_codec_rec.bit_depth = 32; +} + +void choice_midi_dev_cb(void) +{ + char info_buf[256]; + int dev_id = fl_g->choice_midi_dev->value() - 1; + const char *dev_name = fl_g->choice_midi_dev->text(); + + midi_close(); + if (dev_id > -1) { + if (midi_open_device((char *)dev_name) != 0) { + fl_alert(_("MIDI device could not be opened.")); + goto set_disabled_device; + } + if (midi_start_polling() == 0) { + cfg.midi.dev_name = (char *)realloc(cfg.midi.dev_name, strlen(dev_name) + 1); + strcpy(cfg.midi.dev_name, dev_name); + snprintf(info_buf, sizeof(info_buf), _("MIDI device:\n%s\n"), cfg.midi.dev_name); + print_info(info_buf, 1); + return; + } + else { + fl_alert(_("MIDI device could not be started.")); + goto set_disabled_device; + } + } + else { + print_info(_("MIDI support disabled\n"), 1); + goto set_disabled_device; + } + +set_disabled_device: + fl_g->choice_midi_dev->value(0); + cfg.midi.dev_name = (char *)realloc(cfg.midi.dev_name, strlen("Disabled") + 1); + strcpy(cfg.midi.dev_name, "Disabled"); +} + +void button_midi_rescan_devices_cb(void) +{ + // PortMidi needs a complete new initialization to detect device changes + midi_close(); + midi_terminate(); + midi_init(); + + // Populate MIDI device list and select the device from config file in case it was found + populate_midi_dev_list(); + + // Initialize the MIDI device in case it was found + if (fl_g->choice_midi_dev->value() > 0) { + choice_midi_dev_cb(); + } +} + +void browser_midi_command_cb(void) +{ + int selected_line = fl_g->browser_midi_command->value() - 1; + + // Select last line when user clicks on any empty space in the command browser + if (selected_line == -1) { + selected_line = fl_g->browser_midi_command->size() - 1; + fl_g->browser_midi_command->value(selected_line + 1); + } + + fl_g->choice_midi_channel->value(cfg.midi.commands[selected_line].channel); + fl_g->input_midi_msg_num->value(cfg.midi.commands[selected_line].msg_num); + fl_g->choice_midi_cc_mode->value(cfg.midi.commands[selected_line].mode); + fl_g->check_midi_soft_takeover->value(cfg.midi.commands[selected_line].soft_takeover); + fl_g->check_midi_command_enable->value(cfg.midi.commands[selected_line].enabled); + + // Update accessibility of UI elements that depend on the CC mode + fl_g->choice_midi_cc_mode->do_callback(); + fl_g->check_midi_command_enable->do_callback(); + + if (get_midi_ctrl_type(selected_line) == MIDI_CTRL_TYPE_KNOB) { + fl_g->choice_midi_cc_mode->activate(); + fl_g->check_midi_soft_takeover->activate(); + } + else { + fl_g->choice_midi_cc_mode->deactivate(); + fl_g->check_midi_soft_takeover->deactivate(); + } +} + +void input_midi_msg_num_cb(void) +{ + int selected_line = fl_g->browser_midi_command->value() - 1; + int msg_num = fl_g->input_midi_msg_num->value(); + + if (msg_num < 0 || msg_num > 127) { + fl_alert(_("The CC value must be between 0 and 127")); + fl_g->input_midi_msg_num->value(cfg.midi.commands[selected_line].msg_num); + return; + } + + cfg.midi.commands[selected_line].msg_num = fl_g->input_midi_msg_num->value(); +} + +void choice_midi_channel_cb(void) +{ + int selected_line = fl_g->browser_midi_command->value() - 1; + cfg.midi.commands[selected_line].channel = fl_g->choice_midi_channel->value(); +} + +void button_midi_learn_cb(void) +{ + int pushed_down = fl_g->button_midi_learn->value(); + + if (pushed_down == 0) { + fl_g->button_midi_learn->label(_("Learn")); + midi_set_learning(0); + } + else { + fl_g->button_midi_learn->label(_("Waiting...")); + midi_set_learning(1); + } +} + +void choice_midi_cc_mode_cb(void) +{ + int selected_line = fl_g->browser_midi_command->value() - 1; + cfg.midi.commands[selected_line].mode = fl_g->choice_midi_cc_mode->value(); + + if (fl_g->choice_midi_cc_mode->value() == MIDI_MODE_ABSOLUTE) { + fl_g->check_midi_soft_takeover->activate(); + } + else { // MIDI_MODE_RELATIVE_* + fl_g->check_midi_soft_takeover->deactivate(); + } +} + +void check_midi_soft_takeover_cb(void) +{ + int selected_line = fl_g->browser_midi_command->value() - 1; + cfg.midi.commands[selected_line].soft_takeover = fl_g->check_midi_soft_takeover->value(); +} + +void check_midi_command_enable_cb(void) +{ + int enabled = fl_g->check_midi_command_enable->value(); + int selected_line = fl_g->browser_midi_command->value() - 1; + + cfg.midi.commands[selected_line].enabled = enabled; + + if (enabled == 1) { + fl_g->group_midi_command_settings->activate(); + } + else { + fl_g->group_midi_command_settings->deactivate(); + } +} diff --git a/src/FLTK/fl_callbacks.h b/src/FLTK/fl_callbacks.h new file mode 100644 index 0000000..0099e21 --- /dev/null +++ b/src/FLTK/fl_callbacks.h @@ -0,0 +1,323 @@ +// FLTK callback functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef FL_CALLBACKS_H +#define FL_CALLBACKS_H + +enum { + STREAM_TIME = 0, + REC_TIME = 1, + SENT_DATA = 2, + REC_DATA = 3, + STREAM_STATE = 4, +}; + +enum { + STREAM = 0, + RECORD = 1, +}; + +enum { + CB_CALLED_BY_USER = 0, + CB_CALLED_BY_CODE = 1, + CB_CALLED_BY_MIDI = 2, +}; + +class flgui; + +extern int display_info; +extern flgui *fl_g; + +void show_vu_tabs(void); +void hide_vu_tabs(void); + +void button_cfg_cb(void); +void button_mixer_cb(void); +void button_info_cb(void); +void button_record_cb(bool ask); +void button_connect_cb(void); +void button_disconnect_cb(bool ask); +void button_add_icy_add_cb(void); +void button_cfg_del_srv_cb(void); +void button_cfg_del_icy_cb(void); +void choice_cfg_act_srv_cb(void); +void choice_cfg_act_icy_cb(void); +void button_cfg_add_srv_cb(void); +void button_cfg_add_icy_cb(void); +void choice_cfg_bitrate_cb(void); +void choice_cfg_samplerate_cb(void); +void button_cfg_song_go_cb(void); +void choice_cfg_codec_mp3_cb(void); +void choice_cfg_codec_ogg_cb(void); +void choice_cfg_codec_opus_cb(void); +void choice_cfg_codec_aac_cb(void); +void choice_cfg_codec_flac_cb(void); +void button_cfg_export_cb(void); +void button_cfg_import_cb(void); +void button_add_icy_save_cb(void); +void button_add_srv_cancel_cb(void); +void button_add_icy_cancel_cb(void); +void choice_cfg_channel_stereo_cb(void); +void choice_cfg_channel_mono_cb(void); +void button_cfg_browse_songfile_cb(void); +void input_cfg_song_file_cb(void); +void input_cfg_song_cb(void); +void input_cfg_song_prefix_cb(void); +void input_cfg_song_suffix_cb(void); +void input_cfg_buffer_cb(bool print_message); +void input_cfg_signal_cb(void); +void input_cfg_silence_cb(void); +void check_stream_signal_cb(void); +void check_stream_silence_cb(void); +void input_cfg_reconnect_delay_cb(void); +void input_cfg_present_level_cb(void); +void input_cfg_absent_level_cb(void); +void choice_cfg_resample_mode_cb(void); +void button_cfg_check_for_updates_cb(void); +void choice_cfg_dev_cb(void); +void choice_cfg_dev2_cb(void); +void button_cfg_rescan_devices_cb(void); +void radio_cfg_ID_cb(void); +void radio_cfg_name_cb(void); +void choice_cfg_right_channel_cb(void); +void choice_cfg_left_channel_cb(void); +void choice_cfg_right_channel2_cb(void); +void choice_cfg_left_channel2_cb(void); + +void button_add_srv_add_cb(void); +void button_add_srv_save_cb(void); +void button_add_srv_show_pwd_cb(void); +void radio_add_srv_shoutcast_cb(void); +void radio_add_srv_icecast_cb(void); +void radio_add_srv_webrtc_cb(void); +void radio_add_srv_radioco_cb(void); +void button_add_srv_revoke_cert_cb(void); +void button_add_srv_get_stations_cb(void); +void button_add_srv_select_all_cb(void); +void button_add_srv_deselect_all_cb(void); + +void button_start_agent_cb(void); +void button_stop_agent_cb(void); +void check_update_at_startup_cb(void); +void check_start_agent_cb(void); +void check_minimize_to_tray_cb(void); + +void button_stream_codec_settings_cb(void); + +void button_rec_browse_cb(void); +void button_rec_split_now_cb(void); +void choice_rec_bitrate_cb(void); +void choice_rec_samplerate_cb(void); +void choice_rec_channel_stereo_cb(void); +void choice_rec_channel_mono_cb(void); +void choice_rec_codec_mp3_cb(void); +void choice_rec_codec_ogg_cb(void); +void choice_rec_codec_wav_cb(void); +void choice_rec_codec_opus_cb(void); +void choice_rec_codec_aac_cb(void); +void choice_rec_codec_flac_cb(void); +void button_rec_codec_settings_cb(void); +void input_rec_signal_cb(void); +void input_rec_silence_cb(void); +void check_rec_signal_cb(void); +void check_rec_silence_cb(void); + +void input_tls_cert_file_cb(void); +void input_tls_cert_dir_cb(void); +void button_tls_browse_file_cb(void); +void button_tls_browse_dir_cb(void); + +void button_cfg_edit_srv_cb(void); +void button_cfg_edit_icy_cb(void); +void check_song_update_active_cb(void); +void check_read_last_line_cb(void); +void check_sync_to_full_hour_cb(void); + +void input_rec_filename_cb(void); +void input_rec_folder_cb(void); +void input_rec_split_time_cb(void); +void input_log_filename_cb(void); +void button_cfg_log_browse_cb(void); + +void check_gui_attach_cb(void); +void check_gui_ontop_cb(void); +void check_gui_hide_log_window_cb(void); +void check_gui_remember_pos_cb(void); +void check_gui_lcd_auto_cb(void); +void check_gui_start_minimized_cb(void); +void check_gui_disable_gain_slider_cb(void); +void check_gui_show_listeners_cb(void); +void input_gui_listeners_update_rate_cb(void); +void button_gui_bg_color_cb(void); +void button_gui_text_color_cb(void); +void button_gui_vu_low_color_cb(void); +void button_gui_vu_mid_color_cb(void); +void button_gui_vu_high_color_cb(void); +void input_gui_vu_mid_range_start_cb(void); +void input_gui_vu_high_range_start_cb(void); +void choice_gui_language_cb(void); +void radio_gui_vu_gradient_cb(void); +void radio_gui_vu_solid_cb(void); +void check_gui_always_show_vu_tabs_cb(void); +void input_gui_window_title_cb(void); + +void slider_gain_cb(void *called_by); +void vu_tabs_cb(void); + +void check_stream_eq_cb(void); +void check_rec_eq_cb(void); +void button_eq_reset_cb(void); +void choice_eq_preset_cb(void); +void slider_equalizer1_cb(double); +void slider_equalizer2_cb(double); +void slider_equalizer3_cb(double); +void slider_equalizer4_cb(double); +void slider_equalizer5_cb(double); +void slider_equalizer6_cb(double); +void slider_equalizer7_cb(double); +void slider_equalizer8_cb(double); +void slider_equalizer9_cb(double); +void slider_equalizer10_cb(double); + +void check_stream_drc_cb(void); +void check_rec_drc_cb(void); +void button_drc_reset_cb(void); +void check_aggressive_mode_cb(void); +void slider_threshold_cb(double); +void slider_ratio_cb(double); +void slider_attack_cb(double); +void slider_release_cb(double); +void slider_makeup_cb(double); + +void slider_mixer_primary_device_cb(double val, void *called_by); +void slider_mixer_secondary_device_cb(double val, void *called_by); +void slider_mixer_streaming_gain_cb(double val, void *called_by); +void slider_mixer_recording_gain_cb(double val, void *called_by); +void slider_mixer_master_gain_cb(double val, void *called_by); +void slider_mixer_cross_fader_cb(double val, void *called_by); +void button_mixer_reset_cb(void); +void button_mixer_mute_primary_device_cb(void); +void button_mixer_mute_secondary_device_cb(void); + +void check_cfg_overwrite_existing_files_cb(void); +void check_cfg_auto_start_rec_cb(void); +void check_cfg_auto_stop_rec_cb(void); +void check_cfg_rec_after_launch_cb(void); + +void check_cfg_rec_hourly_cb(void); +void check_cfg_connect_cb(void); +void check_cfg_force_reconnecting_cb(void); + +void lcd_rotate(void *); +void ILM216_cb(void); +void window_main_close_cb(bool ask); + +void check_cfg_use_app_cb(void); +void choice_cfg_app_cb(void); +void radio_cfg_artist_title_cb(void); +void radio_cfg_title_artist_cb(void); + +void input_cfg_song_url_cb(void); +void input_cfg_url_update_song_interval_cb(void); +void check_cfg_update_from_url_cb(void); + +void choice_cfg_song_delay_cb(void); + +void update_song(void *user_data); +bool stop_recording(bool ask); + +void choice_stream_mp3_enc_quality_cb(void); +void choice_stream_mp3_stereo_mode_cb(void); +void choice_stream_mp3_bitrate_mode_cb(void); +void choice_stream_mp3_vbr_quality_cb(void); +void choice_stream_mp3_vbr_min_bitrate_cb(void); +void choice_stream_mp3_vbr_max_bitrate_cb(void); +void check_stream_mp3_force_min_bitrate_cb(void); +void choice_stream_mp3_resampling_freq_cb(void); +void check_stream_mp3_activate_lowpass_freq_cb(void); +void input_stream_mp3_lowpass_freq_cb(void); +void check_stream_mp3_activate_lowpass_width_cb(void); +void input_stream_mp3_lowpass_width_cb(void); +void check_stream_mp3_activate_highpass_freq_cb(void); +void input_stream_mp3_highpass_freq_cb(void); +void check_stream_mp3_activate_highpass_width_cb(void); +void input_stream_mp3_highpass_width_cb(void); + +void choice_stream_vorbis_bitrate_mode_cb(void); +void choice_stream_vorbis_vbr_quality_cb(void); +void choice_stream_vorbis_vbr_min_bitrate_cb(void); +void choice_stream_vorbis_vbr_max_bitrate_cb(void); + +void choice_stream_opus_audio_type_cb(void); +void choice_stream_opus_bitrate_mode_cb(void); +void choice_stream_opus_quality_cb(void); +void choice_stream_opus_bandwidth_cb(void); + +void choice_stream_aac_profile_cb(void); +void choice_stream_aac_afterburner_cb(void); +void choice_stream_aac_bitrate_mode_cb(void); + +void radio_stream_flac_bit_depth_16_cb(void); +void radio_stream_flac_bit_depth_24_cb(void); + +void choice_rec_mp3_enc_quality_cb(void); +void choice_rec_mp3_stereo_mode_cb(void); +void choice_rec_mp3_bitrate_mode_cb(void); +void choice_rec_mp3_vbr_quality_cb(void); +void choice_rec_mp3_vbr_min_bitrate_cb(void); +void choice_rec_mp3_vbr_max_bitrate_cb(void); +void check_rec_mp3_force_min_bitrate_cb(void); +void choice_rec_mp3_resampling_freq_cb(void); +void check_rec_mp3_activate_lowpass_freq_cb(void); +void input_rec_mp3_lowpass_freq_cb(void); +void check_rec_mp3_activate_lowpass_width_cb(void); +void input_rec_mp3_lowpass_width_cb(void); +void check_rec_mp3_activate_highpass_freq_cb(void); +void input_rec_mp3_highpass_freq_cb(void); +void check_rec_mp3_activate_highpass_width_cb(void); +void input_rec_mp3_highpass_width_cb(void); + +void choice_rec_vorbis_bitrate_mode_cb(void); +void choice_rec_vorbis_vbr_quality_cb(void); +void choice_rec_vorbis_vbr_min_bitrate_cb(void); +void choice_rec_vorbis_vbr_max_bitrate_cb(void); + +void choice_rec_opus_audio_type_cb(void); +void choice_rec_opus_bitrate_mode_cb(void); +void choice_rec_opus_quality_cb(void); +void choice_rec_opus_bandwidth_cb(void); + +void choice_rec_aac_profile_cb(void); +void choice_rec_aac_afterburner_cb(void); +void choice_rec_aac_bitrate_mode_cb(void); + +void radio_rec_flac_bit_depth_16_cb(void); +void radio_rec_flac_bit_depth_24_cb(void); + +void radio_rec_wav_bit_depth_16_cb(void); +void radio_rec_wav_bit_depth_24_cb(void); +void radio_rec_wav_bit_depth_32_cb(void); + +void choice_midi_dev_cb(void); +void choice_midi_cc_mode_cb(void); +void check_midi_soft_takeover_cb(void); +void button_midi_rescan_devices_cb(void); +void browser_midi_command_cb(void); +void input_midi_msg_num_cb(void); +void choice_midi_channel_cb(void); +void button_midi_learn_cb(void); +void check_midi_command_enable_cb(void); + +#endif diff --git a/src/FLTK/fl_funcs.cpp b/src/FLTK/fl_funcs.cpp new file mode 100644 index 0000000..e74428a --- /dev/null +++ b/src/FLTK/fl_funcs.cpp @@ -0,0 +1,1943 @@ +// FLTK GUI related functions +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef WIN32 +#include +#endif + +#include "gettext.h" +#include "config.h" + +#include "cfg.h" +#include "butt.h" +#include "util.h" +#include "port_audio.h" +#include "port_midi.h" +#include "timer.h" +#include "flgui.h" +#include "fl_funcs.h" +#include "shoutcast.h" +#include "icecast.h" +#include "strfuncs.h" + +pthread_mutex_t write_log_mutex = PTHREAD_MUTEX_INITIALIZER; + +int get_bitrate_list_for_codec(int codec, int **bitrates) +{ + static int mp3[] = {8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320}; + static int aac[] = {8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512}; + static int ogg[] = {8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 500}; + static int opus[] = {8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 510}; + + int num_of_bitrates; + + switch (codec) { + case CHOICE_MP3: + *bitrates = mp3; + num_of_bitrates = sizeof(mp3) / sizeof(int); + break; + case CHOICE_AAC: + *bitrates = aac; + num_of_bitrates = sizeof(aac) / sizeof(int); + break; + case CHOICE_OGG: + *bitrates = ogg; + num_of_bitrates = sizeof(ogg) / sizeof(int); + break; + case CHOICE_OPUS: + *bitrates = opus; + num_of_bitrates = sizeof(opus) / sizeof(int); + break; + default: + num_of_bitrates = 0; + } + + return num_of_bitrates; +} + +int get_codec_index(char *codec) +{ + int codec_idx = 0; + + if (!strcmp(codec, "mp3")) { + codec_idx = CHOICE_MP3; + } + else if (!strcmp(codec, "ogg")) { + codec_idx = CHOICE_OGG; + } + else if (!strcmp(codec, "opus")) { + codec_idx = CHOICE_OPUS; + } + else if (!strcmp(codec, "aac")) { + codec_idx = CHOICE_AAC; + } + else if (!strcmp(codec, "flac")) { + codec_idx = CHOICE_FLAC; + fl_g->choice_rec_bitrate->hide(); + } + else if (!strcmp(codec, "wav")) { + codec_idx = CHOICE_WAV; + fl_g->choice_rec_bitrate->hide(); + } + + return codec_idx; +} + +int get_bitrate_index(int codec, int bitrate) +{ + int *bitrates; + int num_of_bitrates = get_bitrate_list_for_codec(codec, &bitrates); + + for (int i = 0; i < num_of_bitrates; i++) { + if (bitrates[i] == bitrate) { + return i; + } + } + + return 0; +} + +void update_stream_bitrate_list(int codec) +{ + int *bitrates; + int current_bitrate = cfg.audio.bitrate; + int num_of_bitrates = get_bitrate_list_for_codec(codec, &bitrates); + + if (num_of_bitrates == 0) { + return; + } + + // Using menu(NULL) here to clear the bitrate list because ->clear() does not work + // if the initial fl_choice menu items were added with fluid + // fl_g->choice_cfg_bitrate->menu(NULL); + fl_g->choice_cfg_bitrate->clear(); + fl_g->choice_cfg_bitrate->textsize(14); + + char br[8]; + int diff; + int closest_bitrate = bitrates[0]; + for (int i = 0; i < num_of_bitrates; i++) { + snprintf(br, sizeof(br), "%ik", bitrates[i]); + fl_g->choice_cfg_bitrate->add(br); + + // Find closest bitrate + diff = abs(bitrates[i] - current_bitrate); + if (diff < abs(current_bitrate - closest_bitrate)) { + closest_bitrate = bitrates[i]; + } + } + + fl_g->choice_cfg_bitrate->value(get_bitrate_index(codec, closest_bitrate)); + cfg.audio.bitrate = closest_bitrate; +} + +void update_rec_bitrate_list(int codec) +{ + int *bitrates; + int current_bitrate = cfg.rec.bitrate; + int num_of_bitrates = get_bitrate_list_for_codec(codec, &bitrates); + + if (num_of_bitrates == 0) { + return; + } + + // Using menu(NULL) here to clear the bitrate list because ->clear() does not work + // if the initial fl_choice menu items were added with fluid + // fl_g->choice_rec_bitrate->menu(NULL); + fl_g->choice_rec_bitrate->clear(); + fl_g->choice_rec_bitrate->textsize(14); + + char br[8]; + int diff; + int closest_bitrate = bitrates[0]; + for (int i = 0; i < num_of_bitrates; i++) { + snprintf(br, sizeof(br), "%ik", bitrates[i]); + fl_g->choice_rec_bitrate->add(br); + + // Find closest bitrate + diff = abs(bitrates[i] - current_bitrate); + if (diff < abs(current_bitrate - closest_bitrate)) { + closest_bitrate = bitrates[i]; + } + } + + fl_g->choice_rec_bitrate->value(get_bitrate_index(codec, closest_bitrate)); + cfg.rec.bitrate = closest_bitrate; +} + +void populate_midi_dev_list(void) +{ + int dev_count; + + fl_g->choice_midi_dev->clear(); + fl_g->choice_midi_dev->add(_("Disabled")); + fl_g->choice_midi_dev->value(0); + + midi_dev_t **dev_list = midi_get_devices(&dev_count); + for (int i = 0; i < dev_count; i++) { + fl_g->choice_midi_dev->add(dev_list[i]->name); + } + + if (strcmp(cfg.midi.dev_name, "Disabled") != 0) { + int dev_num = midi_get_dev_num_by_name(dev_list, cfg.midi.dev_name); + if (dev_num >= 0) { + fl_g->choice_midi_dev->value(dev_num + 1); + } + } + + midi_free_device_list(dev_list); +} + +void fill_cfg_widgets(void) +{ + int i; + int stream_codec_idx = 0; + int rec_codec_idx = 0; + +#ifndef HAVE_LIBFDK_AAC + fl_g->menu_item_cfg_aac->hide(); + fl_g->menu_item_rec_aac->hide(); + Fl::check(); +#endif + + // fill the main section + fl_g->choice_cfg_dev->textsize(14); + fl_g->choice_cfg_dev2->textsize(14); + + fl_g->choice_cfg_dev2->add(_("None")); + for (i = 0; i < cfg.audio.dev_count; i++) { + unsigned long dev_name_len = strlen(cfg.audio.pcm_list[i]->name) + 10; + char *dev_name = (char *)malloc(dev_name_len); + + snprintf(dev_name, dev_name_len, "%d: %s", i, cfg.audio.pcm_list[i]->name); + fl_g->choice_cfg_dev->add(dev_name); + fl_g->choice_cfg_dev2->add(dev_name); + free(dev_name); + } + + fl_g->choice_cfg_dev->value(cfg.audio.dev_num); + fl_g->choice_cfg_dev2->value(cfg.audio.dev2_num + 1); + + fl_g->choice_cfg_act_srv->clear(); + fl_g->choice_cfg_act_srv->redraw(); + for (i = 0; i < cfg.main.num_of_srv; i++) { + fl_g->choice_cfg_act_srv->add(cfg.srv[i]->name); + } + + if (cfg.main.num_of_srv > 0) { + fl_g->button_cfg_edit_srv->activate(); + fl_g->button_cfg_del_srv->activate(); + fl_g->choice_cfg_act_srv->activate(); + } + else { + fl_g->button_cfg_edit_srv->deactivate(); + fl_g->button_cfg_del_srv->deactivate(); + fl_g->choice_cfg_act_srv->deactivate(); + } + + fl_g->choice_cfg_act_icy->clear(); + fl_g->choice_cfg_act_icy->redraw(); + for (i = 0; i < cfg.main.num_of_icy; i++) + fl_g->choice_cfg_act_icy->add(cfg.icy[i]->name); + + if (cfg.main.num_of_icy > 0) { + fl_g->button_cfg_edit_icy->activate(); + fl_g->button_cfg_del_icy->activate(); + fl_g->choice_cfg_act_icy->activate(); + } + else { + fl_g->button_cfg_edit_icy->deactivate(); + fl_g->button_cfg_del_icy->deactivate(); + fl_g->choice_cfg_act_icy->deactivate(); + } + + fl_g->choice_cfg_act_srv->value(cfg.selected_srv); + fl_g->choice_cfg_act_icy->value(cfg.selected_icy); + + fl_g->check_cfg_connect->value(cfg.main.connect_at_startup); + fl_g->check_cfg_force_reconnecting->value(cfg.main.force_reconnecting); + + fl_g->input_log_filename->value(cfg.main.log_file); + + fl_g->check_update_at_startup->value(cfg.main.check_for_update); + + fl_g->check_start_agent->value(cfg.main.start_agent); + fl_g->check_minimize_to_tray->value(cfg.main.minimize_to_tray); + + // fill the audio section + if (!strcmp(cfg.audio.codec, "mp3")) { + stream_codec_idx = CHOICE_MP3; + } + else if (!strcmp(cfg.audio.codec, "ogg")) { + stream_codec_idx = CHOICE_OGG; + } + else if (!strcmp(cfg.audio.codec, "opus")) { + stream_codec_idx = CHOICE_OPUS; + } + else if (!strcmp(cfg.audio.codec, "aac")) { + stream_codec_idx = CHOICE_AAC; + } + else if (!strcmp(cfg.audio.codec, "flac")) { + stream_codec_idx = CHOICE_FLAC; + fl_g->choice_cfg_bitrate->hide(); + } + + update_stream_bitrate_list(stream_codec_idx); + + fl_g->choice_cfg_codec->value(stream_codec_idx); + fl_g->choice_cfg_bitrate->value(get_bitrate_index(stream_codec_idx, cfg.audio.bitrate)); + + if (cfg.audio.dev_remember == REMEMBER_BY_ID) { + fl_g->radio_cfg_ID->setonly(); + } + else { + fl_g->radio_cfg_name->setonly(); + } + + if (cfg.audio.channel == 1) { + fl_g->choice_cfg_channel->value(CHOICE_MONO); + } + else { + fl_g->choice_cfg_channel->value(CHOICE_STEREO); + } + + fl_g->input_cfg_present_level->value(-cfg.audio.signal_level); + fl_g->input_cfg_absent_level->value(-cfg.audio.silence_level); + + fl_g->input_cfg_buffer->value(cfg.audio.buffer_ms); + + fl_g->choice_cfg_resample_mode->value(cfg.audio.resample_mode); + + // Fill stream section + char delay[32]; + fl_g->choice_cfg_song_delay->textsize(14); + for (int i = 0; i < 11; i++) { + snprintf(delay, sizeof(delay), _("%d seconds"), 2 * i); + fl_g->choice_cfg_song_delay->add(delay); + } + fl_g->check_song_update_active->value(cfg.main.song_update); + fl_g->check_read_last_line->value(cfg.main.read_last_line); + fl_g->choice_cfg_song_delay->value(cfg.main.song_delay / 2); + + fl_g->check_cfg_update_from_url->value(cfg.main.song_update_url_active); + fl_g->input_cfg_url_update_song_interval->value(cfg.main.song_update_url_interval); + fl_g->input_cfg_song_url->value(cfg.main.song_update_url); + + fl_g->input_cfg_song_file->value(cfg.main.song_path); + fl_g->input_cfg_signal->value(cfg.main.signal_threshold); + fl_g->input_cfg_silence->value(cfg.main.silence_threshold); + fl_g->check_stream_signal->value(cfg.main.signal_detection); + fl_g->check_stream_silence->value(cfg.main.silence_detection); + + fl_g->input_cfg_reconnect_delay->value(cfg.main.reconnect_delay); + + fl_g->input_cfg_song_prefix->value(cfg.main.song_prefix); + fl_g->input_cfg_song_suffix->value(cfg.main.song_suffix); + +#if __APPLE__ && __MACH__ + fl_g->choice_cfg_app->add("iTunes\\/Music"); + fl_g->choice_cfg_app->add("Spotify"); + fl_g->choice_cfg_app->add("VOX"); + fl_g->check_cfg_use_app->value(cfg.main.app_update); + fl_g->choice_cfg_app->value(cfg.main.app_update_service); + if (cfg.main.app_artist_title_order == APP_ARTIST_FIRST) { + fl_g->radio_cfg_artist_title->setonly(); + } + else { + fl_g->radio_cfg_title_artist->setonly(); + } +#elif (__linux__ || __FreeBSD__) && HAVE_DBUS + fl_g->choice_cfg_app->add("Rhythmbox"); + fl_g->choice_cfg_app->add("Banshee"); + fl_g->choice_cfg_app->add("Clementine"); + fl_g->choice_cfg_app->add("Spotify"); + fl_g->choice_cfg_app->add("Cantata"); + fl_g->choice_cfg_app->add("Strawberry"); + fl_g->choice_cfg_app->add("Plexamp"); + fl_g->check_cfg_use_app->value(cfg.main.app_update); + fl_g->choice_cfg_app->value(cfg.main.app_update_service); + if (cfg.main.app_artist_title_order == APP_ARTIST_FIRST) { + fl_g->radio_cfg_artist_title->setonly(); + } + else { + fl_g->radio_cfg_title_artist->setonly(); + } +#elif WIN32 + fl_g->choice_cfg_app->add(_("Not supported on Windows")); + fl_g->choice_cfg_app->value(0); + fl_g->check_cfg_use_app->value(0); + fl_g->check_cfg_use_app->deactivate(); + fl_g->choice_cfg_app->deactivate(); + fl_g->radio_cfg_artist_title->deactivate(); + fl_g->radio_cfg_title_artist->deactivate(); +#endif + + // fill the record section + fl_g->input_rec_filename->value(cfg.rec.filename); + fl_g->input_rec_folder->value(cfg.rec.folder); + fl_g->input_rec_split_time->value(cfg.rec.split_time); + + if (!strcmp(cfg.rec.codec, "mp3")) { + rec_codec_idx = CHOICE_MP3; + } + else if (!strcmp(cfg.rec.codec, "ogg")) { + rec_codec_idx = CHOICE_OGG; + } + else if (!strcmp(cfg.rec.codec, "opus")) { + rec_codec_idx = CHOICE_OPUS; + } + else if (!strcmp(cfg.rec.codec, "aac")) { + rec_codec_idx = CHOICE_AAC; + } + else if (!strcmp(cfg.rec.codec, "flac")) { + rec_codec_idx = CHOICE_FLAC; + fl_g->choice_rec_bitrate->hide(); + } + else { // wav + rec_codec_idx = CHOICE_WAV; + fl_g->choice_rec_bitrate->hide(); + } + + update_rec_bitrate_list(rec_codec_idx); + + fl_g->choice_rec_codec->value(rec_codec_idx); + fl_g->choice_rec_bitrate->value(get_bitrate_index(rec_codec_idx, cfg.rec.bitrate)); + + if (cfg.rec.start_rec) { + fl_g->check_cfg_auto_start_rec->value(1); + } + else { + fl_g->check_cfg_auto_start_rec->value(0); + } + + if (cfg.rec.stop_rec) { + fl_g->check_cfg_auto_stop_rec->value(1); + } + else { + fl_g->check_cfg_auto_stop_rec->value(0); + } + + if (cfg.rec.rec_after_launch) { + fl_g->check_cfg_rec_after_launch->value(1); + } + else { + fl_g->check_cfg_rec_after_launch->value(0); + } + + if (cfg.rec.overwrite_files) { + fl_g->check_cfg_overwrite_existing_files->value(1); + } + else { + fl_g->check_cfg_overwrite_existing_files->value(0); + } + + if (cfg.rec.sync_to_hour) { + fl_g->check_sync_to_full_hour->value(1); + } + else { + fl_g->check_sync_to_full_hour->value(0); + } + + fl_g->input_rec_signal->value(cfg.rec.signal_threshold); + fl_g->input_rec_silence->value(cfg.rec.silence_threshold); + fl_g->check_rec_signal->value(cfg.rec.signal_detection); + fl_g->check_rec_silence->value(cfg.rec.silence_detection); + + // fill the ssl/tls section + fl_g->input_tls_cert_file->value(cfg.tls.cert_file); + fl_g->input_tls_cert_dir->value(cfg.tls.cert_dir); + + update_samplerates_list(); + update_channel_lists(); + + // fill the DSP section + fl_g->check_stream_eq->value(cfg.dsp.equalizer_stream); + fl_g->check_rec_eq->value(cfg.dsp.equalizer_rec); + + int choice_eq_idx; + if (strcmp(cfg.dsp.eq_preset, "Manual") == 0) { + choice_eq_idx = 0; + } + else { + choice_eq_idx = fl_g->choice_eq_preset->find_index(cfg.dsp.eq_preset); + } + fl_g->choice_eq_preset->value(choice_eq_idx); + fl_g->choice_eq_preset->do_callback(); + + fl_g->check_stream_drc->value(cfg.dsp.compressor_stream); + fl_g->check_rec_drc->value(cfg.dsp.compressor_rec); + fl_g->check_aggressive_mode->value(cfg.dsp.aggressive_mode); + + slider_threshold_cb(cfg.dsp.threshold); + fl_g->thresholdSlider->value(cfg.dsp.threshold); + + slider_ratio_cb(cfg.dsp.ratio); + fl_g->ratioSlider->value(cfg.dsp.ratio); + + slider_attack_cb(cfg.dsp.attack); + fl_g->attackSlider->value(cfg.dsp.attack); + + slider_release_cb(cfg.dsp.release); + fl_g->releaseSlider->value(cfg.dsp.release); + + slider_makeup_cb(cfg.dsp.makeup_gain); + fl_g->makeupSlider->value(cfg.dsp.makeup_gain); + + // fill audio mixer + slider_mixer_primary_device_cb(util_factor_to_db(cfg.mixer.primary_device_gain), (void *)CB_CALLED_BY_CODE); + fl_g->slider_mixer_primary_device->value(util_factor_to_db(cfg.mixer.primary_device_gain)); + + slider_mixer_secondary_device_cb(util_factor_to_db(cfg.mixer.secondary_device_gain), (void *)CB_CALLED_BY_CODE); + fl_g->slider_mixer_secondary_device->value(util_factor_to_db(cfg.mixer.secondary_device_gain)); + + slider_mixer_streaming_gain_cb(util_factor_to_db(cfg.mixer.streaming_gain), (void *)CB_CALLED_BY_CODE); + fl_g->slider_mixer_streaming_gain->value(util_factor_to_db(cfg.mixer.streaming_gain)); + + slider_mixer_recording_gain_cb(util_factor_to_db(cfg.mixer.recording_gain), (void *)CB_CALLED_BY_CODE); + fl_g->slider_mixer_recording_gain->value(util_factor_to_db(cfg.mixer.recording_gain)); + + slider_mixer_cross_fader_cb(cfg.mixer.cross_fader, (void *)CB_CALLED_BY_CODE); + fl_g->slider_mixer_cross_fader->value(cfg.mixer.cross_fader); + + fl_g->button_mixer_mute_primary_device->value(cfg.mixer.primary_device_muted); + fl_g->button_mixer_mute_primary_device->do_callback(); + fl_g->button_mixer_mute_secondary_device->value(cfg.mixer.secondary_device_muted); + fl_g->button_mixer_mute_secondary_device->do_callback(); + + // fill the GUI section + fl_g->button_gui_bg_color->color(cfg.main.bg_color, fl_lighter((Fl_Color)cfg.main.bg_color)); + fl_g->button_gui_text_color->color(cfg.main.txt_color, fl_lighter((Fl_Color)cfg.main.txt_color)); + fl_g->check_gui_attach->value(cfg.gui.attach); + fl_g->check_gui_ontop->value(cfg.gui.ontop); + if (cfg.gui.ontop) { + fl_g->window_main->stay_on_top(1); + fl_g->window_cfg->stay_on_top(1); + } + fl_g->check_gui_hide_log_window->value(cfg.gui.hide_log_window); + fl_g->check_gui_remember_pos->value(cfg.gui.remember_pos); + + fl_g->check_gui_lcd_auto->value(cfg.gui.lcd_auto); + + fl_g->check_gui_start_minimized->value(cfg.gui.start_minimized); + + fl_g->check_gui_disable_gain_slider->value(cfg.gui.disable_gain_slider); + fl_g->check_gui_disable_gain_slider->do_callback(); + + fl_g->check_gui_show_listeners->value(cfg.gui.show_listeners); + fl_g->input_gui_listeners_update_rate->value(cfg.gui.listeners_update_rate); + + fl_g->choice_gui_language->value(lang_str_to_id(cfg.gui.lang_str)); + + if (cfg.gui.vu_mode == VU_MODE_GRADIENT) { + fl_g->radio_gui_vu_gradient->setonly(); + } + else { + fl_g->radio_gui_vu_solid->setonly(); + } + + fl_g->button_gui_vu_low_color->color(cfg.gui.vu_low_color, fl_lighter((Fl_Color)cfg.gui.vu_low_color)); + fl_g->button_gui_vu_mid_color->color(cfg.gui.vu_mid_color, fl_lighter((Fl_Color)cfg.gui.vu_mid_color)); + fl_g->button_gui_vu_high_color->color(cfg.gui.vu_high_color, fl_lighter((Fl_Color)cfg.gui.vu_high_color)); + fl_g->input_gui_vu_mid_range_start->value(cfg.gui.vu_mid_range_start); + fl_g->input_gui_vu_high_range_start->value(cfg.gui.vu_high_range_start); + + fl_g->check_gui_always_show_vu_tabs->value(cfg.gui.always_show_vu_tabs); + fl_g->check_gui_always_show_vu_tabs->do_callback(); + + if (strlen(cfg.gui.window_title) > 0) { + fl_g->input_gui_window_title->value(cfg.gui.window_title); + fl_g->window_main->label(cfg.gui.window_title); + } + + // fill mp3 codec settings section + + fl_g->choice_stream_mp3_enc_quality->value(cfg.mp3_codec_stream.enc_quality); + fl_g->choice_stream_mp3_stereo_mode->value(cfg.mp3_codec_stream.stereo_mode); + fl_g->choice_stream_mp3_bitrate_mode->value(cfg.mp3_codec_stream.bitrate_mode); + fl_g->choice_stream_mp3_vbr_quality->value(cfg.mp3_codec_stream.vbr_quality); + fl_g->choice_stream_mp3_vbr_min_bitrate->value(get_bitrate_index(CHOICE_MP3, cfg.mp3_codec_stream.vbr_min_bitrate)); + fl_g->choice_stream_mp3_vbr_max_bitrate->value(get_bitrate_index(CHOICE_MP3, cfg.mp3_codec_stream.vbr_max_bitrate)); + fl_g->check_stream_mp3_force_min_bitrate->value(cfg.mp3_codec_stream.vbr_force_min_bitrate); + fl_g->check_stream_mp3_activate_lowpass_freq->value(cfg.mp3_codec_stream.lowpass_freq_active); + fl_g->input_stream_mp3_lowpass_freq->value(cfg.mp3_codec_stream.lowpass_freq); + fl_g->check_stream_mp3_activate_lowpass_width->value(cfg.mp3_codec_stream.lowpass_width_active); + fl_g->input_stream_mp3_lowpass_width->value(cfg.mp3_codec_stream.lowpass_width); + fl_g->check_stream_mp3_activate_highpass_freq->value(cfg.mp3_codec_stream.highpass_freq_active); + fl_g->input_stream_mp3_highpass_freq->value(cfg.mp3_codec_stream.highpass_freq); + fl_g->check_stream_mp3_activate_highpass_width->value(cfg.mp3_codec_stream.highpass_width_active); + fl_g->input_stream_mp3_highpass_width->value(cfg.mp3_codec_stream.highpass_width); + + cfg.mp3_codec_stream.lowpass_freq_active > 0 ? fl_g->input_stream_mp3_lowpass_freq->activate() : fl_g->input_stream_mp3_lowpass_freq->deactivate(); + cfg.mp3_codec_stream.lowpass_width_active > 0 ? fl_g->input_stream_mp3_lowpass_width->activate() : fl_g->input_stream_mp3_lowpass_width->deactivate(); + cfg.mp3_codec_stream.highpass_freq_active > 0 ? fl_g->input_stream_mp3_highpass_freq->activate() : fl_g->input_stream_mp3_highpass_freq->deactivate(); + cfg.mp3_codec_stream.highpass_width_active > 0 ? fl_g->input_stream_mp3_highpass_width->activate() : fl_g->input_stream_mp3_highpass_width->deactivate(); + + switch (cfg.mp3_codec_stream.resampling_freq) { + case CHOICE_MP3_RESAMPLING_DISABLED: + fl_g->choice_stream_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_DISABLED); + break; + case 8000: + fl_g->choice_stream_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_8000); + break; + case 11025: + fl_g->choice_stream_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_11025); + break; + case 12000: + fl_g->choice_stream_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_12000); + break; + case 16000: + fl_g->choice_stream_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_16000); + break; + case 22050: + fl_g->choice_stream_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_22050); + break; + case 24000: + fl_g->choice_stream_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_24000); + break; + case 32000: + fl_g->choice_stream_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_32000); + break; + case 44100: + fl_g->choice_stream_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_44100); + break; + case 48000: + fl_g->choice_stream_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_48000); + break; + default: + fl_g->choice_stream_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_DISABLED); + } + + fl_g->choice_rec_mp3_enc_quality->value(cfg.mp3_codec_rec.enc_quality); + fl_g->choice_rec_mp3_stereo_mode->value(cfg.mp3_codec_rec.stereo_mode); + fl_g->choice_rec_mp3_bitrate_mode->value(cfg.mp3_codec_rec.bitrate_mode); + fl_g->choice_rec_mp3_vbr_quality->value(cfg.mp3_codec_rec.vbr_quality); + fl_g->choice_rec_mp3_vbr_min_bitrate->value(get_bitrate_index(CHOICE_MP3, cfg.mp3_codec_rec.vbr_min_bitrate)); + fl_g->choice_rec_mp3_vbr_max_bitrate->value(get_bitrate_index(CHOICE_MP3, cfg.mp3_codec_rec.vbr_max_bitrate)); + fl_g->check_rec_mp3_force_min_bitrate->value(cfg.mp3_codec_rec.vbr_force_min_bitrate); + fl_g->check_rec_mp3_activate_lowpass_freq->value(cfg.mp3_codec_rec.lowpass_freq_active); + fl_g->input_rec_mp3_lowpass_freq->value(cfg.mp3_codec_rec.lowpass_freq); + fl_g->check_rec_mp3_activate_lowpass_width->value(cfg.mp3_codec_rec.lowpass_width_active); + fl_g->input_rec_mp3_lowpass_width->value(cfg.mp3_codec_rec.lowpass_width); + fl_g->check_rec_mp3_activate_highpass_freq->value(cfg.mp3_codec_rec.highpass_freq_active); + fl_g->input_rec_mp3_highpass_freq->value(cfg.mp3_codec_rec.highpass_freq); + fl_g->check_rec_mp3_activate_highpass_width->value(cfg.mp3_codec_rec.highpass_width_active); + fl_g->input_rec_mp3_highpass_width->value(cfg.mp3_codec_rec.highpass_width); + + cfg.mp3_codec_rec.lowpass_freq_active > 0 ? fl_g->input_rec_mp3_lowpass_freq->activate() : fl_g->input_rec_mp3_lowpass_freq->deactivate(); + cfg.mp3_codec_rec.lowpass_width_active > 0 ? fl_g->input_rec_mp3_lowpass_width->activate() : fl_g->input_rec_mp3_lowpass_width->deactivate(); + cfg.mp3_codec_rec.highpass_freq_active > 0 ? fl_g->input_rec_mp3_highpass_freq->activate() : fl_g->input_rec_mp3_highpass_freq->deactivate(); + cfg.mp3_codec_rec.highpass_width_active > 0 ? fl_g->input_rec_mp3_highpass_width->activate() : fl_g->input_rec_mp3_highpass_width->deactivate(); + + switch (cfg.mp3_codec_rec.resampling_freq) { + case CHOICE_MP3_RESAMPLING_DISABLED: + fl_g->choice_rec_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_DISABLED); + break; + case 8000: + fl_g->choice_rec_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_8000); + break; + case 11025: + fl_g->choice_rec_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_11025); + break; + case 12000: + fl_g->choice_rec_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_12000); + break; + case 16000: + fl_g->choice_rec_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_16000); + break; + case 22050: + fl_g->choice_rec_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_22050); + break; + case 24000: + fl_g->choice_rec_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_24000); + break; + case 32000: + fl_g->choice_rec_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_32000); + break; + case 44100: + fl_g->choice_rec_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_44100); + break; + case 48000: + fl_g->choice_rec_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_48000); + break; + default: + fl_g->choice_rec_mp3_resampling_freq->value(CHOICE_MP3_RESAMPLING_DISABLED); + } + + // fill vorbis codec settings section + int *bitrates; + int num_of_bitrates = get_bitrate_list_for_codec(CHOICE_OGG, &bitrates); + char br[8]; + + fl_g->choice_stream_vorbis_vbr_min_bitrate->textsize(14); + fl_g->choice_stream_vorbis_vbr_max_bitrate->textsize(14); + fl_g->choice_rec_vorbis_vbr_min_bitrate->textsize(14); + fl_g->choice_rec_vorbis_vbr_max_bitrate->textsize(14); + fl_g->choice_stream_vorbis_vbr_min_bitrate->add("Auto (default)"); + fl_g->choice_stream_vorbis_vbr_max_bitrate->add("Auto (default)"); + fl_g->choice_rec_vorbis_vbr_min_bitrate->add("Auto (default)"); + fl_g->choice_rec_vorbis_vbr_max_bitrate->add("Auto (default)"); + for (int i = 0; i < num_of_bitrates; i++) { + snprintf(br, sizeof(br), "%ik", bitrates[i]); + fl_g->choice_stream_vorbis_vbr_min_bitrate->add(br); + fl_g->choice_stream_vorbis_vbr_max_bitrate->add(br); + fl_g->choice_rec_vorbis_vbr_min_bitrate->add(br); + fl_g->choice_rec_vorbis_vbr_max_bitrate->add(br); + } + fl_g->choice_stream_vorbis_bitrate_mode->value(cfg.vorbis_codec_stream.bitrate_mode); + fl_g->choice_stream_vorbis_vbr_quality->value(cfg.vorbis_codec_stream.vbr_quality); + if (cfg.vorbis_codec_stream.vbr_min_bitrate > 0) { + fl_g->choice_stream_vorbis_vbr_min_bitrate->value(get_bitrate_index(CHOICE_OGG, cfg.vorbis_codec_stream.vbr_min_bitrate) + 1); + } + else { + fl_g->choice_stream_vorbis_vbr_min_bitrate->value(0); + } + + if (cfg.vorbis_codec_stream.vbr_max_bitrate > 0) { + fl_g->choice_stream_vorbis_vbr_max_bitrate->value(get_bitrate_index(CHOICE_OGG, cfg.vorbis_codec_stream.vbr_max_bitrate) + 1); + } + else { + fl_g->choice_stream_vorbis_vbr_max_bitrate->value(0); + } + + fl_g->choice_rec_vorbis_bitrate_mode->value(cfg.vorbis_codec_rec.bitrate_mode); + fl_g->choice_rec_vorbis_vbr_quality->value(cfg.vorbis_codec_rec.vbr_quality); + + if (cfg.vorbis_codec_rec.vbr_min_bitrate > 0) { + fl_g->choice_rec_vorbis_vbr_min_bitrate->value(get_bitrate_index(CHOICE_OGG, cfg.vorbis_codec_rec.vbr_min_bitrate) + 1); + } + else { + fl_g->choice_rec_vorbis_vbr_min_bitrate->value(0); + } + + if (cfg.vorbis_codec_rec.vbr_max_bitrate > 0) { + fl_g->choice_rec_vorbis_vbr_max_bitrate->value(get_bitrate_index(CHOICE_OGG, cfg.vorbis_codec_rec.vbr_max_bitrate) + 1); + } + else { + fl_g->choice_rec_vorbis_vbr_max_bitrate->value(0); + } + + // fill opus codec settings section + fl_g->choice_stream_opus_bitrate_mode->value(cfg.opus_codec_stream.bitrate_mode); + fl_g->choice_stream_opus_quality->value(cfg.opus_codec_stream.quality); + fl_g->choice_stream_opus_audio_type->value(cfg.opus_codec_stream.audio_type); + fl_g->choice_stream_opus_bandwidth->value(cfg.opus_codec_stream.bandwidth); + + fl_g->choice_rec_opus_bitrate_mode->value(cfg.opus_codec_rec.bitrate_mode); + fl_g->choice_rec_opus_quality->value(cfg.opus_codec_rec.quality); + fl_g->choice_rec_opus_audio_type->value(cfg.opus_codec_rec.audio_type); + fl_g->choice_rec_opus_bandwidth->value(cfg.opus_codec_rec.bandwidth); + + // fill aac codec settings section + fl_g->choice_stream_aac_bitrate_mode->value(cfg.aac_codec_stream.bitrate_mode); + fl_g->choice_stream_aac_afterburner->value(cfg.aac_codec_stream.afterburner); + fl_g->choice_stream_aac_profile->value(cfg.aac_codec_stream.profile); + + fl_g->choice_rec_aac_bitrate_mode->value(cfg.aac_codec_rec.bitrate_mode); + fl_g->choice_rec_aac_afterburner->value(cfg.aac_codec_rec.afterburner); + fl_g->choice_rec_aac_profile->value(cfg.aac_codec_rec.profile); + + // fill flac codec settings section + switch (cfg.flac_codec_stream.bit_depth) { + case 16: + fl_g->radio_stream_flac_bit_depth_16->setonly(); + break; + case 24: + fl_g->radio_stream_flac_bit_depth_24->setonly(); + break; + default: + fl_g->radio_stream_flac_bit_depth_16->setonly(); + break; + } + + switch (cfg.flac_codec_rec.bit_depth) { + case 16: + fl_g->radio_rec_flac_bit_depth_16->setonly(); + break; + case 24: + fl_g->radio_rec_flac_bit_depth_24->setonly(); + break; + default: + fl_g->radio_rec_flac_bit_depth_16->setonly(); + break; + } + +#if __LITTLE_ENDIAN__ != 1 and __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ +#warning("24 bit wav recording has been disabled because it has not been tested on a big endian machine yet") + fl_g->radio_rec_wav_bit_depth_24->hide(); +#endif + + // fill wav codec settings section + switch (cfg.wav_codec_rec.bit_depth) { + case 16: + fl_g->radio_rec_wav_bit_depth_16->setonly(); + break; + case 24: + fl_g->radio_rec_wav_bit_depth_24->setonly(); + break; + case 32: + fl_g->radio_rec_wav_bit_depth_32->setonly(); + break; + default: + fl_g->radio_rec_wav_bit_depth_16->setonly(); + break; + } + + // Fill MIDI section + populate_midi_dev_list(); + fl_g->browser_midi_command->clear(); + fl_g->browser_midi_command->add(_("Start/Stop broadcasting")); + fl_g->browser_midi_command->add(_("Start/Stop recording")); + fl_g->browser_midi_command->add(_("Master Gain")); + fl_g->browser_midi_command->add(_("Streaming Gain")); + fl_g->browser_midi_command->add(_("Recording Gain")); + fl_g->browser_midi_command->add(_("Primary Device Gain")); + fl_g->browser_midi_command->add(_("Secondary Device Gain")); + fl_g->browser_midi_command->add(_("Cross fader")); + fl_g->browser_midi_command->add(_("Mute/Unmute Primary Device")); + fl_g->browser_midi_command->add(_("Mute/Unmute Secondary Device")); + fl_g->browser_midi_command->add(_("Start broadcasting")); + fl_g->browser_midi_command->add(_("Stop broadcasting")); + fl_g->browser_midi_command->add(_("Start recording")); + fl_g->browser_midi_command->add(_("Stop recording")); + fl_g->browser_midi_command->select(1); // Select first line (Yes, the line counter starts with 1) + fl_g->check_midi_command_enable->value(cfg.midi.commands[0].enabled); + fl_g->choice_midi_channel->value(cfg.midi.commands[0].channel); + fl_g->input_midi_msg_num->value(cfg.midi.commands[0].msg_num); + fl_g->choice_midi_cc_mode->value(cfg.midi.commands[0].mode); + fl_g->check_midi_soft_takeover->value(cfg.midi.commands[0].soft_takeover); + + // Disable CC mode and soft takeover for first command (Start/Stop broadcasting) + fl_g->choice_midi_cc_mode->deactivate(); + fl_g->check_midi_soft_takeover->deactivate(); +} + +void read_eq_slider_values(void) +{ + cfg.dsp.eq_gain[0] = fl_g->equalizerSlider1->value(); + cfg.dsp.eq_gain[1] = fl_g->equalizerSlider2->value(); + cfg.dsp.eq_gain[2] = fl_g->equalizerSlider3->value(); + cfg.dsp.eq_gain[3] = fl_g->equalizerSlider4->value(); + cfg.dsp.eq_gain[4] = fl_g->equalizerSlider5->value(); + cfg.dsp.eq_gain[5] = fl_g->equalizerSlider6->value(); + cfg.dsp.eq_gain[6] = fl_g->equalizerSlider7->value(); + cfg.dsp.eq_gain[7] = fl_g->equalizerSlider8->value(); + cfg.dsp.eq_gain[8] = fl_g->equalizerSlider9->value(); + cfg.dsp.eq_gain[9] = fl_g->equalizerSlider10->value(); +} + +// Updates the samplerate drop down menu for the audio +// device the user has selected +void update_samplerates_list(void) +{ + int i; + int *sr_list; + char sr_asc[10]; + + fl_g->choice_cfg_samplerate->clear(); + fl_g->choice_cfg_samplerate->textsize(14); + + sr_list = cfg.audio.pcm_list[cfg.audio.dev_num]->sr_list; + + for (i = 0; sr_list[i] != 0; i++) { + snprintf(sr_asc, sizeof(sr_asc), "%dHz", sr_list[i]); + fl_g->choice_cfg_samplerate->add(sr_asc); + + if (cfg.audio.samplerate == sr_list[i]) { + fl_g->choice_cfg_samplerate->value(i); + } + } + if (i == 0) { + fl_g->choice_cfg_samplerate->add(_("dev. not supported")); + fl_g->choice_cfg_samplerate->value(0); + } +} + +void update_channel_lists(void) +{ + int i; + char ch_num_txt[16]; + + int dev_num = cfg.audio.dev_num; + int num_of_channels = cfg.audio.pcm_list[dev_num]->num_of_channels; + + fl_g->choice_cfg_left_channel->clear(); + fl_g->choice_cfg_left_channel->redraw(); + fl_g->choice_cfg_left_channel->textsize(14); + fl_g->choice_cfg_right_channel->clear(); + fl_g->choice_cfg_right_channel->redraw(); + fl_g->choice_cfg_right_channel->textsize(14); + + for (i = 1; i <= num_of_channels; i++) { + snprintf(ch_num_txt, sizeof(ch_num_txt), "%d", i); + fl_g->choice_cfg_left_channel->add(ch_num_txt); + fl_g->choice_cfg_right_channel->add(ch_num_txt); + } + + fl_g->choice_cfg_left_channel->value(cfg.audio.left_ch - 1); + fl_g->choice_cfg_right_channel->value(cfg.audio.right_ch - 1); + + fl_g->choice_cfg_left_channel2->clear(); + fl_g->choice_cfg_left_channel2->redraw(); + fl_g->choice_cfg_left_channel->textsize(14); + fl_g->choice_cfg_right_channel2->clear(); + fl_g->choice_cfg_right_channel2->redraw(); + fl_g->choice_cfg_right_channel->textsize(14); + + if (cfg.audio.dev2_num >= 0) { + dev_num = cfg.audio.dev2_num; + num_of_channels = cfg.audio.pcm_list[dev_num]->num_of_channels; + + for (i = 1; i <= num_of_channels; i++) { + snprintf(ch_num_txt, sizeof(ch_num_txt), "%d", i); + fl_g->choice_cfg_left_channel2->add(ch_num_txt); + fl_g->choice_cfg_right_channel2->add(ch_num_txt); + } + fl_g->choice_cfg_left_channel2->value(cfg.audio.left_ch2 - 1); + fl_g->choice_cfg_right_channel2->value(cfg.audio.right_ch2 - 1); + } +} + +void write_log(const char *message, const char *path) +{ + int len; + FILE *log_fd; + char logtimestamp[32]; + char *infotxt; + time_t current_time; + struct tm *current_localtime; + + /* if ((cfg.main.log_file != NULL) && (strlen(cfg.main.log_file) > 0)) { + log_fd = fl_fopen(cfg.main.log_file, "ab"); + if (log_fd != NULL) { + fprintf(log_fd, "%s", message); + fclose(log_fd); + } + } + */ + + const char *log_file = path != NULL ? path : cfg.main.log_file; + + pthread_mutex_lock(&write_log_mutex); + + if ((log_file != NULL) && (strlen(log_file) > 0)) { + current_time = time(NULL); + current_localtime = localtime(¤t_time); + infotxt = strdup(message); + log_fd = fl_fopen(log_file, "ab"); + if (log_fd != NULL) { + strftime(logtimestamp, sizeof(logtimestamp), "%Y-%m-%d %H:%M:%S", current_localtime); + if (strchr(infotxt, ':')) { + strrpl(&infotxt, (char *)"\n", (char *)", ", MODE_ALL); + } + else { + strrpl(&infotxt, (char *)"\n", (char *)" ", MODE_ALL); + } + + strrpl(&infotxt, (char *)":,", (char *)": ", MODE_ALL); + strrpl(&infotxt, (char *)"\t", (char *)"", MODE_ALL); + + len = int(strlen(infotxt)) - 1; + + if (len > 0) { + // remove trailing commas and spaces + while (infotxt[len] == ',' || infotxt[len] == ' ') { + infotxt[len--] = '\0'; + if (len < 0) { + break; + } + } + + fprintf(log_fd, "%s %s\n", logtimestamp, infotxt); + } + fclose(log_fd); + } + free(infotxt); + } + + pthread_mutex_unlock(&write_log_mutex); +} + +void print_info(const char *info, int info_type) +{ + char timebuf[16]; + + time_t current_time; + struct tm *current_localtime; + static struct tm previous_localtime; + + current_time = time(NULL); + current_localtime = localtime(¤t_time); + + Fl::lock(); + + if ((previous_localtime.tm_min != current_localtime->tm_min) || (previous_localtime.tm_hour != current_localtime->tm_hour)) { + previous_localtime.tm_min = current_localtime->tm_min; + previous_localtime.tm_hour = current_localtime->tm_hour; + strftime(timebuf, sizeof(timebuf), "\n%H:%M:", current_localtime); + fl_g->info_buffer->append(timebuf); + } + + fl_g->info_buffer->append((const char *)"\n"); + fl_g->info_buffer->append((const char *)info); + + // always scroll to the last line + fl_g->info_output->scroll(fl_g->info_buffer->count_lines(0, // count the lines from char 0 to the last character + fl_g->info_buffer->length()), // returns the number of characters in the buffer + 0); + + Fl::unlock(); + + // log to log_file if defined + /* if ((cfg.main.log_file != NULL) && (strlen(cfg.main.log_file) > 0)) { + log_fd = fl_fopen(cfg.main.log_file, "ab"); + if (log_fd != NULL) { + strftime(logtimestamp, sizeof(logtimestamp), "%Y-%m-%d %H:%M:%S", current_localtime); + if (strchr(infotxt, ':')) { + strrpl(&infotxt, (char *)"\n", (char *)", ", MODE_ALL); + } + else { + strrpl(&infotxt, (char *)"\n", (char *)" ", MODE_ALL); + } + + strrpl(&infotxt, (char *)":,", (char *)": ", MODE_ALL); + strrpl(&infotxt, (char *)"\t", (char *)"", MODE_ALL); + + len = int(strlen(infotxt)) - 1; + + if (len > 0) { + // remove trailing commas and spaces + while (infotxt[len] == ',' || infotxt[len] == ' ') { + infotxt[len--] = '\0'; + if (len < 0) { + break; + } + } + + fprintf(log_fd, "%s %s\n", logtimestamp, infotxt); + } + fclose(log_fd); + } + }*/ + + write_log(info); +} + +void print_lcd(const char *text, int len, int home, int clear) +{ + if (!strcmp(text, _("idle"))) { + fl_g->sponsor_logo->show(); + } + else { + fl_g->sponsor_logo->hide(); + } + + if (clear) { + fl_g->lcd->clear(); + } + + fl_g->lcd->print((const uchar *)text, len); + + if (home) { + fl_g->lcd->cursor_pos(0); + } +} + +int eval_record_path(int use_previous_index) +{ + int ret; + int has_index_var = 0; + char *expanded_rec_folder; + char *expanded_filename; + char i_str[12]; + static uint32_t previous_index = 0; + + expanded_rec_folder = (char *)malloc(PATH_MAX * sizeof(char)); + + // Check and replace placeholders in record folder + + // expand environment vars like ~, $HOME and %LOCALAPPDATA% + fl_filename_expand(expanded_rec_folder, PATH_MAX, cfg.rec.folder); + + // Using %i in record folder is not allowed + strrpl(&expanded_rec_folder, (char *)"%i", (char *)"", MODE_ALL); + + // expand fmt variables like record_folder_%d_%m_%y to record_folder_05_11_2014 + ret = expand_string(&expanded_rec_folder); + if (ret == 0) { + fl_alert(_("Could not create recording folder:\n%s\nPlease make sure the folder contains only valid format specifiers."), cfg.rec.folder); + free(expanded_rec_folder); + return 1; + } + + // Replace %N with current server name if available + if (cfg.main.num_of_srv > 0) { + strrpl(&expanded_rec_folder, (char *)"%N", cfg.srv[cfg.selected_srv]->name, MODE_ALL); + } + else { + strrpl(&expanded_rec_folder, (char *)"%N", (char *)"", MODE_ALL); + } + + // Create recording directory if it does not exist yet + if (util_mkpath(expanded_rec_folder) != 0) { + fl_alert(_("Could not create recording folder %s\n"), expanded_rec_folder); + free(expanded_rec_folder); + return 1; + } + + // Check and replace placeholders in record file name + expanded_filename = strdup(cfg.rec.filename); + ret = expand_string(&expanded_filename); + if (ret == 0) { + fl_alert(_("Could not create recording file:\n%s\nPlease make sure the filename contains only valid format specifiers."), cfg.rec.filename); + free(expanded_filename); + free(expanded_rec_folder); + return 1; + } + + // Replace %N with current server name if available + if (cfg.main.num_of_srv > 0) { + strrpl(&expanded_filename, (char *)"%N", cfg.srv[cfg.selected_srv]->name, MODE_ALL); + } + else { + strrpl(&expanded_filename, (char *)"%N", (char *)"", MODE_ALL); + } + + // check if there is an index variable in the filename + if (strstr(cfg.rec.filename, "%i")) { + has_index_var = 1; + } + + cfg.rec.path = (char *)realloc(cfg.rec.path, (strlen(expanded_rec_folder) + strlen(expanded_filename) + 1) * sizeof(char)); + + strcpy(cfg.rec.path, expanded_rec_folder); + strcat(cfg.rec.path, expanded_filename); + + if (use_previous_index == 1) { + snprintf(i_str, sizeof(i_str), "%d", previous_index); + strrpl(&cfg.rec.path, (char *)"%i", i_str, MODE_ALL); + } + else { + strrpl(&cfg.rec.path, (char *)"%i", (char *)"1", MODE_ALL); + previous_index = 1; + + if (fl_access(cfg.rec.path, F_OK) == 0) { + if (has_index_var == 1) { + for (uint32_t i = 2; /*inf*/; i++) { + strcpy(cfg.rec.path, expanded_rec_folder); + strcat(cfg.rec.path, expanded_filename); + snprintf(i_str, sizeof(i_str), "%d", i); + strrpl(&cfg.rec.path, (char *)"%i", i_str, MODE_ALL); + + if (fl_access(cfg.rec.path, F_OK) < 0) { + previous_index = i; + break; + } + + if (i == 0xFFFFFFFF) { // 2^32-1 + fl_alert(_("Could not find a valid filename")); + free(expanded_filename); + free(expanded_rec_folder); + return 1; + } + } + } + } + } + + free(expanded_filename); + free(expanded_rec_folder); + + return 0; +} + +int expand_string(char **str) +{ + int str_len; + char expanded_str[1024]; + struct tm *date; + const time_t t = time(NULL); + + // The %i (index number) place holder must be replaced with %%i + // Otherwise strftime will replace %i with i and the index number will loose its function + strrpl(str, (char *)"%i", (char *)"%%i", MODE_ALL); + + // Above statement applies also to %N + strrpl(str, (char *)"%N", (char *)"%%N", MODE_ALL); + + // %c, %x, %X specifiers are not allowed because they return illegal characters for file names + // Therefore we make sure that strftime will ignore them + strrpl(str, (char *)"%c", (char *)"%%c", MODE_ALL); + strrpl(str, (char *)"%x", (char *)"%%x", MODE_ALL); + strrpl(str, (char *)"%X", (char *)"%%X", MODE_ALL); + + date = localtime(&t); + strftime(expanded_str, sizeof(expanded_str) - 1, *str, date); + + str_len = strlen(expanded_str); + *str = (char *)realloc(*str, str_len + 1); + strncpy(*str, expanded_str, str_len + 1); + return str_len; +} + +void test_file_extension(void) +{ + char *current_ext; + + current_ext = util_get_file_extension(cfg.rec.filename); + + // Append extension + if (current_ext == NULL) { + cfg.rec.filename = (char *)realloc(cfg.rec.filename, strlen(cfg.rec.filename) + strlen(cfg.rec.codec) + 2); + strcat(cfg.rec.filename, "."); + strcat(cfg.rec.filename, cfg.rec.codec); + fl_g->input_rec_filename->value(cfg.rec.filename); + } + // Replace extension + else if (strcmp(current_ext, cfg.rec.codec)) { + strrpl(&cfg.rec.filename, current_ext, cfg.rec.codec, MODE_LAST); + fl_g->input_rec_filename->value(cfg.rec.filename); + } +} + +void update_codec_samplerates(void) +{ + lame_stream.samplerate_in = cfg.audio.samplerate; + lame_rec.samplerate_in = cfg.audio.samplerate; + lame_enc_reinit(&lame_stream); + lame_enc_reinit(&lame_rec); + + vorbis_stream.samplerate = cfg.audio.samplerate; + vorbis_rec.samplerate = cfg.audio.samplerate; + vorbis_enc_reinit(&vorbis_stream); + vorbis_enc_reinit(&vorbis_rec); + + opus_stream.samplerate = cfg.audio.samplerate; + opus_rec.samplerate = cfg.audio.samplerate; + opus_enc_reinit(&opus_stream); + opus_enc_reinit(&opus_rec); + +#ifdef HAVE_LIBFDK_AAC + if (g_aac_lib_available == 1) { + aac_stream.samplerate = cfg.audio.samplerate; + aac_rec.samplerate = cfg.audio.samplerate; + aac_enc_reinit(&aac_stream); + aac_enc_reinit(&aac_rec); + } +#endif + + flac_stream.samplerate = cfg.audio.samplerate; + flac_rec.samplerate = cfg.audio.samplerate; + flac_enc_reinit(&flac_stream); + flac_enc_reinit(&flac_rec); +} + +void init_main_gui_and_audio(void) +{ + int sx, sy, sw, sh; + int butt_x, butt_y, butt_w, butt_h; + int current_screen; + + butt_w = fl_g->window_main->w(); + butt_h = fl_g->window_main->h(); + + Fl::screen_xywh(sx, sy, sw, sh); + current_screen = Fl::screen_num(sx, sy); + + // Make sure butt is opened at screen center on first start + if (cfg.gui.x_pos == -1 && cfg.gui.y_pos == -1) { + Fl::screen_xywh(sx, sy, sw, sh, current_screen); + cfg.gui.x_pos = sx + sw / 2 - butt_w / 2; + cfg.gui.y_pos = sy + sh / 2 - butt_h / 2; + } + + if (cfg.gui.remember_pos) { + butt_x = cfg.gui.x_pos; + butt_y = cfg.gui.y_pos; + + int is_visible = 0; + for (int i = 0; i < Fl::screen_count(); i++) { + Fl::screen_xywh(sx, sy, sw, sh, i); + if ((butt_x >= sx - butt_w + 50) && (butt_x + 50 < (sx + sw)) && (butt_y >= sy - butt_h + 50) && (butt_y + 50 < (sy + sh))) { + is_visible = 1; + } + } + + // Move butt window to the saved position only if at least 50 pixel of butt are visible on the screen + if (is_visible) { + fl_g->window_main->position(cfg.gui.x_pos, cfg.gui.y_pos); + } + + if (cfg.gui.window_height > 213) { + fl_g->window_main->resize(fl_g->window_main->x(), fl_g->window_main->y(), fl_g->window_main->w(), cfg.gui.window_height); + } + + // if( (butt_x+butt_w > 50) && (butt_x+50 < total_screen_width) && (butt_y+butt_h > 50) && (butt_y+50 < total_screen_height) ) + } + else { // Open at screen center if cfg.gui.remember_pos == 0 + Fl::screen_xywh(sx, sy, sw, sh, current_screen); + fl_g->window_main->position(sx + sw / 2 - butt_w / 2, sy + sh / 2 - butt_h / 2); + } + + fl_g->slider_gain->value(util_factor_to_db(cfg.main.gain)); + fl_g->slider_gain->do_callback(); + + if (cfg.gui.ontop) { + fl_g->window_main->stay_on_top(1); + } + + fl_g->button_info->label(_("Hide log")); + if (cfg.gui.hide_log_window) { + button_info_cb(); + } + + lame_stream.channel = cfg.audio.channel; + lame_stream.bitrate = cfg.audio.bitrate; + lame_stream.samplerate_in = cfg.audio.samplerate; + lame_stream.enc_quality = cfg.mp3_codec_stream.enc_quality; + lame_stream.stereo_mode = cfg.mp3_codec_stream.stereo_mode; + lame_stream.bitrate_mode = cfg.mp3_codec_stream.bitrate_mode; + lame_stream.vbr_quality = cfg.mp3_codec_stream.vbr_quality; + lame_stream.vbr_min_bitrate = cfg.mp3_codec_stream.vbr_min_bitrate; + lame_stream.vbr_max_bitrate = cfg.mp3_codec_stream.vbr_max_bitrate; + lame_stream.vbr_force_min_bitrate = cfg.mp3_codec_stream.vbr_force_min_bitrate; + lame_stream.lowpass_freq = cfg.mp3_codec_stream.lowpass_freq * cfg.mp3_codec_stream.lowpass_freq_active; + lame_stream.lowpass_width = cfg.mp3_codec_stream.lowpass_width * cfg.mp3_codec_stream.lowpass_width_active; + lame_stream.highpass_freq = cfg.mp3_codec_stream.highpass_freq * cfg.mp3_codec_stream.highpass_freq_active; + lame_stream.highpass_width = cfg.mp3_codec_stream.highpass_width * cfg.mp3_codec_stream.highpass_freq_active; + lame_stream.samplerate_out = cfg.mp3_codec_stream.resampling_freq > 0 ? cfg.mp3_codec_stream.resampling_freq : lame_stream.samplerate_in; + lame_enc_reinit(&lame_stream); + + lame_rec.channel = cfg.audio.channel; + lame_rec.bitrate = cfg.rec.bitrate; + lame_rec.samplerate_in = cfg.audio.samplerate; + lame_rec.enc_quality = cfg.mp3_codec_rec.enc_quality; + lame_rec.stereo_mode = cfg.mp3_codec_rec.stereo_mode; + lame_rec.bitrate_mode = cfg.mp3_codec_rec.bitrate_mode; + lame_rec.vbr_quality = cfg.mp3_codec_rec.vbr_quality; + lame_rec.vbr_min_bitrate = cfg.mp3_codec_rec.vbr_min_bitrate; + lame_rec.vbr_max_bitrate = cfg.mp3_codec_rec.vbr_max_bitrate; + lame_rec.vbr_force_min_bitrate = cfg.mp3_codec_rec.vbr_force_min_bitrate; + lame_rec.lowpass_freq = cfg.mp3_codec_rec.lowpass_freq * cfg.mp3_codec_rec.lowpass_freq_active; + lame_rec.lowpass_width = cfg.mp3_codec_rec.lowpass_width * cfg.mp3_codec_rec.lowpass_width_active; + lame_rec.highpass_freq = cfg.mp3_codec_rec.highpass_freq * cfg.mp3_codec_rec.highpass_freq_active; + lame_rec.highpass_width = cfg.mp3_codec_rec.highpass_width * cfg.mp3_codec_rec.highpass_freq_active; + lame_rec.samplerate_out = cfg.mp3_codec_rec.resampling_freq > 0 ? cfg.mp3_codec_rec.resampling_freq : lame_rec.samplerate_in; + lame_enc_reinit(&lame_rec); + + vorbis_stream.channel = cfg.audio.channel; + vorbis_stream.bitrate = cfg.audio.bitrate; + vorbis_stream.samplerate = cfg.audio.samplerate; + vorbis_stream.bitrate_mode = cfg.vorbis_codec_stream.bitrate_mode; + vorbis_stream.vbr_quality = 1 - (cfg.vorbis_codec_stream.vbr_quality * 0.1); + vorbis_stream.vbr_min_bitrate = cfg.vorbis_codec_stream.vbr_min_bitrate; + vorbis_stream.vbr_max_bitrate = cfg.vorbis_codec_stream.vbr_max_bitrate; + vorbis_enc_reinit(&vorbis_stream); + + vorbis_rec.channel = cfg.audio.channel; + vorbis_rec.bitrate = cfg.rec.bitrate; + vorbis_rec.samplerate = cfg.audio.samplerate; + vorbis_rec.bitrate_mode = cfg.vorbis_codec_rec.bitrate_mode; + vorbis_rec.vbr_quality = 1 - (cfg.vorbis_codec_rec.vbr_quality * 0.1); + vorbis_rec.vbr_min_bitrate = cfg.vorbis_codec_rec.vbr_min_bitrate; + vorbis_rec.vbr_max_bitrate = cfg.vorbis_codec_rec.vbr_max_bitrate; + vorbis_enc_reinit(&vorbis_rec); + + opus_stream.channel = cfg.audio.channel; + opus_stream.bitrate = cfg.audio.bitrate * 1000; + opus_stream.samplerate = cfg.audio.samplerate; + opus_stream.bitrate_mode = cfg.opus_codec_stream.bitrate_mode; + opus_stream.audio_type = cfg.opus_codec_stream.audio_type; + opus_stream.quality = cfg.opus_codec_stream.quality; + opus_stream.bandwidth = cfg.opus_codec_stream.bandwidth; + opus_enc_alloc(&opus_stream); + opus_enc_init(&opus_stream); + + opus_rec.channel = cfg.audio.channel; + opus_rec.bitrate = cfg.rec.bitrate * 1000; + opus_rec.samplerate = cfg.audio.samplerate; + opus_rec.bitrate_mode = cfg.opus_codec_rec.bitrate_mode; + opus_rec.audio_type = cfg.opus_codec_rec.audio_type; + opus_rec.quality = cfg.opus_codec_rec.quality; + opus_rec.bandwidth = cfg.opus_codec_rec.bandwidth; + opus_enc_alloc(&opus_rec); + opus_enc_init(&opus_rec); + +#ifdef HAVE_LIBFDK_AAC + if (g_aac_lib_available == 1) { + aac_stream.channel = cfg.audio.channel; + aac_stream.bitrate = cfg.audio.bitrate; + aac_stream.samplerate = cfg.audio.samplerate; + aac_stream.bitrate_mode = cfg.aac_codec_stream.bitrate_mode; + aac_stream.profile = cfg.aac_codec_stream.profile; + aac_stream.afterburner = cfg.aac_codec_stream.afterburner == 0 ? 1 : 0; + aac_enc_reinit(&aac_stream); + + aac_rec.channel = cfg.audio.channel; + aac_rec.bitrate = cfg.rec.bitrate; + aac_rec.samplerate = cfg.audio.samplerate; + aac_rec.bitrate_mode = cfg.aac_codec_rec.bitrate_mode; + aac_rec.profile = cfg.aac_codec_rec.profile; + aac_rec.afterburner = cfg.aac_codec_rec.afterburner == 0 ? 1 : 0; + aac_enc_reinit(&aac_rec); + } +#endif + + flac_stream.channel = cfg.audio.channel; + flac_stream.samplerate = cfg.audio.samplerate; + flac_stream.enc_type = FLAC_ENC_TYPE_STREAM; + flac_stream.bit_depth = cfg.flac_codec_stream.bit_depth; + flac_enc_reinit(&flac_stream); + + flac_rec.channel = cfg.audio.channel; + flac_rec.samplerate = cfg.audio.samplerate; + flac_rec.enc_type = FLAC_ENC_TYPE_REC; + flac_rec.bit_depth = cfg.flac_codec_rec.bit_depth; + flac_enc_reinit(&flac_rec); +} + +char *ask_user_msg = NULL; +char *ask_user_hash = NULL; +int ask_user_has_clicked = 0; +int ask_user_answer = 0; + +void ask_user_reset(void) +{ + if (ask_user_msg != NULL) { + free(ask_user_msg); + ask_user_msg = NULL; + } + if (ask_user_hash != NULL) { + free(ask_user_hash); + ask_user_hash = NULL; + } + ask_user_has_clicked = 0; +} + +int ask_user_get_has_clicked(void) +{ + return ask_user_has_clicked; +} + +int ask_user_get_answer(void) +{ + return ask_user_answer; +} + +void ask_user_set_msg(char *msg) +{ + int len = strlen(msg); + ask_user_msg = (char *)calloc(len + 1, sizeof(char)); + strncpy(ask_user_msg, msg, len); +} + +void ask_user_set_hash(char *hash) +{ + int len = strlen(hash); + ask_user_hash = (char *)calloc(len + 1, sizeof(char)); + strncpy(ask_user_hash, hash, len); +} + +void ask_user_ask(void) +{ + if (fl_choice("%s", _("TRUST"), _("No"), NULL, ask_user_msg) == 1) { // No + ask_user_answer = IC_ABORT; + } + else { // TRUST + int len = strlen(ask_user_hash); + cfg.srv[cfg.selected_srv]->cert_hash = (char *)realloc(cfg.srv[cfg.selected_srv]->cert_hash, len + 1); + + memset(cfg.srv[cfg.selected_srv]->cert_hash, 0, len + 1); + strncpy(cfg.srv[cfg.selected_srv]->cert_hash, ask_user_hash, len); + ask_user_answer = IC_RETRY; + } + + ask_user_has_clicked = 1; +} + +void activate_stream_ui_elements(void) +{ + if (!recording) { + fl_g->choice_cfg_channel->activate(); + fl_g->choice_cfg_dev->activate(); + fl_g->choice_cfg_dev2->activate(); + fl_g->choice_cfg_samplerate->activate(); + fl_g->button_cfg_rescan_devices->activate(); + fl_g->button_cfg_import->activate(); + } + + fl_g->choice_cfg_codec->activate(); + fl_g->choice_cfg_bitrate->activate(); + + fl_g->choice_stream_mp3_enc_quality->activate(); + fl_g->choice_stream_mp3_stereo_mode->activate(); + fl_g->choice_stream_mp3_vbr_quality->activate(); + fl_g->choice_stream_mp3_bitrate_mode->activate(); + fl_g->choice_stream_mp3_vbr_min_bitrate->activate(); + fl_g->choice_stream_mp3_vbr_max_bitrate->activate(); + fl_g->check_stream_mp3_force_min_bitrate->activate(); + fl_g->choice_stream_mp3_resampling_freq->activate(); + fl_g->check_stream_mp3_activate_lowpass_freq->activate(); + fl_g->check_stream_mp3_activate_lowpass_width->activate(); + fl_g->check_stream_mp3_activate_highpass_freq->activate(); + fl_g->check_stream_mp3_activate_highpass_width->activate(); + + if (cfg.mp3_codec_stream.lowpass_freq_active == 1) { + fl_g->input_stream_mp3_lowpass_freq->activate(); + } + if (cfg.mp3_codec_stream.lowpass_width_active == 1) { + fl_g->input_stream_mp3_lowpass_width->activate(); + } + if (cfg.mp3_codec_stream.highpass_freq_active == 1) { + fl_g->input_stream_mp3_highpass_freq->activate(); + } + if (cfg.mp3_codec_stream.highpass_width_active == 1) { + fl_g->input_stream_mp3_highpass_width->activate(); + } + + fl_g->choice_stream_vorbis_vbr_quality->activate(); + fl_g->choice_stream_vorbis_bitrate_mode->activate(); + fl_g->choice_stream_vorbis_vbr_min_bitrate->activate(); + fl_g->choice_stream_vorbis_vbr_max_bitrate->activate(); + + fl_g->choice_stream_opus_quality->activate(); + fl_g->choice_stream_opus_audio_type->activate(); + fl_g->choice_stream_opus_bandwidth->activate(); + fl_g->choice_stream_opus_bitrate_mode->activate(); + + fl_g->choice_stream_aac_profile->activate(); + fl_g->choice_stream_aac_afterburner->activate(); + fl_g->choice_stream_aac_bitrate_mode->activate(); + + fl_g->radio_stream_flac_bit_depth_16->activate(); + fl_g->radio_stream_flac_bit_depth_24->activate(); +} + +void deactivate_stream_ui_elements(void) +{ + fl_g->choice_cfg_bitrate->deactivate(); + fl_g->choice_cfg_samplerate->deactivate(); + fl_g->choice_cfg_channel->deactivate(); + fl_g->choice_cfg_samplerate->deactivate(); + + fl_g->choice_cfg_dev->deactivate(); + fl_g->choice_cfg_dev2->deactivate(); + fl_g->button_cfg_rescan_devices->deactivate(); + fl_g->choice_cfg_codec->deactivate(); + + fl_g->choice_stream_mp3_enc_quality->deactivate(); + fl_g->choice_stream_mp3_stereo_mode->deactivate(); + fl_g->choice_stream_mp3_vbr_quality->deactivate(); + fl_g->choice_stream_mp3_bitrate_mode->deactivate(); + fl_g->choice_stream_mp3_vbr_min_bitrate->deactivate(); + fl_g->choice_stream_mp3_vbr_max_bitrate->deactivate(); + fl_g->check_stream_mp3_force_min_bitrate->deactivate(); + fl_g->choice_stream_mp3_resampling_freq->deactivate(); + fl_g->check_stream_mp3_activate_lowpass_freq->deactivate(); + fl_g->check_stream_mp3_activate_lowpass_width->deactivate(); + fl_g->check_stream_mp3_activate_highpass_freq->deactivate(); + fl_g->check_stream_mp3_activate_highpass_width->deactivate(); + fl_g->input_stream_mp3_lowpass_freq->deactivate(); + fl_g->input_stream_mp3_lowpass_width->deactivate(); + fl_g->input_stream_mp3_highpass_freq->deactivate(); + fl_g->input_stream_mp3_highpass_width->deactivate(); + + fl_g->choice_stream_vorbis_vbr_quality->deactivate(); + fl_g->choice_stream_vorbis_bitrate_mode->deactivate(); + fl_g->choice_stream_vorbis_vbr_min_bitrate->deactivate(); + fl_g->choice_stream_vorbis_vbr_max_bitrate->deactivate(); + + fl_g->choice_stream_opus_quality->deactivate(); + fl_g->choice_stream_opus_audio_type->deactivate(); + fl_g->choice_stream_opus_bandwidth->deactivate(); + fl_g->choice_stream_opus_bitrate_mode->deactivate(); + + fl_g->choice_stream_aac_profile->deactivate(); + fl_g->choice_stream_aac_afterburner->deactivate(); + fl_g->choice_stream_aac_bitrate_mode->deactivate(); + + fl_g->radio_stream_flac_bit_depth_16->deactivate(); + fl_g->radio_stream_flac_bit_depth_24->deactivate(); + + fl_g->button_cfg_import->deactivate(); +} + +void activate_rec_ui_elements(void) +{ + if (!connected) { + fl_g->choice_cfg_channel->activate(); + fl_g->choice_cfg_dev->activate(); + fl_g->choice_cfg_dev2->activate(); + fl_g->choice_cfg_samplerate->activate(); + fl_g->button_cfg_rescan_devices->activate(); + fl_g->button_cfg_import->activate(); + } + + fl_g->choice_rec_codec->activate(); + fl_g->choice_rec_bitrate->activate(); + + fl_g->choice_rec_mp3_enc_quality->activate(); + fl_g->choice_rec_mp3_stereo_mode->activate(); + fl_g->choice_rec_mp3_vbr_quality->activate(); + fl_g->choice_rec_mp3_bitrate_mode->activate(); + fl_g->choice_rec_mp3_vbr_min_bitrate->activate(); + fl_g->choice_rec_mp3_vbr_max_bitrate->activate(); + fl_g->check_rec_mp3_force_min_bitrate->activate(); + fl_g->choice_rec_mp3_resampling_freq->activate(); + fl_g->check_rec_mp3_activate_lowpass_freq->activate(); + fl_g->check_rec_mp3_activate_lowpass_width->activate(); + fl_g->check_rec_mp3_activate_highpass_freq->activate(); + fl_g->check_rec_mp3_activate_highpass_width->activate(); + + if (cfg.mp3_codec_rec.lowpass_freq_active == 1) { + fl_g->input_rec_mp3_lowpass_freq->activate(); + } + if (cfg.mp3_codec_rec.lowpass_width_active == 1) { + fl_g->input_rec_mp3_lowpass_width->activate(); + } + if (cfg.mp3_codec_rec.highpass_freq_active == 1) { + fl_g->input_rec_mp3_highpass_freq->activate(); + } + if (cfg.mp3_codec_rec.highpass_width_active == 1) { + fl_g->input_rec_mp3_highpass_width->activate(); + } + + fl_g->choice_rec_vorbis_vbr_quality->activate(); + fl_g->choice_rec_vorbis_bitrate_mode->activate(); + fl_g->choice_rec_vorbis_vbr_min_bitrate->activate(); + fl_g->choice_rec_vorbis_vbr_max_bitrate->activate(); + + fl_g->choice_rec_opus_quality->activate(); + fl_g->choice_rec_opus_audio_type->activate(); + fl_g->choice_rec_opus_bandwidth->activate(); + fl_g->choice_rec_opus_bitrate_mode->activate(); + + fl_g->choice_rec_aac_profile->activate(); + fl_g->choice_rec_aac_afterburner->activate(); + fl_g->choice_rec_aac_bitrate_mode->activate(); + + fl_g->radio_rec_flac_bit_depth_16->activate(); + fl_g->radio_rec_flac_bit_depth_24->activate(); + + fl_g->radio_rec_wav_bit_depth_16->activate(); + fl_g->radio_rec_wav_bit_depth_24->activate(); + fl_g->radio_rec_wav_bit_depth_32->activate(); +} + +void deactivate_rec_ui_elements(void) +{ + fl_g->choice_rec_codec->deactivate(); + fl_g->choice_rec_bitrate->deactivate(); + fl_g->choice_cfg_channel->deactivate(); + fl_g->choice_cfg_dev->deactivate(); + fl_g->choice_cfg_dev2->deactivate(); + fl_g->choice_cfg_samplerate->deactivate(); + fl_g->button_cfg_rescan_devices->deactivate(); + + fl_g->choice_rec_mp3_enc_quality->deactivate(); + fl_g->choice_rec_mp3_stereo_mode->deactivate(); + fl_g->choice_rec_mp3_vbr_quality->deactivate(); + fl_g->choice_rec_mp3_bitrate_mode->deactivate(); + fl_g->choice_rec_mp3_vbr_min_bitrate->deactivate(); + fl_g->choice_rec_mp3_vbr_max_bitrate->deactivate(); + fl_g->check_rec_mp3_force_min_bitrate->deactivate(); + fl_g->choice_rec_mp3_resampling_freq->deactivate(); + fl_g->check_rec_mp3_activate_lowpass_freq->deactivate(); + fl_g->check_rec_mp3_activate_lowpass_width->deactivate(); + fl_g->check_rec_mp3_activate_highpass_freq->deactivate(); + fl_g->check_rec_mp3_activate_highpass_width->deactivate(); + fl_g->input_rec_mp3_lowpass_freq->deactivate(); + fl_g->input_rec_mp3_lowpass_width->deactivate(); + fl_g->input_rec_mp3_highpass_freq->deactivate(); + fl_g->input_rec_mp3_highpass_width->deactivate(); + + fl_g->choice_rec_vorbis_vbr_quality->deactivate(); + fl_g->choice_rec_vorbis_bitrate_mode->deactivate(); + fl_g->choice_rec_vorbis_vbr_min_bitrate->deactivate(); + fl_g->choice_rec_vorbis_vbr_max_bitrate->deactivate(); + + fl_g->choice_rec_opus_quality->deactivate(); + fl_g->choice_rec_opus_audio_type->deactivate(); + fl_g->choice_rec_opus_bandwidth->deactivate(); + fl_g->choice_rec_opus_bitrate_mode->deactivate(); + + fl_g->choice_rec_aac_profile->deactivate(); + fl_g->choice_rec_aac_afterburner->deactivate(); + fl_g->choice_rec_aac_bitrate_mode->deactivate(); + + fl_g->radio_rec_flac_bit_depth_16->deactivate(); + fl_g->radio_rec_flac_bit_depth_24->deactivate(); + + fl_g->radio_rec_wav_bit_depth_16->deactivate(); + fl_g->radio_rec_wav_bit_depth_24->deactivate(); + fl_g->radio_rec_wav_bit_depth_32->deactivate(); + + fl_g->button_cfg_import->deactivate(); +} + +void lang_id_to_str(int lang_id, char **lang_str, int mapping_type) +{ + if (lang_id >= LANG_COUNT) { + lang_id = 0; + } + + if (mapping_type == LANG_MAPPING_NEW) { + *lang_str = (char *)realloc(*lang_str, strlen(lang_array_new[lang_id]) + 1); + snprintf(*lang_str, strlen(lang_array_new[lang_id]) + 1, "%s", lang_array_new[lang_id]); + } + else { // for compatibility with butt configurations <= 0.1.33 + *lang_str = (char *)realloc(*lang_str, strlen(lang_array_old[lang_id]) + 1); + snprintf(*lang_str, strlen(lang_array_old[lang_id]) + 1, "%s", lang_array_old[lang_id]); + } +} + +int lang_str_to_id(char *lang_str) +{ + int lang_id = 0; + + for (int i = 0; i < LANG_COUNT; i++) { + if (strcmp(lang_str, lang_array_new[i]) == 0) { + lang_id = i; + } + } + + return lang_id; +} + +// The following function *_on_main_thread can be called with Fl::awake() from any worker thread +void disconnect_on_main_thread(void *userdata) +{ + bool ask = *(bool *)userdata; + button_disconnect_cb(ask); +} + +void connect_on_main_thread(void *userdata) +{ + button_connect_cb(); +} + +void start_record_on_main_thread(void *userdata) +{ + bool ask = *(bool *)userdata; + button_record_cb(ask); +} + +void stop_record_on_main_thread(void *userdata) +{ + bool ask = *(bool *)userdata; + stop_recording(ask); +} + +void do_callback_on_main_thread(void *userdata) +{ + Fl_Widget *w = (Fl_Widget *)userdata; + w->do_callback(w, (void *)CB_CALLED_BY_MIDI); +} + +void update_slider_from_midi(Fl_Slider *slider, int command_id, int value) +{ + int mode = cfg.midi.commands[command_id].mode; + int soft_takeover = cfg.midi.commands[command_id].soft_takeover; + int &picked_up = cfg.midi.commands[command_id].picked_up; + + double min_internal_val = slider->minimum(); + double max_internal_val = slider->maximum(); + if (min_internal_val > max_internal_val) { + min_internal_val = slider->maximum(); + max_internal_val = slider->minimum(); + } + int new_midi_val = value; + double current_internal_val = slider->value(); + int current_midi_val = (int)(round((current_internal_val - min_internal_val) / (max_internal_val - min_internal_val) * 127)); + double new_internal_val; + int8_t midi_step; + + // Do not change the value if the new value is too far away from the current value to prevent jumping around + if (soft_takeover == 1 && picked_up == 0 && mode == MIDI_MODE_ABSOLUTE && abs(new_midi_val - current_midi_val) > 5) { + return; + } + + if (mode == MIDI_MODE_ABSOLUTE) { + picked_up = 1; + new_internal_val = min_internal_val + new_midi_val * (max_internal_val - min_internal_val) / 127; + slider->value(new_internal_val); + } + else { // mode == MIDI_MODE_RELATIVE + if (mode == MIDI_MODE_RELATIVE_TWOS_COMPLEMENT) { + midi_step = (int8_t)(new_midi_val < 64 ? new_midi_val : new_midi_val | 0x80); // Sign extent + } + else if (mode == MIDI_MODE_RELATIVE_BINARY_OFFSET) { + midi_step = (int8_t)(new_midi_val - 64); + } + else if (mode == MIDI_MODE_RELATIVE_SIGN_MAGNITUDE) { + int sign = (new_midi_val & 0x40) == 0 ? 1 : -1; + midi_step = (int8_t)(sign * (new_midi_val & 0x3F)); + } + else { + print_info("Error: Invalid CC mode selected", 1); + return; + } + + double internal_step = midi_step * (max_internal_val - min_internal_val) / 63; + new_internal_val = current_internal_val + internal_step; + // Clamp to lower/upper limits of the slider + new_internal_val = fmax(fmin(new_internal_val, max_internal_val), min_internal_val); + slider->value(new_internal_val); + + printf("midi_step: %d\n", midi_step); + printf("internal_step: %0.1f\n", internal_step); + printf("new_internal_val: %0.1f\n", new_internal_val); + } + Fl::awake(do_callback_on_main_thread, slider); +} + +int exec_midi_command(int command_id, int msg_type, int value) +{ + /* + printf("command_type: %d\n", command_type); + printf("command_id: %d\n", command_id); + printf("value: %d\n", value); + */ + static bool ask = false; + + Fl::lock(); + switch (command_id) { + case MIDI_CMD_START_STOP_BROADCASTING: + if (msg_type == MIDI_MSG_TYPE_CC) { + if (value >= 64) { + if (connected == false) { + Fl::awake(connect_on_main_thread, NULL); + } + } + else { + if (connected == true) { + Fl::awake(disconnect_on_main_thread, &ask); + } + else { + try_to_connect = 0; + } + } + } + else if (msg_type == MIDI_MSG_TYPE_NOTE_ON) { + if (connected == false) { + Fl::awake(connect_on_main_thread, NULL); + } + else { + Fl::awake(disconnect_on_main_thread, &ask); + } + } + break; + case MIDI_CMD_START_BROADCASTING: + if (connected == false) { + Fl::awake(connect_on_main_thread, NULL); + } + break; + case MIDI_CMD_STOP_BROADCASTING: + Fl::awake(disconnect_on_main_thread, &ask); + break; + case MIDI_CMD_START_STOP_RECORDING: + if (msg_type == MIDI_MSG_TYPE_CC) { + if (value >= 64) { + if (recording == false) { + Fl::awake(start_record_on_main_thread, &ask); + } + } + else { + Fl::awake(stop_record_on_main_thread, &ask); + } + } + else if (msg_type == MIDI_MSG_TYPE_NOTE_ON) { + if (recording == false) { + Fl::awake(start_record_on_main_thread, &ask); + } + else { + Fl::awake(stop_record_on_main_thread, &ask); + } + } + break; + case MIDI_CMD_START_RECORDING: + if (recording == false) { + Fl::awake(start_record_on_main_thread, &ask); + } + break; + case MIDI_CMD_STOP_RECORDING: + if (recording == true) { + Fl::awake(stop_record_on_main_thread, &ask); + } + break; + case MIDI_CMD_MASTER_GAIN: + if (msg_type == MIDI_MSG_TYPE_CC) { + update_slider_from_midi(fl_g->slider_gain, command_id, value); + } + break; + case MIDI_CMD_STREAMING_GAIN: + if (msg_type == MIDI_MSG_TYPE_CC) { + update_slider_from_midi(fl_g->slider_mixer_streaming_gain, command_id, value); + } + break; + case MIDI_CMD_RECORDING_GAIN: + if (msg_type == MIDI_MSG_TYPE_CC) { + update_slider_from_midi(fl_g->slider_mixer_recording_gain, command_id, value); + } + break; + case MIDI_CMD_PRIMARY_DEV_VOL: + if (msg_type == MIDI_MSG_TYPE_CC) { + update_slider_from_midi(fl_g->slider_mixer_primary_device, command_id, value); + } + break; + case MIDI_CMD_SECONDARY_DEV_VOL: + if (msg_type == MIDI_MSG_TYPE_CC) { + update_slider_from_midi(fl_g->slider_mixer_secondary_device, command_id, value); + } + break; + case MIDI_CMD_CROSS_FADER: + if (msg_type == MIDI_MSG_TYPE_CC) { + update_slider_from_midi(fl_g->slider_mixer_cross_fader, command_id, value); + } + break; + case MIDI_CMD_PRIMARY_DEV_MUTE_UNMUTE: + fl_g->button_mixer_mute_primary_device->value(!fl_g->button_mixer_mute_primary_device->value()); + Fl::awake(do_callback_on_main_thread, fl_g->button_mixer_mute_primary_device); + break; + case MIDI_CMD_SECONDARY_DEV_MUTE_UNMUTE: + fl_g->button_mixer_mute_secondary_device->value(!fl_g->button_mixer_mute_secondary_device->value()); + Fl::awake(do_callback_on_main_thread, fl_g->button_mixer_mute_secondary_device); + break; + } + + Fl::unlock(); + return 0; +} + +int get_midi_ctrl_type(int midi_cmd) +{ + if (midi_cmd == MIDI_CMD_START_STOP_BROADCASTING || // + midi_cmd == MIDI_CMD_START_STOP_RECORDING || // + midi_cmd == MIDI_CMD_PRIMARY_DEV_MUTE_UNMUTE || // + midi_cmd == MIDI_CMD_SECONDARY_DEV_MUTE_UNMUTE // + ) { + return MIDI_CTRL_TYPE_BUTTON; + } + else { + return MIDI_CTRL_TYPE_KNOB; + } +} diff --git a/src/FLTK/fl_funcs.h b/src/FLTK/fl_funcs.h new file mode 100644 index 0000000..c6ce138 --- /dev/null +++ b/src/FLTK/fl_funcs.h @@ -0,0 +1,60 @@ +// FLTK GUI related functions +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef FL_FUNCS_H +#define FL_FUNCS_H + +#include + +#define GUI_LOOP() Fl::run(); +#define CHECK_EVENTS() Fl::check() + +void fill_cfg_widgets(void); +void update_samplerates_list(void); +void update_codec_samplerates(void); +void update_channel_lists(void); +void print_info(const char *info, int info_type); +void write_log(const char *message, const char *path = NULL); +void print_lcd(const char *text, int len, int home, int clear); +void test_file_extension(void); +int expand_string(char **str); +void init_main_gui_and_audio(void); +void ask_user_set_msg(char *m); +void ask_user_set_hash(char *h); +void ask_user_reset(void); +void ask_user_ask(void); +int ask_user_get_answer(void); +int ask_user_get_has_clicked(void); +void activate_stream_ui_elements(void); +void deactivate_stream_ui_elements(void); +void activate_rec_ui_elements(void); +void deactivate_rec_ui_elements(void); +void lang_id_to_str(int lang_id, char **lang_str, int mapping_type); +int lang_str_to_id(char *lang_str); +int eval_record_path(int use_previous_index); +void read_eq_slider_values(void); +int get_bitrate_list_for_codec(int codec, int **bitrates); +void update_stream_bitrate_list(int codec); +void update_rec_bitrate_list(int codec); +int get_bitrate_index(int codec, int bitrate); +int get_codec_index(char *codec); +int get_midi_ctrl_type(int midi_command); + +typedef const char *(*currentTrackFunction)(int); +extern currentTrackFunction getCurrentTrackFunctionFromId(int i); +int exec_midi_command(int command_id, int msg_type, int value); +void populate_midi_dev_list(void); + +#endif diff --git a/src/FLTK/fl_timer_funcs.cpp b/src/FLTK/fl_timer_funcs.cpp new file mode 100644 index 0000000..484a9c9 --- /dev/null +++ b/src/FLTK/fl_timer_funcs.cpp @@ -0,0 +1,1173 @@ +// FLTK GUI related functions +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef WIN32 +#include +#endif + +#ifdef WIN32 +#include "tray_agent.h" +#endif + +#include "gettext.h" +#include "config.h" + +#include "atom.h" +#include "cfg.h" +#include "butt.h" +#include "util.h" +#include "port_audio.h" +#include "timer.h" +#include "flgui.h" +#include "fl_funcs.h" +#include "shoutcast.h" +#include "icecast.h" +#include "webrtc.h" +#include "strfuncs.h" +#include "fl_timer_funcs.h" +#include "logos.h" +#include "Fl_LED.h" +#include "command.h" +#include "url.h" +#ifdef WITH_RADIOCO +#include "radioco.h" +#endif + +#if __APPLE__ && __MACH__ +#include "CurrentTrackOSX.h" +#endif + +const char *(*current_track_app)(int); + +void split_recording_file(void); + +pthread_t split_recording_file_thread_detached; +pthread_t request_listener_count_thread_detached; +pthread_t url_song_update_thread_detached; + +ATOM_NEW_INT(url_song_update_thread_running, 0); +ATOM_NEW_INT(request_listener_count_thread_running, 0); +ATOM_NEW_INT(g_listener_count, -1); +ATOM_NEW_INT(failed_get_listener_tries, 0); + +int g_vu_meter_timer_is_active = 0; +int g_stop_vu_meter_timer = 0; + +void set_threshold_input_from_command(command_t *command, Fl_Value_Input *input, Fl_Check_Button *checkbox) +{ + if (command->param != NULL) { + float val = *(float *)command->param; + if (val <= 0) { + checkbox->value(0); + checkbox->do_callback(); + } + else { + checkbox->value(1); + checkbox->do_callback(); + input->value(val); + input->do_callback(); + } + free(command->param); + } +} + +void cmd_timer(void *) +{ + command_t command; + if (command_get_cmd_from_fifo(&command) < (int)sizeof(command_t)) { + Fl::repeat_timeout(0.25, &cmd_timer); + return; + } + + switch (command.cmd) { + case CMD_CONNECT: + if (!connected) { + if (command.param_size > 0) { + char *srv_name = (char *)command.param; + int idx; + if ((idx = fl_g->choice_cfg_act_srv->find_index(srv_name)) != -1) { + fl_g->choice_cfg_act_srv->value(idx); + fl_g->choice_cfg_act_srv->do_callback(); + Fl::add_timeout(0.25, &cmd_timer); + button_connect_cb(); + } + else { + Fl::repeat_timeout(0.25, &cmd_timer); + } + + if (command.param != NULL) { + free(command.param); + } + } + else { + Fl::add_timeout(0.25, &cmd_timer); + button_connect_cb(); + } + } + else { + Fl::repeat_timeout(0.25, &cmd_timer); + } + break; + case CMD_DISCONNECT: + if (connected == true) { + button_disconnect_cb(false); + } + else { + try_to_connect = 0; + } + Fl::repeat_timeout(0.25, &cmd_timer); + break; + case CMD_START_RECORDING: + if (!recording) { + button_record_cb(false); + } + Fl::repeat_timeout(0.25, &cmd_timer); + break; + case CMD_STOP_RECORDING: + stop_recording(false); + Fl::repeat_timeout(0.25, &cmd_timer); + break; + case CMD_SPLIT_RECORDING: + split_recording_file(); + Fl::repeat_timeout(0.25, &cmd_timer); + break; + case CMD_QUIT: + window_main_close_cb(false); + break; + case CMD_UPDATE_SONGNAME: + /* cfg.main.song = (char*)realloc(cfg.main.song, command.param_size+1); + strcpy(cfg.main.song, (char*)command.param); + Fl::add_timeout(cfg.main.song_delay, &update_song);*/ + fl_g->input_cfg_song->value((const char *)command.param); + fl_g->button_cfg_song_go->do_callback(); + Fl::repeat_timeout(0.25, &cmd_timer); + if (command.param != NULL) { + free(command.param); + } + break; + case CMD_SET_STREAM_SIGNAL_THRESHOLD: + set_threshold_input_from_command(&command, fl_g->input_cfg_signal, fl_g->check_stream_signal); + Fl::repeat_timeout(0.25, &cmd_timer); + break; + case CMD_SET_STREAM_SILENCE_THRESHOLD: + set_threshold_input_from_command(&command, fl_g->input_cfg_silence, fl_g->check_stream_silence); + Fl::repeat_timeout(0.25, &cmd_timer); + break; + case CMD_SET_RECORD_SIGNAL_THRESHOLD: + set_threshold_input_from_command(&command, fl_g->input_rec_signal, fl_g->check_rec_signal); + Fl::repeat_timeout(0.25, &cmd_timer); + break; + case CMD_SET_RECORD_SILENCE_THRESHOLD: + set_threshold_input_from_command(&command, fl_g->input_rec_silence, fl_g->check_rec_silence); + Fl::repeat_timeout(0.25, &cmd_timer); + break; + case CMD_GET_STATUS: + status_packet_t status_packet; + status_packet.version = STATUS_PACKET_VERSION; + + status_packet.status = (1 << STATUS_EXTENDED_PACKET) | (connected << STATUS_CONNECTED) | (try_to_connect << STATUS_CONNECTING) | + (recording << STATUS_RECORDING) | (signal_detected << STATUS_SIGNAL_DETECTED) | (silence_detected << STATUS_SILENCE_DETECTED); + + status_packet.volume_left = round(10 * fl_g->vumeter->left_dB); + status_packet.volume_right = round(10 * fl_g->vumeter->right_dB); + + if (connected == 1) { + status_packet.stream_seconds = (uint32_t)timer_get_elapsed_time(&stream_timer); + status_packet.stream_kByte = kbytes_sent; + status_packet.listener_count = atom_get_int(&g_listener_count); + } + else { + status_packet.stream_seconds = 0; + status_packet.stream_kByte = 0; + status_packet.listener_count = -1; + } + + if (recording == 1) { + status_packet.record_seconds = (uint32_t)timer_get_elapsed_time(&rec_timer); + status_packet.record_kByte = kbytes_written; + status_packet.rec_path = strdup(cfg.rec.path); +#ifdef WIN32 + // Replace '/' with '\\' + // Note: strrpl(&status_packet.rec_path,...) must not be used at this point because addresses of packed struct members may be unaligned + char *p; + while ((p = strchr(status_packet.rec_path, '/')) != NULL) { + *p = '\\'; + } +#endif + } + else { + status_packet.record_seconds = 0; + status_packet.record_kByte = 0; + status_packet.rec_path = strdup(""); + } + status_packet.rec_path_len = strlen(status_packet.rec_path) + 1; + + if (cfg.main.song != NULL) { + status_packet.song = strdup(cfg.main.song); + } + else { + status_packet.song = strdup(""); + } + status_packet.song_len = strlen(status_packet.song) + 1; + + command_send_status_reply(&status_packet); + + free(status_packet.song); + free(status_packet.rec_path); + + Fl::repeat_timeout(0.25, &cmd_timer); + break; + default: + Fl::repeat_timeout(0.25, &cmd_timer); + } +} + +void agent_watchdog_timer(void *) +{ +#ifdef WIN32 + int is_iconfied = fl_g->window_main->shown() && !fl_g->window_main->visible(); + + if (cfg.main.minimize_to_tray == 1 && is_iconfied == 1 && tray_agent_is_running(NULL) == 0) { + fl_g->window_main->show(); + } + else { + Fl::repeat_timeout(1, &agent_watchdog_timer); + } +#endif +} + +void has_agent_been_started_timer(void *) +{ +#ifdef WIN32 + if (tray_agent_is_running(NULL) != 1) { + fl_alert("Agent could not be started."); + } +#endif +} + +void has_agent_been_stopped_timer(void *) +{ +#ifdef WIN32 + if (tray_agent_is_running(NULL) != 0) { + fl_alert("Agent could not be stopped."); + } +#endif +} + +void vu_meter_timer(void *) +{ + static int cleared = 0; + static int no_new_frames_cnt = 0; + + if (pa_new_frames) { + snd_update_vu(0); + no_new_frames_cnt = 0; + cleared = 0; + } + else if (no_new_frames_cnt < 10) { + no_new_frames_cnt++; + } + else if (cleared == 0) { + snd_update_vu(1); + cleared = 1; + } + + if (g_stop_vu_meter_timer == 1) { + g_vu_meter_timer_is_active = 0; + } + else { + Fl::repeat_timeout(0.05, &vu_meter_timer); + } +} + +void display_info_timer(void *reset) +{ + char lcd_text_buf[33]; + + if (try_to_connect == 1) { + Fl::repeat_timeout(0.2, &display_info_timer); + return; + } + + if (reset != NULL && *(int *)reset == 1) { + atom_set_int(&g_listener_count, -1); + } + + if (display_info == SENT_DATA) { + snprintf(lcd_text_buf, sizeof(lcd_text_buf), _("stream sent\n%0.2lfMB"), kbytes_sent / 1024); + print_lcd(lcd_text_buf, strlen(lcd_text_buf), 0, 1); + } + + if (display_info == STREAM_TIME && timer_is_elapsed(&stream_timer)) { + snprintf(lcd_text_buf, sizeof(lcd_text_buf), _("stream time\n%s"), timer_get_time_str(&stream_timer)); + print_lcd(lcd_text_buf, strlen(lcd_text_buf), 0, 1); + } + + if (display_info == STREAM_STATE && connected == true) { + if (cfg.gui.show_listeners == true && atom_get_int(&g_listener_count) > -1) { + if (atom_get_int(&g_listener_count) <= 99999) { + snprintf(lcd_text_buf, sizeof(lcd_text_buf), _("On Air\nListeners %5d"), atom_get_int(&g_listener_count)); + } + else { + snprintf(lcd_text_buf, sizeof(lcd_text_buf), _("On Air\nListeners>%5d"), atom_get_int(&g_listener_count)); + } + } + else { + snprintf(lcd_text_buf, sizeof(lcd_text_buf), _("On Air")); + } + print_lcd(lcd_text_buf, strlen(lcd_text_buf), 0, 1); + } + + if (display_info == REC_TIME && timer_is_elapsed(&rec_timer)) { + snprintf(lcd_text_buf, sizeof(lcd_text_buf), _("record time\n%s"), timer_get_time_str(&rec_timer)); + print_lcd(lcd_text_buf, strlen(lcd_text_buf), 0, 1); + } + + if (display_info == REC_DATA) { + snprintf(lcd_text_buf, sizeof(lcd_text_buf), _("record size\n%0.2lfMB"), kbytes_written / 1024); + print_lcd(lcd_text_buf, strlen(lcd_text_buf), 0, 1); + } + + if (cfg.gui.show_listeners == true) { + if (display_info == STREAM_STATE) { + fl_g->label_current_listeners->hide(); + } + else if (connected && cfg.srv[cfg.selected_srv]->type != WEBRTC && atom_get_int(&g_listener_count) > -1) { + fl_g->label_current_listeners->show(); + } + } + + Fl::repeat_timeout(0.2, &display_info_timer); +} + +void rotate_sponsor_logo_timer(void *) +{ + static int current_logo = rand() % 2; + static Fl_Image *sponsor_logo = NULL; + + if (sponsor_logo != NULL) { + delete sponsor_logo; + } + + if (current_logo == 0) { + sponsor_logo = new Fl_RGB_Image(radio_co_logo, 124, 61, 4, 0); + fl_g->sponsor_logo->callback([](Fl_Widget *w, void *u) { + fl_open_uri("https://radio.co/?utm_source=butt&utm_medium=app"); + }); + current_logo = 1; + } + else if (current_logo == 1) { + sponsor_logo = new Fl_RGB_Image(live365_logo, 124, 61, 4, 0); + fl_g->sponsor_logo->callback([](Fl_Widget *w, void *u) { + fl_open_uri("https://live365.com/broadcaster/radio-broadcasting?utm_source=butt&utm_medium=click&utm_campaign=onestopshop"); + }); + current_logo = 0; + } + + fl_g->sponsor_logo->image(sponsor_logo); + fl_g->sponsor_logo->redraw(); + + Fl::repeat_timeout(10, &rotate_sponsor_logo_timer); +} + +void display_rotate_timer(void *) +{ + if (!connected && !recording) { + goto exit; + } + + if (!cfg.gui.lcd_auto) { + goto exit; + } + + switch (display_info) { + case STREAM_STATE: + case STREAM_TIME: + display_info = SENT_DATA; + break; + case SENT_DATA: + if (recording) { + display_info = REC_TIME; + } + else { + display_info = STREAM_TIME; + } + break; + case REC_TIME: + display_info = REC_DATA; + break; + case REC_DATA: + if (connected) { + display_info = STREAM_TIME; + } + else { + display_info = REC_TIME; + } + break; + default: + break; + } + +exit: + Fl::repeat_timeout(5, &display_rotate_timer); +} + +void reconnect_timer(void *) +{ + if (disconnect == 1) { + return; + } + button_connect_cb(); +} + +void is_connected_timer(void *) +{ + if (!connected) { + if (cfg.srv[cfg.selected_srv]->type == ICECAST) { + ic_disconnect(); + } +#ifdef HAVE_LIBDATACHANNEL + else if (cfg.srv[cfg.selected_srv]->type == WEBRTC) { + webrtc_disconnect(); + } +#endif + else { + sc_disconnect(); + } + +#ifdef WIN32 + tray_agent_send_cmd(TA_CONNECT_STATE); +#endif + + Fl::remove_timeout(&display_info_timer); + Fl::remove_timeout(&is_connected_timer); + fl_g->button_connect->color(FL_BACKGROUND_COLOR); + fl_g->button_connect->redraw(); + + if (disconnect == 1) { + return; + } + + // Initiate delayed reconnect + if (cfg.main.reconnect_delay > 1) { + char text_buf[256]; + fl_g->lcd->clear(); + fl_g->lcd->print((const uchar *)_("idle"), strlen(_("idle"))); + fl_g->sponsor_logo->show(); + fl_g->sponsor_logo->redraw(); + snprintf(text_buf, sizeof(text_buf), _("ERROR: Connection lost\nreconnecting in %d seconds..."), cfg.main.reconnect_delay); + print_info(text_buf, 0); + } + else { + print_info(_("ERROR: Connection lost\nreconnecting..."), 1); + } + Fl::add_timeout(cfg.main.reconnect_delay, &reconnect_timer); + + return; + } + + Fl::repeat_timeout(0.5, &is_connected_timer); +} + +void cfg_win_pos_timer(void *) +{ +#ifdef WIN32 + fl_g->window_cfg->position(fl_g->window_main->x() + fl_g->window_main->w() + 0, fl_g->window_main->y()); +#else // UNIX + fl_g->window_cfg->position(fl_g->window_main->x() + fl_g->window_main->w(), fl_g->window_main->y()); +#endif + + Fl::repeat_timeout(0.1, &cfg_win_pos_timer); +} + +void *split_recording_file_thread_func(void *init) +{ + int synced_to_full_hour; + time_t start_time; + + time_t current_time; + struct tm *current_time_tm; + + int split_time_seconds = 60 * cfg.rec.split_time; + + struct timespec wait_400ms; + wait_400ms.tv_sec = 0; + wait_400ms.tv_nsec = (400 * 1000 * 1000); + + start_time = time(NULL); + synced_to_full_hour = 0; + + set_max_thread_priority(); + + while (recording) { + current_time = time(NULL); + current_time_tm = localtime(¤t_time); + + if ((cfg.rec.sync_to_hour == 1) && (synced_to_full_hour == 0) && (current_time_tm->tm_min == 0) && (current_time_tm->tm_sec >= 0)) { + start_time = current_time - current_time_tm->tm_sec; + synced_to_full_hour = 1; + split_recording_file(); + } + else if (current_time - start_time >= split_time_seconds) { + start_time = current_time; + split_recording_file(); + } + + nanosleep(&wait_400ms, NULL); + } + + // Detach thread (free ressources) because no one will call pthread_join() on it + pthread_detach(pthread_self()); + + return NULL; +} + +void *request_listener_count_thread_func(void *reset) +{ + int listeners; + static int got_listener_count = 0; + + atom_set_int(&request_listener_count_thread_running, 1); + + if (reset != NULL && *(int *)reset == 1) { + got_listener_count = 0; + } + + if (cfg.srv[cfg.selected_srv]->custom_listener_url != NULL && strlen(cfg.srv[cfg.selected_srv]->custom_listener_url) > 0) { + if (strstr(cfg.srv[cfg.selected_srv]->custom_listener_url, "/status-json.xsl") != NULL || + strstr(cfg.srv[cfg.selected_srv]->custom_listener_url, "/7.xsl") != NULL) { + char *mount; + if (cfg.srv[cfg.selected_srv]->custom_listener_mount != NULL && strlen(cfg.srv[cfg.selected_srv]->custom_listener_mount) > 0) { + mount = cfg.srv[cfg.selected_srv]->custom_listener_mount; + } + else { + if (cfg.srv[cfg.selected_srv]->type == ICECAST) { + mount = cfg.srv[cfg.selected_srv]->mount; + } + else { + mount = NULL; + } + } + listeners = ic_get_listener_count_from_url(cfg.srv[cfg.selected_srv]->custom_listener_url, mount); + } + else if (strstr(cfg.srv[cfg.selected_srv]->custom_listener_url, "/stats?sid") != NULL || + strstr(cfg.srv[cfg.selected_srv]->custom_listener_url, "/7.html") != NULL) { + listeners = sc_get_listener_count_from_url(cfg.srv[cfg.selected_srv]->custom_listener_url); + } + else { + listeners = -1; + } + } + else if (cfg.srv[cfg.selected_srv]->type == ICECAST) { + listeners = ic_get_listener_count(); + } + else if (cfg.srv[cfg.selected_srv]->type == SHOUTCAST) { + listeners = sc_get_listener_count(); + } +#ifdef HAVE_LIBDATACHANNEL + else if (cfg.srv[cfg.selected_srv]->type == WEBRTC) { + listeners = webrtc_get_listener_count(); + } +#endif + else { // if (cfg.srv[cfg.selected_srv]->type == RADIOCO) + listeners = -1; + } + + // Increase failed_tries only if we never got a listener count for this session + if (listeners == -1 && got_listener_count == 0) { + int failed_tries = atom_get_int(&failed_get_listener_tries); + atom_set_int(&failed_get_listener_tries, ++failed_tries); + goto return_thread; + } + + Fl::lock(); + if (listeners >= 0) { + char listener_label[32]; + if (display_info != STREAM_STATE) { + snprintf(listener_label, sizeof(listener_label), "%s: %d", _("Listeners"), listeners); + fl_g->label_current_listeners->copy_label(listener_label); + fl_g->label_current_listeners->show(); + } + got_listener_count = 1; + atom_set_int(&g_listener_count, listeners); + } + else { + fl_g->label_current_listeners->hide(); + atom_set_int(&g_listener_count, -1); + } + Fl::unlock(); + +return_thread: + // Detach thread (free ressources) because no one will call pthread_join() on it + pthread_detach(pthread_self()); + + atom_set_int(&request_listener_count_thread_running, 0); + + return NULL; +} + +void request_listener_count_timer(void *reset) +{ + if (reset != NULL && *(int *)reset == 1) { + atom_set_int(&failed_get_listener_tries, 0); + atom_set_int(&g_listener_count, -1); + } + + if (connected == 0 || atom_get_int(&failed_get_listener_tries) > 3) { + fl_g->label_current_listeners->hide(); + return; + } + + if (atom_get_int(&request_listener_count_thread_running) == 0) { + if (pthread_create(&request_listener_count_thread_detached, NULL, request_listener_count_thread_func, reset) != 0) { + print_info("Fatal error: Could not launch request listeners thread. Please restart BUTT", 1); + return; + } + } + + Fl::repeat_timeout(cfg.gui.listeners_update_rate, &request_listener_count_timer); +} + +void split_recording_file_timer(void) +{ + if (pthread_create(&split_recording_file_thread_detached, NULL, split_recording_file_thread_func, NULL) != 0) { + print_info("Fatal error: Could not launch split recording thread. Please restart BUTT", 1); + return; + } +} + +void split_recording_file(void) +{ + char *p_ext; + char *insert_pos; + char ext[64]; + char file_num_str[12]; + char *original_path; + + if (!recording) { + return; + } + + p_ext = util_get_file_extension(cfg.rec.filename); + if (p_ext == NULL) { + print_info(_("Could not find a file extension in current filename\n" + "Automatic file splitting is deactivated"), + 0); + return; + } + + if (eval_record_path(1) != 0) { + return; + } + + if (fl_access(cfg.rec.path, F_OK) == 0) { // File exists + original_path = strdup(cfg.rec.path); + snprintf(ext, sizeof(ext), "%s", p_ext); + // increment the index until we find a filename that doesn't exist yet + for (uint32_t i = 1; /*inf*/; i++) { // index_loop + + snprintf(file_num_str, sizeof(file_num_str), "-%d", i); + + // find beginning of the file extension + insert_pos = strrstr(cfg.rec.path, ext) - 1; + + // Put index between end of file name end beginning of extension + strinsrt(&cfg.rec.path, file_num_str, insert_pos); + + if (fl_access(cfg.rec.path, F_OK) < 0) { // Found non-existing file name + free(original_path); + break; + } + + if (i == 0xFFFFFFFF) { // 2^32-1 + print_info(_("Could not find a valid filename for next file" + "\nbutt keeps recording to current file"), + 0); + free(original_path); + return; + } + + free(cfg.rec.path); + cfg.rec.path = strdup(original_path); + } + } + + if ((next_fd = fl_fopen(cfg.rec.path, "wb+")) == NULL) { + fl_alert(_("Could not open:\n%s"), cfg.rec.path); + return; + } + + print_info(_("Recording to:"), 0); + print_info(cfg.rec.path, 0); + + next_file = 1; +} + +void reset_stream_signal_detection_timer(void) +{ + if (cfg.main.signal_detection == 1 && cfg.main.signal_threshold > 0) { + Fl::remove_timeout(&stream_signal_timer); + Fl::add_timeout(1, &stream_signal_timer); + } +} + +void stream_signal_timer(void *) +{ + // printf("stream_signal_timer\n"); + static timer_ms_t signal_timer; + + if (signal_detected == true) { + if (signal_timer.is_running == false) { + timer_init(&signal_timer, cfg.main.signal_threshold); + timer_start(&signal_timer); + } + + if (timer_is_elapsed(&signal_timer)) { + button_connect_cb(); + timer_stop(&signal_timer); + return; + } + } + else { + timer_stop(&signal_timer); + } + + Fl::repeat_timeout(0.1, &stream_signal_timer); +} + +void reset_record_signal_detection_timer(void) +{ + if (cfg.rec.signal_detection == 1 && cfg.rec.signal_threshold > 0) { + Fl::remove_timeout(&record_signal_timer); + Fl::add_timeout(1, &record_signal_timer); + } +} + +void record_signal_timer(void *) +{ + // printf("record_signal_timer\n"); + + static timer_ms_t signal_timer; + if (signal_detected == true) { + if (signal_timer.is_running == false) { + timer_init(&signal_timer, cfg.rec.signal_threshold); + timer_start(&signal_timer); + } + + if (timer_is_elapsed(&signal_timer)) { + // print_info("Audio signal detected", 0); + button_record_cb(false); + timer_stop(&signal_timer); + return; + } + } + else { + timer_stop(&signal_timer); + } + + Fl::repeat_timeout(0.1, &record_signal_timer); +} + +void reset_stream_silence_detection_timer(void) +{ + if (cfg.main.silence_detection == 1 && cfg.main.silence_threshold > 0) { + Fl::remove_timeout(&stream_silence_timer); + Fl::add_timeout(1, &stream_silence_timer); + } +} + +void stream_silence_timer(void *) +{ + // printf("stream_silence_timer\n"); + + static timer_ms_t silence_timer; + if (silence_detected == true) { + if (silence_timer.is_running == false) { + timer_init(&silence_timer, cfg.main.silence_threshold); + timer_start(&silence_timer); + } + + if (timer_is_elapsed(&silence_timer)) { + // print_info("Streaming silence threshold has been reached", 0); + if (connected == 1 || try_to_connect == 1) { + button_disconnect_cb(false); + } + timer_stop(&silence_timer); + return; + } + } + else { + timer_stop(&silence_timer); + } + + Fl::repeat_timeout(0.1, &stream_silence_timer); +} + +void reset_record_silence_detection_timer(void) +{ + if (cfg.rec.silence_detection == 1 && cfg.rec.silence_threshold > 0) { + Fl::remove_timeout(&record_silence_timer); + Fl::add_timeout(1, &record_silence_timer); + } +} + +void record_silence_timer(void *) +{ + // printf("record_silence_timer\n"); + + static timer_ms_t silence_timer; + if (silence_detected == true) { + if (silence_timer.is_running == false) { + timer_init(&silence_timer, cfg.rec.silence_threshold); + timer_start(&silence_timer); + } + + if (timer_is_elapsed(&silence_timer)) { + // print_info("Recording silence threshold has been reached", 0); + stop_recording(false); + timer_stop(&silence_timer); + return; + } + } + else { + timer_stop(&silence_timer); + } + + Fl::repeat_timeout(0.1, &record_silence_timer); +} + +void wait_for_radioco_timer(void *) +{ +#ifdef WITH_RADIOCO + int error; + + if (radioco_get_state() == RADIOCO_STATE_WAITING) { + goto exit; + } + + error = radioco_get_thread_error(); + + if (error == RADIOCO_ERR_OK) { + error = radioco_request_station_list(); + if (error == RADIOCO_ERR_OK) { + radioco_stations_t stations; + radioco_get_station_list(&stations); + int nitems = fl_g->browser_add_srv_station_list->nitems(); + for (int i = 0; i < stations.num_of_stations; i++) { + bool exists = false; + for (int j = 0; j < nitems; j++) { + char *list_name = fl_g->browser_add_srv_station_list->text(j + 1); + if (!strcmp(list_name, stations.name[i])) { + exists = true; + break; + } + } + + if (exists == false) { + fl_g->browser_add_srv_station_list->add(stations.name[i], 1); + } + } + fl_g->browser_add_srv_station_list->redraw(); + return; + } + else { + fl_alert("Error during radioco stations request (%d).\nPlease try again.", error); + return; + } + } + else if (error == RADIOCO_ERR_CANCELED) { + return; + } + else { + fl_alert("Error in radioco thread (%d).\nPlease try again.", error); + return; + } + +exit: + Fl::repeat_timeout(1, &wait_for_radioco_timer); +#endif +} + +void songfile_timer(void *user_data) +{ + size_t len; + int num_of_lines; + int num_of_newlines; + char song[501]; + char msg[100]; + char *fgets_ret; + float repeat_time = 1; + + int reset; + if (user_data != NULL) { + reset = *((int *)user_data); + } + else { + reset = 0; + } + +#ifdef WIN32 + struct _stat s; +#else +#ifdef __USE_LARGEFILE64 + struct stat64 s; // Fixes fl_stat() on Raspberry PI OS (32 bit) +#else + struct stat s; +#endif +#endif + + static time_t old_t; + + if (reset == 1) { + old_t = 0; + } + + char *last_line = NULL; + + if ((cfg.main.song_path == NULL) || (connected == 0)) { + goto exit; + } + + if (fl_stat(cfg.main.song_path, (struct stat *)&s) != 0) { + // File was probably locked by another application + // retry in 5 seconds + repeat_time = 5; + goto exit; + } + + if (old_t == s.st_mtime) { // file hasn't changed + goto exit; + } + + if ((cfg.main.song_fd = fl_fopen(cfg.main.song_path, "rb")) == NULL) { + snprintf(msg, sizeof(msg), _("Warning\nCould not open: %s.\nWill retry in 5 seconds"), cfg.main.song_path); + + print_info(msg, 1); + repeat_time = 5; + goto exit; + } + + old_t = s.st_mtime; + + if (cfg.main.read_last_line == 1) { + /* Read last line instead of first */ + + fseek(cfg.main.song_fd, -100, SEEK_END); + len = fread(song, sizeof(char), 100, cfg.main.song_fd); + + // Count number of lines within the last 100 characters of the file + // Some programs add a new line to the end of the file and some don't + // We have to take this into account when counting the number of lines + num_of_newlines = 0; + for (uint32_t i = 0; i < len; i++) { + if (song[i] == '\n') { + num_of_newlines++; + } + } + + if (num_of_newlines == 0) { + num_of_lines = 1; + } + else if (num_of_newlines > 0 && song[len - 1] != '\n') { + num_of_lines = num_of_newlines + 1; + } + else { + num_of_lines = num_of_newlines; + } + + if (num_of_lines > 1) { // file has multiple lines + // Remove newlines at end of file + if (song[len - 2] == '\r') { // Windows + song[len - 2] = '\0'; + } + else if (song[len - 1] == '\n') { // OSX, Linux + song[len - 1] = '\0'; + } + else { + song[len] = '\0'; + } + + last_line = strrchr(song, '\n') + 1; + } + else { // file has only one line + // Remove newlines at end of file + if (len > 1 && song[len - 2] == '\r') { // Windows + song[len - 2] = '\0'; + } + else if (len > 0 && song[len - 1] == '\n') { // OSX, Linux + song[len - 1] = '\0'; + } + else { + song[len] = '\0'; + } + + last_line = song; + } + + // Remove UTF-8 BOM + if ((uint8_t)last_line[0] == 0xEF && (uint8_t)last_line[1] == 0xBB && (uint8_t)last_line[2] == 0xBF) { + cfg.main.song = (char *)realloc(cfg.main.song, strlen(last_line) + 1); + strcpy(cfg.main.song, last_line + 3); + } + else { + cfg.main.song = (char *)realloc(cfg.main.song, strlen(last_line) + 1); + strcpy(cfg.main.song, last_line); + } + + Fl::add_timeout(cfg.main.song_delay, &update_song); + } + else { + // read first line + fgets_ret = fgets(song, 500, cfg.main.song_fd); + + if (fgets_ret == NULL && feof(cfg.main.song_fd) != 0) { // file is empty (0 bytes) + len = 0; + } + else if (fgets_ret != NULL) { // Normal case + len = strlen(song); + } + else { // Some error occurred + fclose(cfg.main.song_fd); + goto exit; + } + + // remove newline character + if (len > 1 && song[len - 2] == '\r') { // Windows + song[len - 2] = '\0'; + } + else if (len > 0 && song[len - 1] == '\n') { // OSX, Linux + song[len - 1] = '\0'; + } + else { + song[len] = '\0'; + } + + // Remove UTF-8 BOM + if ((uint8_t)song[0] == 0xEF && (uint8_t)song[1] == 0xBB && (uint8_t)song[2] == 0xBF) { + cfg.main.song = (char *)realloc(cfg.main.song, strlen(song) + 1); + strcpy(cfg.main.song, song + 3); + } + else { + cfg.main.song = (char *)realloc(cfg.main.song, strlen(song) + 1); + strcpy(cfg.main.song, song); + } + + Fl::add_timeout(cfg.main.song_delay, &update_song); + } + + fclose(cfg.main.song_fd); + +exit: + Fl::repeat_timeout(repeat_time, &songfile_timer); +} + +void *url_song_update_thread_func(void *user_data) +{ + char song[1024]; + char *new_line; + + atom_set_int(&url_song_update_thread_running, 1); + + uint32_t ret = url_get(cfg.main.song_update_url, NULL, song, sizeof(song)); + if (ret <= 0) { + goto return_thread; + } + + // Remove new line characters + new_line = strchr(song, '\r'); + if (new_line != NULL) { + *new_line = '\0'; + } + new_line = strchr(song, '\n'); + if (new_line != NULL) { + *new_line = '\0'; + } + + if (cfg.main.song != NULL) { + if (strncmp(song, cfg.main.song, sizeof(song)) == 0) { + goto return_thread; + } + } + + cfg.main.song = (char *)realloc(cfg.main.song, strlen(song) + 1); + strcpy(cfg.main.song, song); + + // Call Fl::add_timeout from main thread + Fl::awake([](void *) -> void { + Fl::add_timeout(cfg.main.song_delay, &update_song); + }); + +return_thread: + // Detach thread (free ressources) because no one will call pthread_join() on it + pthread_detach(pthread_self()); + + atom_set_int(&url_song_update_thread_running, 0); + + return NULL; +} + +void song_url_timer(void *user_data) +{ + if (atom_get_int(&url_song_update_thread_running) == 0) { + if (pthread_create(&url_song_update_thread_detached, NULL, url_song_update_thread_func, user_data) != 0) { + print_info("Fatal error: Could not launch url song update thread. Please restart BUTT", 1); + return; + } + } + + Fl::repeat_timeout(cfg.main.song_update_url_interval, &song_url_timer); +} + +void app_timer(void *user_data) +{ + int reset; + + if (user_data != NULL) { + reset = *((int *)user_data); + } + else { + reset = 0; + } + + if (current_track_app != NULL) { + const char *track = current_track_app(cfg.main.app_artist_title_order); + if (track != NULL) { + if (cfg.main.song == NULL || strcmp(cfg.main.song, track) || reset == 1) { + cfg.main.song = (char *)realloc(cfg.main.song, strlen(track) + 1); + strcpy(cfg.main.song, track); + Fl::add_timeout(cfg.main.song_delay, &update_song); + } + free((void *)track); + } + else { + if (cfg.main.song != NULL && strcmp(cfg.main.song, "")) { + cfg.main.song = (char *)realloc(cfg.main.song, 1); + strcpy(cfg.main.song, ""); + Fl::add_timeout(cfg.main.song_delay, &update_song); + } + } + } + + Fl::repeat_timeout(1, &app_timer); +} diff --git a/src/FLTK/fl_timer_funcs.h b/src/FLTK/fl_timer_funcs.h new file mode 100644 index 0000000..bab364d --- /dev/null +++ b/src/FLTK/fl_timer_funcs.h @@ -0,0 +1,52 @@ +// FLTK GUI related functions +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef FL_TIMER_FUNCS_H +#define FL_TIMER_FUNCS_H + +void rotate_sponsor_logo_timer(void *); +void display_info_timer(void *); +void agent_watchdog_timer(void *); +void has_agent_been_started_timer(void *); +void has_agent_been_stopped_timer(void *); +void vu_meter_timer(void *); +void cmd_timer(void *); +void reconnect_timer(void *); +void is_connected_timer(void *); +void cfg_win_pos_timer(void *); +void songfile_timer(void *); +void song_url_timer(void *); +void stream_silence_timer(void *); +void record_silence_timer(void *); +void stream_signal_timer(void *); +void record_signal_timer(void *); +void wait_for_radioco_timer(void *); +void request_listener_count_timer(void *reset); + +void display_rotate_timer(void *); +void app_timer(void *); + +void split_recording_file_timer(void); +void split_recording_file(void); +void reset_stream_signal_detection_timer(void); +void reset_stream_silence_detection_timer(void); +void reset_record_signal_detection_timer(void); +void reset_record_silence_detection_timer(void); + +extern const char *(*current_track_app)(int); +extern int g_vu_meter_timer_is_active; +extern int g_stop_vu_meter_timer; + +#endif diff --git a/src/FLTK/flgui.cpp b/src/FLTK/flgui.cpp new file mode 100644 index 0000000..1c689f1 --- /dev/null +++ b/src/FLTK/flgui.cpp @@ -0,0 +1,6680 @@ +// generated by Fast Light User Interface Designer (fluid) version 1.0309 + +#include "../../gettext.h" +#include "flgui.h" + +void flgui::cb_window_main_i(Fl_My_Double_Window*, void*) { + window_main_close_cb(true); +} +void flgui::cb_window_main(Fl_My_Double_Window* o, void* v) { + ((flgui*)(o->user_data()))->cb_window_main_i(o,v); +} + +void flgui::cb_lcd_i(Fl_ILM216*, void*) { + ILM216_cb(); +} +void flgui::cb_lcd(Fl_ILM216* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_lcd_i(o,v); +} + +void flgui::cb_button_mixer_i(Fl_Button*, void*) { + button_mixer_cb(); +} +void flgui::cb_button_mixer(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_button_mixer_i(o,v); +} + +void flgui::cb_button_record_i(Fl_Button*, void*) { + button_record_cb(true); +} +void flgui::cb_button_record(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_button_record_i(o,v); +} + +void flgui::cb_button_disconnect_i(Fl_Button*, void*) { + button_disconnect_cb(true); +} +void flgui::cb_button_disconnect(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_button_disconnect_i(o,v); +} + +void flgui::cb_button_connect_i(Fl_Button*, void*) { + button_connect_cb(); +} +void flgui::cb_button_connect(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_button_connect_i(o,v); +} + +void flgui::cb_vu_tabs_i(Fl_Tabs*, void*) { + vu_tabs_cb(); +} +void flgui::cb_vu_tabs(Fl_Tabs* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_vu_tabs_i(o,v); +} + +void flgui::cb_button_cfg_i(Fl_Button*, void*) { + button_cfg_cb(); +} +void flgui::cb_button_cfg(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_button_cfg_i(o,v); +} + +void flgui::cb_button_info_i(Fl_Button*, void*) { + button_info_cb(); +} +void flgui::cb_button_info(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_button_info_i(o,v); +} + +void flgui::cb_slider_gain_i(Fl_My_Value_Slider*, void* v) { + slider_gain_cb(v); +} +void flgui::cb_slider_gain(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_slider_gain_i(o,v); +} + +#include +static const unsigned char idata_radio_co_badge[] = +{0,0,0,0,255,255,255,19,255,255,255,68,255,255,255,66,255,255,255,66,255, +255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255, +255,67,255,255,255,67,255,255,255,67,255,255,255,66,255,255,255,66,255,255,255, +67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67, +255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255, +255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255, +255,66,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255, +67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67, +255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255, +255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255, +255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,66,255,255,255, +67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67, +255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255, +255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255, +255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255, +67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67, +255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,66,255,255,255,67,255, +255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255, +255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255, +67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67, +255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255, +255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255,255,67,255,255, +255,67,255,255,255,67,255,255,255,67,255,255,255,66,255,255,255,66,255,255,255, +67,255,255,255,66,255,255,255,12,0,0,0,0,255,255,255,62,255,255,255,242,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,230,255,255,255,45,255,255,255,223,255,255,255,255,255,255,255,249,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255, +255,255,253,255,255,255,253,255,255,255,253,255,255,255,248,255,255,255,255,255, +255,255,194,255,255,255,255,255,255,255,252,255,255,255,255,255,255,255,255,255, +255,255,254,255,255,255,255,255,255,255,254,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,255, +255,255,254,255,255,255,254,255,255,255,255,255,255,255,254,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,254,255,255,255,254,255,255,255,254,255,255,255,255,255,255,255,254,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,254,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,254,255,255,255,254,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,253,255,255,255,255,255,255,255,233,255, +255,255,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,253,255,255,255,255,255,255,255,231,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,253,255,255,255,255,255,255,255,232,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,255, +255,255,255,255,255,255,232,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255,255,255,255, +255,255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,253,255,255,255,255,255,255,255,232,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,254,254,254,255,253,253,253,255,254,254,254,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253,253,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,255,253, +253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,253,255,255,255,255,255,255,255,232,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254, +254,254,255,255,255,255,255,254,254,254,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,253,255,255,255,255,255,255,255,232,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,254,254,254,255,255,255,255,255,241,241,241,255,210, +210,210,255,234,234,234,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,254,254,254,255,222,222,222,255,247,247,247,255,255,255,255,255,254, +254,254,255,255,255,255,255,243,243,243,255,225,225,225,255,255,255,255,255,254, +254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,255, +255,255,255,255,255,255,232,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253, +253,253,255,255,255,255,255,221,221,221,255,35,35,35,255,102,102,102,255,38,38, +38,255,212,212,212,255,255,255,255,255,252,252,252,255,254,254,254,255,255,255, +255,255,254,254,254,255,254,254,254,255,255,255,255,255,254,254,254,255,253,253, +253,255,255,255,255,255,254,254,254,255,254,254,254,255,255,255,255,255,255,255, +255,255,254,254,254,255,254,254,254,255,255,255,255,255,253,253,253,255,255,255, +255,255,255,255,255,255,253,253,253,255,255,255,255,255,254,254,254,255,255,255, +255,255,255,255,255,255,253,253,253,255,254,254,254,255,255,255,255,255,253,253, +253,255,255,255,255,255,255,255,255,255,254,254,254,255,254,254,254,255,255,255, +255,255,255,255,255,255,253,253,253,255,255,255,255,255,254,254,254,255,254,254, +254,255,255,255,255,255,254,254,254,255,253,253,253,255,255,255,255,255,251,251, +251,255,66,66,66,255,226,226,226,255,255,255,255,255,252,252,252,255,255,255, +255,255,208,208,208,255,98,98,98,255,255,255,255,255,254,254,254,255,253,253, +253,255,255,255,255,255,255,255,255,255,254,254,254,255,255,255,255,255,255,255, +255,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255,255,255,255,255, +255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,255,255,255, +255,255,116,116,116,255,174,174,174,255,255,255,255,255,237,237,237,255,245,245, +245,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,253,253,253,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,253,253,253,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254, +254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254, +254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253, +253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,102,102, +102,255,227,227,227,255,255,255,255,255,252,252,252,255,255,255,255,255,210,210, +210,255,125,125,125,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,254,254,254,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,253,255,255,255,255,255,255,255,232,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,253,253,253,255,255,255,255,255,174,174, +174,255,81,81,81,255,229,229,229,255,255,255,255,255,255,255,255,255,252,252, +252,255,166,166,166,255,148,148,148,255,105,105,105,255,131,131,131,255,237,237, +237,255,255,255,255,255,252,252,252,255,168,168,168,255,97,97,97,255,127,127, +127,255,230,230,230,255,255,255,255,255,212,212,212,255,143,143,143,255,133,133, +133,255,97,97,97,255,207,207,207,255,255,255,255,255,253,253,253,255,178,178, +178,255,103,103,103,255,137,137,137,255,244,244,244,255,255,255,255,255,201,201, +201,255,105,105,105,255,106,106,106,255,202,202,202,255,255,255,255,255,239,239, +239,255,158,158,158,255,139,139,139,255,155,155,155,255,255,255,255,255,185,185, +185,255,110,110,110,255,132,132,132,255,232,232,232,255,255,255,255,255,251,251, +251,255,163,163,163,255,95,95,95,255,144,144,144,255,68,68,68,255,229,229,229, +255,255,255,255,255,252,252,252,255,255,255,255,255,214,214,214,255,71,71,71, +255,143,143,143,255,91,91,91,255,178,178,178,255,255,255,255,255,180,180,180, +255,196,196,196,255,255,255,255,255,253,253,253,255,154,154,154,255,227,227,227, +255,255,255,255,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,253,255,255,255,255,255,255,255,232,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,254,254,254,255,255,255,255,255,253,253,253,255,174,174,174, +255,34,34,34,255,123,123,123,255,243,243,243,255,255,255,255,255,61,61,61,255, +142,142,142,255,233,233,233,255,158,158,158,255,87,87,87,255,255,255,255,255, +164,164,164,255,94,94,94,255,231,231,231,255,173,173,173,255,53,53,53,255,255, +255,255,255,194,194,194,255,0,0,0,255,215,215,215,255,208,208,208,255,0,0,0,255, +239,239,239,255,223,223,223,255,0,0,0,255,233,233,233,255,219,219,219,255,255, +255,255,255,218,218,218,255,0,0,0,255,212,212,212,255,212,212,212,255,0,0,0,255, +222,222,222,255,244,244,244,255,0,0,0,255,170,170,170,255,245,245,245,255,201, +201,201,255,58,58,58,255,231,231,231,255,182,182,182,255,72,72,72,255,255,255, +255,255,163,163,163,255,98,98,98,255,230,230,230,255,186,186,186,255,0,0,0,255, +232,232,232,255,255,255,255,255,252,252,252,255,255,255,255,255,217,217,217,255, +0,0,0,255,201,201,201,255,224,224,224,255,48,48,48,255,197,197,197,255,225, +225,225,255,19,19,19,255,255,255,255,255,217,217,217,255,62,62,62,255,252,252, +252,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,253,255,255,255,255,255,255,255,232,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,250,250,250,255,138,138,138,255,131,131,131,255,255,255,255,255,101,101, +101,255,238,238,238,255,255,255,255,255,255,255,255,255,86,86,86,255,221,221, +221,255,105,105,105,255,230,230,230,255,255,255,255,255,255,255,255,255,99,99, +99,255,225,225,225,255,200,200,200,255,146,146,146,255,255,255,255,255,255,255, +255,255,137,137,137,255,193,193,193,255,254,254,254,255,116,116,116,255,110,110, +110,255,199,199,199,255,255,255,255,255,151,151,151,255,176,176,176,255,255,255, +255,255,255,255,255,255,175,175,175,255,161,161,161,255,246,246,246,255,85,85, +85,255,254,254,254,255,255,255,255,255,145,145,145,255,93,93,93,255,145,145, +145,255,134,134,134,255,85,85,85,255,229,229,229,255,98,98,98,255,231,231,231, +255,255,255,255,255,255,255,255,255,98,98,98,255,227,227,227,255,255,255,255, +255,252,252,252,255,255,255,255,255,210,210,210,255,123,123,123,255,255,255,255, +255,255,255,255,255,216,216,216,255,98,98,98,255,255,255,255,255,114,114,114, +255,199,199,199,255,147,147,147,255,185,185,185,255,255,255,255,255,252,252,252, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +253,255,255,255,255,255,255,255,232,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,200,200,200,255,237,237,237,255,255,255,255, +255,211,211,211,255,73,73,73,255,255,255,255,255,94,94,94,255,217,217,217,255, +255,255,255,255,235,235,235,255,35,35,35,255,239,239,239,255,114,114,114,255, +195,195,195,255,255,255,255,255,245,245,245,255,38,38,38,255,238,238,238,255, +198,198,198,255,139,139,139,255,255,255,255,255,255,255,255,255,149,149,149,255, +190,190,190,255,255,255,255,255,249,249,249,255,233,233,233,255,44,44,44,255, +206,206,206,255,189,189,189,255,125,125,125,255,255,255,255,255,255,255,255,255, +127,127,127,255,183,183,183,255,245,245,245,255,85,85,85,255,244,244,244,255, +255,255,255,255,158,158,158,255,146,146,146,255,255,255,255,255,246,246,246,255, +233,233,233,255,255,255,255,255,99,99,99,255,196,196,196,255,255,255,255,255, +247,247,247,255,76,76,76,255,229,229,229,255,255,255,255,255,252,252,252,255, +255,255,255,255,213,213,213,255,99,99,99,255,255,255,255,255,255,255,255,255, +174,174,174,255,125,125,125,255,255,255,255,255,217,217,217,255,0,0,0,255,90,90, +90,255,245,245,245,255,255,255,255,255,254,254,254,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255,255,255,255,255, +255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,146,146,146,255,46,46,46,255,136,136,136,255,0,0,0,255,195,195,195,255, +255,255,255,255,95,95,95,255,67,67,67,255,151,151,151,255,43,43,43,255,169,169, +169,255,255,255,255,255,214,214,214,255,17,17,17,255,147,147,147,255,74,74,74, +255,152,152,152,255,255,255,255,255,182,182,182,255,131,131,131,255,255,255,255, +255,255,255,255,255,132,132,132,255,194,194,194,255,234,234,234,255,92,92,92, +255,181,181,181,255,79,79,79,255,216,216,216,255,252,252,252,255,84,84,84,255, +122,122,122,255,122,122,122,255,89,89,89,255,251,251,251,255,236,236,236,255,57, +57,57,255,247,247,247,255,255,255,255,255,239,239,239,255,90,90,90,255,156,156, +156,255,144,144,144,255,133,133,133,255,255,255,255,255,214,214,214,255,0,0,0, +255,143,143,143,255,111,111,111,255,0,0,0,255,230,230,230,255,255,255,255,255, +252,252,252,255,255,255,255,255,215,215,215,255,0,0,0,255,126,126,126,255,134, +134,134,255,34,34,34,255,228,228,228,255,255,255,255,255,255,255,255,255,97,97, +97,255,164,164,164,255,255,255,255,255,253,253,253,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255, +255,255,255,255,255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254, +254,255,255,255,255,255,255,255,255,255,221,221,221,255,190,190,190,255,223,223, +223,255,255,255,255,255,253,253,253,255,110,110,110,255,205,205,205,255,198,198, +198,255,217,217,217,255,255,255,255,255,254,254,254,255,255,255,255,255,235,235, +235,255,190,190,190,255,215,215,215,255,255,255,255,255,255,255,255,255,236,236, +236,255,227,227,227,255,255,255,255,255,255,255,255,255,228,228,228,255,237,237, +237,255,255,255,255,255,219,219,219,255,185,185,185,255,225,225,225,255,255,255, +255,255,255,255,255,255,249,249,249,255,199,199,199,255,199,199,199,255,249,249, +249,255,255,255,255,255,248,248,248,255,221,221,221,255,253,253,253,255,254,254, +254,255,255,255,255,255,246,246,246,255,195,195,195,255,199,199,199,255,245,245, +245,255,255,255,255,255,255,255,255,255,234,234,234,255,190,190,190,255,219,219, +219,255,222,222,222,255,246,246,246,255,255,255,255,255,254,254,254,255,255,255, +255,255,243,243,243,255,223,223,223,255,214,214,214,255,191,191,191,255,241,241, +241,255,255,255,255,255,255,255,255,255,247,247,247,255,81,81,81,255,233,233, +233,255,255,255,255,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255,255,255,255,255, +255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,253,253,253,255,80,80,80,255,232,232,232,255,255,255,255,255,255,255, +255,255,254,254,254,255,255,255,255,255,254,254,254,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,254,254,254,255,255,255,255,255,255,255, +255,255,254,254,254,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,255,254,254, +254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253, +253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254, +254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,254,254,254,255,255,255,255,255,254,254,254,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,251,251, +251,255,255,255,255,255,175,175,175,255,124,124,124,255,255,255,255,255,253,253, +253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,253,255,255,255,255,255,255,255,232,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,255,254, +254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,253,253,253,255,253,253,253,255,253,253,253,255,255,255,255,255,254,254, +254,255,145,145,145,255,232,232,232,255,255,255,255,255,252,252,252,255,255,255, +255,255,255,255,255,255,255,255,255,255,254,254,254,255,253,253,253,255,253,253, +253,255,255,255,255,255,255,255,255,255,254,254,254,255,254,254,254,255,255,255, +255,255,255,255,255,255,254,254,254,255,254,254,254,255,255,255,255,255,253,253, +253,255,253,253,253,255,253,253,253,255,255,255,255,255,255,255,255,255,254,254, +254,255,253,253,253,255,253,253,253,255,254,254,254,255,255,255,255,255,255,255, +255,255,253,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254, +254,255,253,253,253,255,253,253,253,255,254,254,254,255,255,255,255,255,255,255, +255,255,254,254,254,255,253,253,253,255,253,253,253,255,253,253,253,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,255,253,253, +253,255,253,253,253,255,253,253,253,255,254,254,254,255,255,255,255,255,255,255, +255,255,142,142,142,255,220,220,220,255,255,255,255,255,253,253,253,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,253,255,255,255,255,255,255,255,232,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,254,253,253,255,255,255,255,255,255,255,255,255,254,253, +253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,255,255,255, +255,255,255,255,255,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,253,255,255,255,255,255,255,255,232,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,252,243,243,255,253,248,248,255,255,255,255,255,255,254, +254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254, +254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255, +255,255,255,255,255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,254,254,255,254,253,253,255,255,255,255,255,255,255,255,255,241,197, +197,255,224,87,87,255,226,110,110,255,245,218,218,255,255,255,255,255,255,254, +254,255,254,253,253,255,255,254,254,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255,255,255,255,255, +255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,254,254,255,254,253,253,255,255,255, +255,255,255,255,255,255,255,255,255,255,252,243,243,255,222,71,71,255,222,77,77, +255,220,44,44,255,228,124,124,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,254,253,253,255,255,254,254,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,253,255,255,255,255,255,255,255,232,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,254,253,253,255,255,255,255,255,255,255,255,255,247,225,225,255,237,181,181, +255,255,255,255,255,252,244,244,255,224,97,97,255,223,84,84,255,222,70,70,255, +229,132,132,255,255,255,255,255,251,241,241,255,237,178,178,255,251,240,240,255, +255,255,255,255,255,255,255,255,254,253,253,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,253,255,255,255,255,255,255,255,232,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,254,253,253,255,255,255,255,255,255,255,255,255, +252,243,243,255,235,172,172,255,221,55,55,255,223,74,74,255,254,249,249,255,252, +246,246,255,224,91,91,255,223,82,82,255,222,65,65,255,228,129,129,255,255,255, +255,255,248,229,229,255,219,0,0,255,224,93,93,255,240,192,192,255,254,252,252, +255,255,255,255,255,255,254,254,255,255,253,253,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255,255, +255,255,255,255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254, +255,255,255,255,255,254,253,253,255,240,195,195,255,224,93,93,255,221,43,43,255, +222,78,78,255,226,107,107,255,254,250,250,255,252,245,245,255,224,91,91,255,223, +83,83,255,222,65,65,255,228,129,129,255,255,255,255,255,248,231,231,255,222,75, +75,255,223,81,81,255,220,31,31,255,227,119,119,255,244,213,213,255,255,255,255, +255,255,255,255,255,255,254,254,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,254,254,254,255,253,253,253,255,254,254,254,255,255,255,255, +255,253,253,253,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,253,255,255,255,255,255,255,255,232,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,245,217,217,255,227,122,122, +255,220,31,31,255,222,78,78,255,224,92,92,255,222,75,75,255,225,101,101,255,254, +250,250,255,252,246,246,255,224,91,91,255,223,83,83,255,222,65,65,255,228,129, +129,255,255,255,255,255,248,230,230,255,221,63,63,255,223,86,86,255,224,91,91, +255,222,68,68,255,221,42,42,255,231,147,147,255,249,233,233,255,255,255,255,255, +255,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253, +255,255,255,255,255,255,255,232,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,255,255,255,255,255, +241,200,200,255,219,0,0,255,222,70,70,255,224,90,90,255,223,84,84,255,223,83,83, +255,222,74,74,255,225,103,103,255,254,250,250,255,252,245,245,255,224,91,91,255, +223,83,83,255,222,65,65,255,228,129,129,255,255,255,255,255,248,231,231,255,222, +65,65,255,223,84,84,255,223,81,81,255,223,86,86,255,223,89,89,255,221,53,53, +255,222,63,63,255,248,227,227,255,255,255,255,255,255,254,254,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,250,250,250,255,231,232,232,255,230,230,230,255,242,242,242,255,255,255,255, +255,212,212,213,255,233,233,233,255,255,255,255,255,254,254,254,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,253,255,255,255,255,255,255,255,232,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,229,132,132,255,221,63,63,255,224,91,91,255, +223,81,81,255,223,82,82,255,223,84,84,255,223,81,81,255,225,97,97,255,253,249, +249,255,252,245,245,255,224,90,90,255,223,83,83,255,222,66,66,255,228,128,128, +255,255,255,255,255,248,229,229,255,221,61,61,255,224,90,90,255,223,81,81,255, +223,82,82,255,223,81,81,255,224,96,96,255,220,31,31,255,236,174,174,255,255,255, +255,255,254,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254, +254,255,254,254,254,255,254,254,254,255,255,255,255,255,253,253,253,255,254,254, +254,255,255,255,255,255,255,255,255,255,254,254,254,255,253,253,253,255,253,253, +253,255,253,253,253,255,254,254,254,255,254,254,254,255,254,254,254,255,254,254, +254,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,255,253,253, +253,255,252,252,252,255,255,255,255,255,228,228,228,255,0,0,0,255,0,0,0,255,172, +172,172,255,193,193,193,255,0,0,0,255,47,48,50,255,239,239,239,255,255,255,255, +255,254,254,254,255,254,254,254,255,253,253,253,255,253,253,253,255,253,253,253, +255,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254, +255,253,253,253,255,253,253,253,255,253,253,253,255,254,254,254,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,253,253,253,255,253,253,253,255,253,253,253,255,253,253,253,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,253,255,255,255,255,255,255,255, +232,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,229,136,136,255,221,63,63, +255,223,86,86,255,223,82,82,255,223,82,82,255,223,86,86,255,220,27,27,255,227, +118,118,255,254,252,252,255,252,246,246,255,224,94,94,255,223,82,82,255,222,64, +64,255,229,133,133,255,255,255,255,255,249,235,235,255,222,70,70,255,221,59,59, +255,223,86,86,255,223,81,81,255,223,82,82,255,223,88,88,255,221,46,46,255,236, +172,172,255,255,255,255,255,254,254,254,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,254,254,254,255,253,253,253,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,254,254,254,255,253,253,253,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,227,227,227,255,0,0, +0,255,0,0,0,255,175,175,175,255,184,184,184,255,0,0,0,255,0,0,0,255,234,234, +235,255,255,255,255,255,252,252,252,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,253,253,253,255,254,254,254,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,253, +253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,253,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254, +254,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,254,254,254,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255, +255,255,255,255,255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,229,135, +135,255,221,61,61,255,223,87,87,255,223,82,82,255,223,86,86,255,222,67,67,255, +234,167,167,255,252,245,245,255,255,255,255,255,249,231,231,255,222,73,73,255, +223,87,87,255,222,72,72,255,226,114,114,255,254,251,251,255,255,255,255,255,249, +234,234,255,229,138,138,255,222,68,68,255,223,86,86,255,223,81,81,255,224,89,89, +255,220,41,41,255,236,173,173,255,255,255,255,255,254,253,253,255,255,255,255, +255,255,255,255,255,255,255,255,255,250,250,250,255,246,246,246,255,247,247,247, +255,255,255,255,255,221,221,221,255,236,236,236,255,255,255,255,255,255,255,255, +255,247,247,247,255,217,217,217,255,208,208,208,255,218,218,219,255,252,252,252, +255,252,252,252,255,245,245,245,255,247,247,247,255,254,254,254,255,255,255,255, +255,255,255,255,255,239,239,239,255,214,214,214,255,211,211,211,255,243,243,243, +255,235,235,235,255,0,0,0,255,0,0,0,255,166,166,166,255,251,251,252,255,170,170, +170,255,206,206,206,255,255,255,255,255,253,253,253,255,255,255,255,255,253,253, +253,255,224,224,224,255,212,212,212,255,216,216,216,255,242,242,242,255,255,255, +255,255,255,255,255,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255, +255,255,254,254,254,255,255,255,255,255,251,251,251,255,221,221,221,255,211,212, +212,255,220,220,220,255,248,248,248,255,255,255,255,255,254,254,254,255,255,255, +255,255,254,254,254,255,255,255,255,255,255,255,255,255,232,233,233,255,213,213, +213,255,213,213,214,255,232,232,232,255,255,255,255,255,255,255,255,255,253,253, +253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,253,255,255,255,255,255,255,255,232,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,229,135,135,255,221,61,61,255,223,87,87,255,223,83,83, +255,223,80,80,255,224,85,85,255,253,245,245,255,255,255,255,255,244,211,211,255, +226,110,110,255,222,74,74,255,223,84,84,255,223,85,85,255,222,70,70,255,229,135, +135,255,247,227,227,255,255,255,255,255,246,222,222,255,221,44,44,255,223,88,88, +255,223,81,81,255,224,89,89,255,220,41,41,255,236,172,172,255,255,255,255,255, +254,253,253,255,255,255,255,255,253,253,253,255,255,255,255,255,176,176,176,255, +0,0,0,255,94,95,95,255,145,146,146,255,0,0,0,255,191,191,191,255,255,255,255, +255,198,198,198,255,61,62,63,255,0,0,0,255,0,0,0,255,0,0,0,255,124,124,125,255, +126,127,128,255,30,31,32,255,98,99,99,255,247,247,247,255,255,255,255,255,172, +172,173,255,0,0,3,255,0,0,0,255,0,0,0,255,57,58,59,255,146,147,147,255,47,48,49, +255,0,0,0,255,171,171,172,255,176,177,177,255,76,77,77,255,86,87,88,255,223,223, +223,255,255,255,255,255,215,215,215,255,96,97,98,255,0,0,0,255,0,0,0,255,0,0,0, +255,44,45,47,255,175,175,175,255,255,255,255,255,255,255,255,255,254,254,254, +255,255,255,255,255,254,254,254,255,255,255,255,255,210,210,211,255,84,85,86, +255,0,0,0,255,0,0,0,255,0,0,0,255,71,72,73,255,197,197,197,255,255,255,255,255, +253,253,253,255,255,255,255,255,241,241,241,255,136,137,137,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,135,135,135,255,240,240,240,255,255,255,255,255,253,253, +253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,253,255,255,255,255,255,255,255,232,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,229,135,135,255,221,61,61,255,223,87,87,255,223,83,83,255,223,79,79,255, +224,90,90,255,252,243,243,255,253,246,246,255,222,69,69,255,221,62,62,255,223, +87,87,255,223,81,81,255,223,81,81,255,224,90,90,255,220,8,8,255,228,126,126, +255,255,255,255,255,246,220,220,255,221,52,52,255,223,87,87,255,223,81,81,255, +224,89,89,255,220,41,41,255,236,172,172,255,255,255,255,255,254,253,253,255,255, +255,255,255,253,253,253,255,255,255,255,255,167,167,167,255,0,0,0,255,6,10,14, +255,0,0,0,255,0,0,0,255,202,202,202,255,215,215,215,255,0,0,0,255,0,0,0,255,0,0, +0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,52,53,55,255,252,252, +252,255,172,172,172,255,0,0,0,255,22,24,25,255,0,0,0,255,0,0,0,255,0,0,0,255,0, +0,0,255,42,44,45,255,0,0,0,255,173,173,173,255,163,163,163,255,0,0,0,255,0,0, +0,255,230,230,231,255,224,224,224,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255, +0,0,0,255,0,0,0,255,0,0,0,255,154,154,155,255,255,255,255,255,254,254,254,255, +253,253,253,255,255,255,255,255,208,208,208,255,0,0,0,255,0,0,0,255,0,0,0,255,0, +0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,189,189,189,255,255,255,255,255,243,243, +244,255,82,83,84,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,77,78,79,255,244,244,244,255,255,255,255,255,254,254,254,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,253,255,255,255,255,255,255,255, +232,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,229,135,135,255,221,61,61, +255,223,87,87,255,223,83,83,255,223,79,79,255,224,88,88,255,252,245,245,255,253, +246,246,255,224,95,95,255,223,82,82,255,223,83,83,255,223,82,82,255,223,82,82, +255,223,87,87,255,222,68,68,255,229,134,134,255,255,255,255,255,246,221,221,255, +221,50,50,255,223,87,87,255,223,81,81,255,224,89,89,255,220,41,41,255,236,172, +172,255,255,255,255,255,254,253,253,255,255,255,255,255,253,253,253,255,255,255, +255,255,169,169,170,255,0,0,0,255,29,31,32,255,57,58,59,255,153,154,154,255,221, +221,221,255,92,93,94,255,0,0,0,255,0,0,0,255,131,131,131,255,210,210,210,255, +191,192,192,255,71,72,73,255,0,0,0,255,0,0,0,255,95,96,96,255,219,219,219,255,0, +0,0,255,30,32,33,255,0,0,0,255,158,159,159,255,213,213,213,255,179,179,180, +255,35,36,38,255,25,27,29,255,0,0,0,255,172,172,173,255,166,167,167,255,0,0,0, +255,0,0,0,255,220,220,221,255,111,111,112,255,0,0,0,255,0,0,0,255,135,135,136, +255,211,211,212,255,180,180,180,255,11,15,18,255,39,40,41,255,0,0,0,255,214,214, +214,255,255,255,255,255,255,255,255,255,248,248,248,255,69,70,71,255,0,0,0,255, +0,0,0,255,148,148,148,255,213,213,213,255,176,176,176,255,0,0,0,255,0,0,0,255, +0,0,0,255,238,238,239,255,175,175,175,255,0,0,0,255,17,20,22,255,85,85,86,255, +200,200,200,255,201,201,202,255,88,89,89,255,12,15,18,255,0,0,0,255,162,162,162, +255,255,255,255,255,253,253,253,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,253,255,255,255,255,255,255,255,232,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,229,135,135,255,221,61,61,255,223,87,87,255,223,83,83,255, +223,79,79,255,224,88,88,255,252,245,245,255,253,247,247,255,224,95,95,255,222, +77,77,255,223,84,84,255,223,82,82,255,223,82,82,255,223,87,87,255,221,61,61, +255,229,136,136,255,255,255,255,255,246,221,221,255,221,51,51,255,223,87,87,255, +223,81,81,255,224,89,89,255,220,41,41,255,236,172,172,255,255,255,255,255,254, +253,253,255,255,255,255,255,253,253,253,255,255,255,255,255,169,169,169,255,0,0, +0,255,0,0,0,255,196,197,197,255,255,255,255,255,223,223,223,255,0,0,0,255,0,0, +0,255,115,116,116,255,255,255,255,255,255,255,255,255,255,255,255,255,222,222, +222,255,0,0,0,255,0,0,0,255,105,105,106,255,172,172,173,255,0,0,0,255,0,0,0,255, +165,165,165,255,255,255,255,255,255,255,255,255,255,255,255,255,200,200,200,255, +0,0,0,255,0,0,0,255,172,172,173,255,166,166,167,255,0,0,0,255,52,53,55,255, +182,182,183,255,38,40,41,255,0,0,0,255,120,120,121,255,255,255,255,255,255,255, +255,255,255,255,255,255,193,194,194,255,0,0,0,255,0,0,0,255,157,157,158,255,255, +255,255,255,255,255,255,255,212,212,212,255,0,0,0,255,0,0,0,255,136,137,137,255, +255,255,255,255,255,255,255,255,255,255,255,255,204,204,204,255,151,152,152,255, +154,154,154,255,211,212,212,255,108,109,109,255,0,0,0,255,29,31,33,255,233,233, +233,255,255,255,255,255,255,255,255,255,234,234,234,255,35,37,39,255,0,0,0,255, +82,83,84,255,249,249,249,255,255,255,255,255,254,254,254,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,253,255,255,255,255,255,255,255,232,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,229,135,135,255,221,61,61,255,223,87,87,255,223, +83,83,255,223,79,79,255,224,88,88,255,252,244,244,255,252,245,245,255,223,72, +72,255,223,84,84,255,223,88,88,255,223,81,81,255,223,81,81,255,224,93,93,255, +221,61,61,255,227,122,122,255,255,255,255,255,246,220,220,255,221,51,51,255,223, +87,87,255,223,81,81,255,224,89,89,255,220,41,41,255,236,172,172,255,255,255, +255,255,254,253,253,255,255,255,255,255,253,253,253,255,255,255,255,255,169,169, +169,255,0,0,0,255,0,0,0,255,225,225,225,255,255,255,255,255,200,200,201,255,0,0, +0,255,0,0,0,255,184,185,185,255,255,255,255,255,249,249,249,255,252,252,252, +255,254,254,254,255,100,101,102,255,0,0,0,255,104,104,105,255,147,148,148,255,0, +0,0,255,0,0,0,255,220,221,221,255,255,255,255,255,249,249,249,255,255,255,255, +255,244,244,244,255,62,63,64,255,0,0,0,255,173,174,174,255,166,167,167,255,0,0, +0,255,63,64,65,255,157,158,158,255,20,22,24,255,0,0,0,255,187,187,187,255,255, +255,255,255,248,248,248,255,255,255,255,255,240,240,240,255,33,35,37,255,0,0,0, +255,133,134,134,255,255,255,255,255,255,255,255,255,196,196,196,255,0,0,0,255,0, +0,0,255,201,201,201,255,255,255,255,255,249,249,249,255,251,251,251,255,255, +255,255,255,255,255,255,255,255,255,255,255,247,247,247,255,45,46,48,255,0,0,0, +255,125,125,125,255,255,255,255,255,251,251,251,255,250,250,250,255,255,255,255, +255,127,127,128,255,0,0,0,255,46,48,49,255,238,238,238,255,255,255,255,255,254, +254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255,255,255,255, +255,255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,229,135,135,255,221, +61,61,255,223,87,87,255,223,83,83,255,222,78,78,255,224,91,91,255,253,246,246, +255,255,254,254,255,232,149,149,255,220,26,26,255,222,71,71,255,224,91,91,255, +223,89,89,255,221,61,61,255,221,42,42,255,237,180,180,255,255,255,255,255,247, +224,224,255,221,50,50,255,223,88,88,255,223,81,81,255,224,89,89,255,220,41,41, +255,236,172,172,255,255,255,255,255,254,253,253,255,255,255,255,255,253,253,253, +255,255,255,255,255,169,169,169,255,0,0,0,255,0,0,0,255,222,222,222,255,255,255, +255,255,209,209,209,255,0,0,0,255,0,0,0,255,154,154,155,255,255,255,255,255,255, +255,255,255,255,255,255,255,244,244,244,255,57,59,60,255,0,0,0,255,105,105,106, +255,160,160,161,255,0,0,0,255,0,0,0,255,198,198,198,255,255,255,255,255,254,254, +254,255,255,255,255,255,227,227,227,255,0,0,0,255,0,0,0,255,173,173,173,255,166, +167,167,255,0,0,0,255,60,61,62,255,167,167,168,255,26,28,30,255,0,0,0,255,158, +159,159,255,255,255,255,255,254,254,254,255,255,255,255,255,224,224,224,255,0,0, +0,255,0,0,0,255,142,142,142,255,255,255,255,255,255,255,255,255,203,203,203, +255,0,0,0,255,0,0,0,255,176,176,176,255,255,255,255,255,255,255,255,255,255,255, +255,255,241,241,241,255,215,215,216,255,221,221,221,255,224,225,225,255,80,81, +82,255,0,0,0,255,86,87,88,255,252,252,252,255,255,255,255,255,255,255,255,255, +254,254,254,255,92,93,93,255,0,0,0,255,64,65,66,255,243,243,243,255,255,255,255, +255,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255,255, +255,255,255,255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,229,135,135, +255,221,61,61,255,223,87,87,255,223,82,82,255,223,85,85,255,222,70,70,255,245, +215,215,255,255,255,255,255,255,255,255,255,243,208,208,255,226,113,113,255,220, +32,32,255,221,44,44,255,230,138,138,255,247,225,225,255,255,255,255,255,255, +255,255,255,238,187,187,255,221,52,52,255,223,88,88,255,223,81,81,255,224,89,89, +255,220,41,41,255,236,172,172,255,255,255,255,255,254,253,253,255,255,255,255, +255,253,253,253,255,255,255,255,255,169,169,169,255,0,0,0,255,0,0,0,255,224,224, +224,255,255,255,255,255,235,235,235,255,0,0,0,255,24,25,27,255,0,0,0,255,196, +196,196,255,249,249,249,255,241,241,242,255,146,146,146,255,0,0,0,255,0,0,0,255, +100,101,101,255,200,200,200,255,0,0,0,255,7,11,14,255,67,68,69,255,220,220,221, +255,250,250,250,255,233,233,233,255,114,114,115,255,0,0,0,255,0,0,0,255,172,172, +172,255,166,166,166,255,0,0,0,255,24,26,29,255,204,204,204,255,67,67,68,255,0,0, +0,255,0,0,0,255,201,202,202,255,251,251,251,255,234,235,235,255,110,110,111, +255,0,0,0,255,0,0,0,255,196,196,196,255,248,248,248,255,229,229,229,255,239,239, +239,255,0,0,0,255,0,0,3,255,41,43,44,255,213,213,213,255,251,251,251,255,230, +231,231,255,96,97,98,255,0,0,0,255,0,0,0,255,214,214,214,255,144,144,144,255,0, +0,0,255,0,0,0,255,160,161,161,255,245,245,246,255,246,246,247,255,166,166,166, +255,0,0,0,255,0,0,0,255,127,127,128,255,255,255,255,255,254,254,254,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255,255,255,255,255, +255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,230,136,136,255,221,60, +60,255,223,87,87,255,223,82,82,255,223,83,83,255,223,79,79,255,222,74,74,255, +236,174,174,255,252,244,244,255,255,255,255,255,254,251,251,255,238,186,186,255, +242,201,201,255,255,255,255,255,255,255,255,255,249,232,232,255,232,150,150,255, +221,62,62,255,223,84,84,255,223,82,82,255,223,82,82,255,223,89,89,255,220,41,41, +255,236,173,173,255,255,255,255,255,254,253,253,255,255,255,255,255,253,253,253, +255,255,255,255,255,171,171,171,255,0,0,0,255,0,0,0,255,226,226,226,255,255,255, +255,255,255,255,255,255,155,155,155,255,0,0,0,255,46,47,48,255,0,0,0,255,77,78, +79,255,54,55,56,255,0,0,0,255,33,34,35,255,0,0,2,255,82,83,83,255,245,245,245, +255,113,113,114,255,0,0,0,255,27,29,30,255,0,0,0,255,85,86,87,255,23,26,28,255, +0,0,0,255,53,54,55,255,0,0,0,255,174,174,174,255,168,168,169,255,0,0,0,255,0, +0,0,255,232,232,232,255,179,179,180,255,0,0,0,255,37,38,40,255,0,0,0,255,81, +81,82,255,29,31,33,255,0,0,0,255,0,0,0,255,92,92,93,255,232,232,232,255,86,86, +87,255,0,0,0,255,209,209,209,255,179,179,179,255,0,0,0,255,27,29,30,255,0,0,0, +255,84,85,86,255,12,16,19,255,0,0,1,255,0,0,0,255,127,128,128,255,255,255,255, +255,217,218,218,255,0,0,0,255,11,14,16,255,0,0,0,255,62,63,64,255,65,66,67,255, +0,0,0,255,8,12,14,255,0,0,0,255,218,218,218,255,255,255,255,255,253,253,253, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255,255, +255,255,255,255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,254,254,255,255,255,255,255,255,255,255,255,229,132,132, +255,222,69,69,255,223,86,86,255,223,82,82,255,223,82,82,255,223,83,83,255,223, +83,83,255,220,39,39,255,224,96,96,255,240,195,195,255,255,255,255,255,255,255, +255,255,255,255,255,255,253,246,246,255,236,175,175,255,222,71,71,255,221,52,52, +255,223,86,86,255,223,82,82,255,223,82,82,255,223,81,81,255,224,90,90,255,221, +51,51,255,235,170,170,255,255,255,255,255,254,253,253,255,255,255,255,255,253, +253,253,255,255,255,255,255,160,160,161,255,0,0,0,255,0,0,0,255,223,223,223,255, +255,255,255,255,255,255,255,255,249,249,249,255,127,128,128,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,19,22,25,255,28,31,34,255,0,0,0,255,0,0,0,255,250,250, +250,255,239,239,239,255,81,82,83,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,93, +94,94,255,0,0,0,255,0,0,0,255,165,165,165,255,157,157,158,255,0,0,0,255,0,0,0, +255,222,222,222,255,255,255,255,255,150,151,151,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,76,77,78,255,239,239,239,255,232,232,232,255,0,0,0,255, +0,0,0,255,170,171,171,255,255,255,255,255,150,150,151,255,0,0,0,255,0,0,0,255, +0,0,0,255,0,0,0,255,0,0,0,255,124,124,125,255,246,246,246,255,255,255,255,255, +255,255,255,255,199,200,200,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,199,199,199,255,255,255,255,255,253,253,253,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255,255,255, +255,255,255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,254,254,255,255,255,255,255,234,162,162,255, +219,0,0,255,224,93,93,255,223,86,86,255,223,81,81,255,223,82,82,255,223,83,83, +255,224,90,90,255,222,76,76,255,220,29,29,255,228,125,125,255,244,213,213,255, +241,200,200,255,225,98,98,255,220,35,35,255,223,83,83,255,223,89,89,255,223,82, +82,255,223,82,82,255,223,82,82,255,223,88,88,255,223,89,89,255,218,0,0,255,241, +200,200,255,255,255,255,255,254,253,253,255,255,255,255,255,254,254,254,255,255, +255,255,255,223,224,224,255,194,195,195,255,197,197,198,255,243,243,243,255,255, +255,255,255,253,253,253,255,255,255,255,255,255,255,255,255,204,204,205,255,156, +156,156,255,142,143,143,255,158,158,159,255,223,223,223,255,219,219,219,255,193, +193,193,255,204,205,205,255,250,250,250,255,255,255,255,255,248,248,248,255,191, +191,191,255,149,149,149,255,143,143,144,255,184,184,184,255,242,242,242,255,206, +206,206,255,191,191,192,255,225,225,225,255,223,223,223,255,194,194,194,255,197, +198,198,255,241,242,242,255,255,255,255,255,255,255,255,255,218,218,219,255,166, +166,167,255,143,144,144,255,152,152,153,255,195,195,195,255,249,249,249,255,255, +255,255,255,255,255,255,255,199,200,200,255,168,168,168,255,245,245,246,255,255, +255,255,255,255,255,255,255,217,217,218,255,164,164,164,255,142,142,143,255,157, +158,158,255,206,207,207,255,255,255,255,255,255,255,255,255,254,254,254,255,254, +254,254,255,255,255,255,255,235,235,235,255,179,179,180,255,146,147,147,255,147, +147,147,255,178,178,179,255,234,235,235,255,255,255,255,255,254,254,254,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,253,255,255,255,255,255,255,255,232,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,255, +255,255,255,252,245,245,255,232,152,152,255,221,44,44,255,222,65,65,255,224,90, +90,255,223,84,84,255,223,82,82,255,223,81,81,255,223,85,85,255,224,90,90,255, +222,64,64,255,221,47,47,255,221,45,45,255,222,73,73,255,224,90,90,255,223,83,83, +255,223,81,81,255,223,82,82,255,223,86,86,255,223,89,89,255,221,53,53,255,222, +64,64,255,237,180,180,255,255,254,254,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,254,254,254,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,254,254,254,255,255,255,255,255,254,254,254,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253, +253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,255,254, +254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,253,253,253,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,254,254,254,255,254,254,254,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254, +254,254,255,255,255,255,255,255,255,255,255,253,253,253,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253, +253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,253,255,255,255,255,255,255,255,232,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,254,254,255,255,255,255,255,255,255,255,255,245, +216,216,255,228,124,124,255,220,30,30,255,222,77,77,255,224,90,90,255,223,82,82, +255,223,82,82,255,223,81,81,255,223,86,86,255,223,88,88,255,223,88,88,255,223, +85,85,255,223,82,82,255,223,81,81,255,223,84,84,255,224,90,90,255,222,67,67, +255,221,41,41,255,231,148,148,255,249,231,231,255,255,255,255,255,255,255,255, +255,255,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,254,254,254,255,253,253,253,255,253,253,253,255,254,254,254,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,253,253,253,255,253,253,253, +255,254,254,254,255,253,253,253,255,253,253,253,255,253,253,253,255,253,253,253, +255,253,253,253,255,255,255,255,255,255,255,255,255,254,254,254,255,253,253,253, +255,254,254,254,255,254,254,254,255,253,253,253,255,254,254,254,255,253,253,253, +255,253,253,253,255,254,254,254,255,254,254,254,255,253,253,253,255,253,253,253, +255,254,254,254,255,255,255,255,255,255,255,255,255,253,253,253,255,253,253,253, +255,254,254,254,255,254,254,254,255,253,253,253,255,254,254,254,255,255,255,255, +255,255,255,255,255,253,253,253,255,253,253,253,255,254,254,254,255,255,255,255, +255,255,255,255,255,253,253,253,255,253,253,253,255,254,254,254,255,253,253,253, +255,253,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,254,254,254,255,253,253,253,255,254,254,254,255,254,254,254, +255,253,253,253,255,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +253,255,255,255,255,255,255,255,232,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,254,254,255,255,254,254,255,255,255,255,255,255,253,253,255,240,196,196, +255,224,95,95,255,220,38,38,255,223,85,85,255,223,88,88,255,223,82,82,255,223, +81,81,255,223,82,82,255,223,82,82,255,223,81,81,255,223,83,83,255,224,90,90, +255,222,78,78,255,220,30,30,255,227,120,120,255,245,214,214,255,255,255,255,255, +255,255,255,255,254,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,253,255,255,255,255,255,255,255,232, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +254,253,253,255,255,255,255,255,255,255,255,255,252,243,243,255,235,172,172,255, +222,65,65,255,221,54,54,255,223,89,89,255,223,86,86,255,223,81,81,255,223,81,81, +255,223,88,88,255,223,85,85,255,220,38,38,255,224,91,91,255,240,193,193,255,254, +252,252,255,255,255,255,255,255,254,254,255,255,253,253,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,253,255,255,255,255,255,255,255,232,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,255,254, +253,253,255,255,255,255,255,255,255,255,255,248,230,230,255,231,145,145,255,221, +41,41,255,222,68,68,255,224,90,90,255,223,89,89,255,221,56,56,255,222,63,63, +255,235,170,170,255,252,242,242,255,255,255,255,255,255,255,255,255,254,253,253, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255,255, +255,255,255,255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,254, +255,254,253,253,255,255,255,255,255,255,255,255,255,244,212,212,255,227,118,118, +255,220,37,37,255,221,47,47,255,230,142,142,255,248,228,228,255,255,255,255,255, +255,255,255,255,254,253,253,255,255,254,254,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,253,255,255,255,255,255,255,255,232, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,253,253,255,255,254,254,255,255,255,255,255,254,250,250,255,244,212,212,255, +246,220,220,255,255,255,255,255,255,255,255,255,254,253,253,255,255,254,254,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,253,255,255,255,255,255,255,255,232,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,254,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,254,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,253,255,255,255,255,255,255,255,232,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,254,253,253,255,254,253,253,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253, +255,255,255,255,255,255,255,232,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,255,255,255,255, +255,255,255,232,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,253,255,255,255,255,255,255,255,232, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,253,255,255,255,255,255,255,255,232,255,255,255,254, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,253,255,255,255,255,255,255,255,231,255,255,255,255,255,255,255,252, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253, +255,255,255,255,255,255,255,233,255,255,255,223,255,255,255,255,255,255,255,249, +255,255,255,253,255,255,255,253,255,255,255,252,255,255,255,252,255,255,255,253, +255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,252, +255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,252,255,255,255,252, +255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,252, +255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253, +255,255,255,253,255,255,255,252,255,255,255,253,255,255,255,253,255,255,255,253, +255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253, +255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253, +255,255,255,252,255,255,255,253,255,255,255,252,255,255,255,253,255,255,255,253, +255,255,255,253,255,255,255,253,255,255,255,252,255,255,255,253,255,255,255,253, +255,255,255,252,255,255,255,253,255,255,255,253,255,255,255,252,255,255,255,253, +255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,252, +255,255,255,252,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253, +255,255,255,252,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253, +255,255,255,253,255,255,255,252,255,255,255,253,255,255,255,252,255,255,255,253, +255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,252,255,255,255,253, +255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,252, +255,255,255,253,255,255,255,253,255,255,255,252,255,255,255,252,255,255,255,253, +255,255,255,252,255,255,255,252,255,255,255,253,255,255,255,253,255,255,255,253, +255,255,255,253,255,255,255,252,255,255,255,253,255,255,255,253,255,255,255,253, +255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,252, +255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,252,255,255,255,252, +255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253,255,255,255,253, +255,255,255,252,255,255,255,253,255,255,255,253,255,255,255,248,255,255,255,255, +255,255,255,194,255,255,255,62,255,255,255,242,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,230,255,255,255,45, +0,0,0,0,255,255,255,20,255,255,255,68,255,255,255,66,255,255,255,66,255,255, +255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255, +66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66, +255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255, +255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255, +255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255, +66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66, +255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255, +255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255, +255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255, +66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66, +255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255, +255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255, +255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255, +66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66, +255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255, +255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255, +255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255, +66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66, +255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255, +255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255, +255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255, +66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66,255,255,255,66, +255,255,255,66,255,255,255,13,0,0,0,0}; +static Fl_Image *image_radio_co_badge() { + static Fl_Image *image = new Fl_RGB_Image(idata_radio_co_badge, 124, 61, 4, 0); + return image; +} + +void flgui::cb_window_cfg_i(Fl_My_Double_Window*, void*) { + if(window_cfg->shown()) +{ + window_cfg->hide(); + Fl::remove_timeout(&cfg_win_pos_timer); +}; +} +void flgui::cb_window_cfg(Fl_My_Double_Window* o, void* v) { + ((flgui*)(o->user_data()))->cb_window_cfg_i(o,v); +} + +void flgui::cb_choice_cfg_act_srv_i(Fl_Choice*, void*) { + choice_cfg_act_srv_cb(); +} +void flgui::cb_choice_cfg_act_srv(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_cfg_act_srv_i(o,v); +} + +void flgui::cb_ADD_i(Fl_Button*, void*) { + button_cfg_add_srv_cb(); +} +void flgui::cb_ADD(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_ADD_i(o,v); +} + +void flgui::cb_button_cfg_edit_srv_i(Fl_Button*, void*) { + button_cfg_edit_srv_cb(); +} +void flgui::cb_button_cfg_edit_srv(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_cfg_edit_srv_i(o,v); +} + +void flgui::cb_button_cfg_del_srv_i(Fl_Button*, void*) { + button_cfg_del_srv_cb(); +} +void flgui::cb_button_cfg_del_srv(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_cfg_del_srv_i(o,v); +} + +void flgui::cb_choice_cfg_act_icy_i(Fl_Choice*, void*) { + choice_cfg_act_icy_cb(); +} +void flgui::cb_choice_cfg_act_icy(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_cfg_act_icy_i(o,v); +} + +void flgui::cb_ADD1_i(Fl_Button*, void*) { + button_cfg_add_icy_cb(); +} +void flgui::cb_ADD1(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_ADD1_i(o,v); +} + +void flgui::cb_button_cfg_edit_icy_i(Fl_Button*, void*) { + button_cfg_edit_icy_cb(); +} +void flgui::cb_button_cfg_edit_icy(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_cfg_edit_icy_i(o,v); +} + +void flgui::cb_button_cfg_del_icy_i(Fl_Button*, void*) { + button_cfg_del_icy_cb(); +} +void flgui::cb_button_cfg_del_icy(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_cfg_del_icy_i(o,v); +} + +void flgui::cb_input_log_filename_i(Fl_Input*, void*) { + input_log_filename_cb(); +} +void flgui::cb_input_log_filename(Fl_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_log_filename_i(o,v); +} + +void flgui::cb__i(Fl_Button*, void*) { + button_cfg_log_browse_cb(); +} +void flgui::cb_(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb__i(o,v); +} + +static const unsigned char idata_folder[] = +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,19,19,0, +4,4,4,0,2,2,2,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,36,36, +36,12,4,4,4,58,3,3,3,62,1,1,1,62,0,0,0,61,0,0,0,14,0,0,0,0,0,0,0,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,14,2,2,2,156,1,1,1,105,0,0,0,95,0,0,0,95, +0,0,0,89,0,0,0,180,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,5,5,5, +98,5,5,5,123,0,0,0,75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0,0,0,154,0,0,0, +111,0,0,0,113,0,0,0,113,0,0,0,113,0,0,0,113,0,0,0,118,0,0,0,81,0,0,0,0,0,0,0,5, +0,0,0,3,5,5,5,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,2,2,2,72,2,2,2,25,0,0,0,2,7, +7,7,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,15,0,0,0,15,0,0,0,15,0,0, +0,15,0,0,0,15,0,0,0,1,0,0,0,152,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,95,0,0,0,48,2,2,2,5,4,4,4,3,0,0,0,0,7,7,7,94,3,3,3,140,0,0,0, +140,0,0,0,141,0,0,0,144,0,0,0,144,0,0,0,144,0,0,0,144,0,0,0,144,0,0,0,144,3,3,3, +139,6,6,6,196,0,0,0,141,0,0,0,141,0,0,0,138,4,4,4,136,0,0,0,16,0,0,0,0,0,0,0,0, +0,0,0,96,0,0,0,46,0,0,0,2,0,0,0,0,0,0,0,78,0,0,0,110,0,0,0,0,1,1,1,7,0,0,0,7, +0,0,0,7,0,0,0,7,0,0,0,7,0,0,0,7,0,0,0,7,1,1,1,7,0,0,0,7,0,0,0,1,2,2,2,7,0,0,0, +11,0,0,0,0,0,0,0,177,1,1,1,15,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,45,0,0,0,1,0,0,0, +0,0,0,0,157,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,71,0,0,0,105,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,96,0,0,0,46,0,0,0,0,0,0,0,100,0,0,0,57,0,0,0,1,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,167,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,48,0,0, +0,14,0,0,0,125,0,0,0,12,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,0,0,0,79,0,0,0,0,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,97,0,0,0,46,0,0,0,68,0,0,0,95,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,0,11,0,0,0,127,0,0,0,18,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,99,0, +0,0,36,0,0,0,166,0,0,0,0,0,0,0,0,2,2,2,0,2,2,2,0,2,2,2,0,2,2,2,0,2,2,2,0,2,2, +2,0,2,2,2,0,2,2,2,0,2,2,2,0,2,2,2,0,1,1,1,1,1,1,1,2,0,0,0,50,0,0,0,111,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,81,10,10,10,152,0,0,0,71,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,3,0,0,0,0,0,0,0,160,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,6,6,6,91,4,4,4,196,0,0,0,13,4,4,4,23,3,3,3,20,4,4,4,20,4,4,4,20,4,4,4,20, +4,4,4,20,4,4,4,20,4,4,4,20,4,4,4,20,4,4,4,20,4,4,4,20,3,3,3,20,16,16,16,11,5, +5,5,95,0,0,0,104,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,0, +0,118,0,0,0,133,0,0,0,133,0,0,0,133,0,0,0,133,0,0,0,133,0,0,0,133,0,0,0,133,0, +0,0,133,0,0,0,133,0,0,0,133,0,0,0,133,0,0,0,133,0,0,0,133,0,0,0,135,0,0,0,113, +4,4,4,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +static Fl_Image *image_folder() { + static Fl_Image *image = new Fl_RGB_Image(idata_folder, 24, 24, 4, 0); + return image; +} + +void flgui::cb_button_cfg_import_i(Fl_Button*, void*) { + button_cfg_import_cb(); +} +void flgui::cb_button_cfg_import(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_cfg_import_i(o,v); +} + +void flgui::cb_Save_i(Fl_Button*, void*) { + cfg_write_file(NULL); +} +void flgui::cb_Save(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Save_i(o,v); +} + +void flgui::cb_Export_i(Fl_Button*, void*) { + button_cfg_export_cb(); +} +void flgui::cb_Export(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Export_i(o,v); +} + +void flgui::cb_check_start_agent_i(Fl_Check_Button*, void*) { + check_start_agent_cb(); +} +void flgui::cb_check_start_agent(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_start_agent_i(o,v); +} + +void flgui::cb_check_minimize_to_tray_i(Fl_Check_Button*, void*) { + check_minimize_to_tray_cb(); +} +void flgui::cb_check_minimize_to_tray(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_minimize_to_tray_i(o,v); +} + +void flgui::cb_Start_i(Fl_Button*, void*) { + button_start_agent_cb(); +} +void flgui::cb_Start(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Start_i(o,v); +} + +void flgui::cb_Stop_i(Fl_Button*, void*) { + button_stop_agent_cb(); +} +void flgui::cb_Stop(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Stop_i(o,v); +} + +void flgui::cb_check_update_at_startup_i(Fl_Check_Button*, void*) { + check_update_at_startup_cb(); +} +void flgui::cb_check_update_at_startup(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_update_at_startup_i(o,v); +} + +void flgui::cb_Check_i(Fl_Button*, void*) { + button_cfg_check_for_updates_cb(); +} +void flgui::cb_Check(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Check_i(o,v); +} + +void flgui::cb_Manual_i(Fl_Button*, void*) { + char uri[128]; +snprintf(uri, sizeof(uri), "https://danielnoethen.de/butt/release/%s/butt-%s_manual.html", VERSION, VERSION); +fl_open_uri(uri); +} +void flgui::cb_Manual(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Manual_i(o,v); +} + +void flgui::cb_YouTube_i(Fl_Button*, void*) { + char uri[128]; +snprintf(uri, sizeof(uri), "https://www.youtube.com/@butt.broadcaster"); +fl_open_uri(uri); +} +void flgui::cb_YouTube(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_YouTube_i(o,v); +} + +static const unsigned char idata_yt_icon[] = +{0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,125,0,0,0,210,0,0,0,247,0,0,0,255,0,0,0,255, +0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,247,0,0,0, +210,0,0,0,124,0,0,0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,0,0,0,222,0,0,0,255,0,0, +0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0, +0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255, +0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,220,0,0,0,38,0,0,0,0, +0,0,0,13,0,0,0,221,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,219,0,0,0,12,0,0,0,123,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +121,0,0,0,209,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,207,0,0,0,246,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,248,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +245,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,47,0,0,0,99,0,0,0,224,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,40,0,0,0, +0,0,0,0,5,0,0,0,94,0,0,0,222,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,102,0,0, +0,229,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0, +0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255, +0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,40,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,116,0,0,0,239,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,60, +0,0,0,215,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,60,0,0,0,179,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0, +0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255, +0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,40,0,0,0,0,0,0,0,1,0,0,0,77,0,0,0,200,0,0,0,255,0,0,0,255,0,0,0,255,0, +0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255, +0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,45,0,0,0,89,0,0,0,210,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,246,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,248,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,245,0,0,0,208,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,206,0,0,0,122,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,120,0,0,0,13,0,0,0,220,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,219,0,0,0,11,0,0,0,0,0,0,0,39, +0,0,0,221,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +220,0,0,0,38,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,124,0,0,0,208,0,0,0,246,0,0, +0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0, +0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255, +0,0,0,246,0,0,0,208,0,0,0,123,0,0,0,12,0,0,0,0,0,0,0,0}; +static Fl_Image *image_yt_icon() { + static Fl_Image *image = new Fl_RGB_Image(idata_yt_icon, 28, 20, 4, 0); + return image; +} + +void flgui::cb_Stereo_i(Fl_Menu_*, void*) { + choice_cfg_channel_stereo_cb(); +} +void flgui::cb_Stereo(Fl_Menu_* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Stereo_i(o,v); +} + +void flgui::cb_Mono_i(Fl_Menu_*, void*) { + choice_cfg_channel_mono_cb(); +} +void flgui::cb_Mono(Fl_Menu_* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Mono_i(o,v); +} + +unsigned char flgui::menu_choice_cfg_channel_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_cfg_channel[] = { + {"Stereo", 0, (Fl_Callback*)flgui::cb_Stereo, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Mono", 0, (Fl_Callback*)flgui::cb_Mono, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_cfg_samplerate_i(Fl_Choice*, void*) { + choice_cfg_samplerate_cb(); +} +void flgui::cb_choice_cfg_samplerate(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_cfg_samplerate_i(o,v); +} + +void flgui::cb_radio_cfg_ID_i(Fl_Round_Button*, void*) { + radio_cfg_ID_cb(); +} +void flgui::cb_radio_cfg_ID(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_radio_cfg_ID_i(o,v); +} + +void flgui::cb_radio_cfg_name_i(Fl_Round_Button*, void*) { + radio_cfg_name_cb(); +} +void flgui::cb_radio_cfg_name(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_radio_cfg_name_i(o,v); +} + +void flgui::cb_button_cfg_rescan_devices_i(Fl_Button*, void*) { + button_cfg_rescan_devices_cb(); +} +void flgui::cb_button_cfg_rescan_devices(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_cfg_rescan_devices_i(o,v); +} + +void flgui::cb_choice_cfg_dev_i(Fl_Choice*, void*) { + choice_cfg_dev_cb(); +} +void flgui::cb_choice_cfg_dev(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_cfg_dev_i(o,v); +} + +void flgui::cb_choice_cfg_left_channel_i(Fl_Choice*, void*) { + choice_cfg_left_channel_cb(); +} +void flgui::cb_choice_cfg_left_channel(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_cfg_left_channel_i(o,v); +} + +void flgui::cb_choice_cfg_right_channel_i(Fl_Choice*, void*) { + choice_cfg_right_channel_cb(); +} +void flgui::cb_choice_cfg_right_channel(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_cfg_right_channel_i(o,v); +} + +void flgui::cb_choice_cfg_dev2_i(Fl_Choice*, void*) { + choice_cfg_dev2_cb(); +} +void flgui::cb_choice_cfg_dev2(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_cfg_dev2_i(o,v); +} + +void flgui::cb_choice_cfg_left_channel2_i(Fl_Choice*, void*) { + choice_cfg_left_channel2_cb(); +} +void flgui::cb_choice_cfg_left_channel2(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_cfg_left_channel2_i(o,v); +} + +void flgui::cb_choice_cfg_right_channel2_i(Fl_Choice*, void*) { + choice_cfg_right_channel2_cb(); +} +void flgui::cb_choice_cfg_right_channel2(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_cfg_right_channel2_i(o,v); +} + +void flgui::cb_MP3_i(Fl_Menu_*, void*) { + choice_cfg_codec_mp3_cb(); +} +void flgui::cb_MP3(Fl_Menu_* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_MP3_i(o,v); +} + +void flgui::cb_OGG_i(Fl_Menu_*, void*) { + choice_cfg_codec_ogg_cb(); +} +void flgui::cb_OGG(Fl_Menu_* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_OGG_i(o,v); +} + +void flgui::cb_OPUS_i(Fl_Menu_*, void*) { + choice_cfg_codec_opus_cb(); +} +void flgui::cb_OPUS(Fl_Menu_* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_OPUS_i(o,v); +} + +void flgui::cb_menu_item_cfg_aac_i(Fl_Menu_*, void*) { + choice_cfg_codec_aac_cb(); +} +void flgui::cb_menu_item_cfg_aac(Fl_Menu_* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_menu_item_cfg_aac_i(o,v); +} + +void flgui::cb_FLAC_i(Fl_Menu_*, void*) { + choice_cfg_codec_flac_cb(); +} +void flgui::cb_FLAC(Fl_Menu_* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_FLAC_i(o,v); +} + +unsigned char flgui::menu_choice_cfg_codec_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_cfg_codec[] = { + {"MP3", 0, (Fl_Callback*)flgui::cb_MP3, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"OGG/VORBIS", 0, (Fl_Callback*)flgui::cb_OGG, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"OPUS", 0, (Fl_Callback*)flgui::cb_OPUS, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"AAC+", 0, (Fl_Callback*)flgui::cb_menu_item_cfg_aac, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"FLAC", 0, (Fl_Callback*)flgui::cb_FLAC, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; +Fl_Menu_Item* flgui::menu_item_cfg_aac = flgui::menu_choice_cfg_codec + 3; + +void flgui::cb_choice_cfg_bitrate_i(Fl_Choice*, void*) { + choice_cfg_bitrate_cb(); +} +void flgui::cb_choice_cfg_bitrate(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_cfg_bitrate_i(o,v); +} + +void flgui::cb_1_i(Fl_Button*, void*) { + button_stream_codec_settings_cb(); +} +void flgui::cb_1(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_1_i(o,v); +} + +static const unsigned char idata_settings[] = +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +112,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,110,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,161,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,159,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,42,0,0,0,223,0,0,0,255,0,0,0,55,0,0,0,55,0,0,0,255,0,0,0,223,0,0,0,42, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,0,0,193,0,0,0,174,0,0,0,86,0,0,0,148,0,0,0,254,0,0,0,255, +0,0,0,251,0,0,0,9,0,0,0,9,0,0,0,251,0,0,0,255,0,0,0,253,0,0,0,148,0,0,0,86,0, +0,0,174,0,0,0,193,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,95,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,248,0,0,0,146,0,0,0,41,0,0, +0,0,0,0,0,0,0,0,0,41,0,0,0,147,0,0,0,248,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0, +255,0,0,0,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,230,0,0,0, +255,0,0,0,155,0,0,0,199,0,0,0,219,0,0,0,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,46,0,0,0,219,0,0,0,199,0,0,0,155,0,0,0,255,0,0,0,230,0,0,0, +13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,134,0,0,0,255,0,0,0,230,0,0,0,5,0,0,0, +0,0,0,0,3,0,0,0,0,0,0,0,38,0,0,0,174,0,0,0,242,0,0,0,242,0,0,0,173,0,0,0,37,0, +0,0,0,0,0,0,2,0,0,0,0,0,0,0,5,0,0,0,231,0,0,0,255,0,0,0,135,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,81,0,0,0,245,0,0,0,255,0,0,0,183,0,0,0,12,0,0,0,0,0,0,0, +38,0,0,0,238,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,236,0,0,0,27,0,0,0, +0,0,0,0,12,0,0,0,184,0,0,0,255,0,0,0,245,0,0,0,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,54,0,0,0,246,0,0,0,255,0,0,0,44,0,0,0,0,0,0,0,174,0,0,0,255, +0,0,0,179,0,0,0,27,0,0,0,28,0,0,0,181,0,0,0,255,0,0,0,169,0,0,0,0,0,0,0,44,0, +0,0,255,0,0,0,246,0,0,0,54,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,244,0,0,0,255,0,0,0,11,0,0,0,0,0,0,0,242,0,0,0,255,0,0,0,27,0,0,0, +0,0,0,0,0,0,0,0,29,0,0,0,255,0,0,0,240,0,0,0,0,0,0,0,12,0,0,0,255,0,0,0,244,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,244,0,0,0, +255,0,0,0,11,0,0,0,0,0,0,0,241,0,0,0,255,0,0,0,28,0,0,0,0,0,0,0,0,0,0,0,29,0,0, +0,255,0,0,0,240,0,0,0,0,0,0,0,12,0,0,0,255,0,0,0,244,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,54,0,0,0,246,0,0,0,255,0,0,0,44,0,0,0,0, +0,0,0,173,0,0,0,255,0,0,0,181,0,0,0,28,0,0,0,29,0,0,0,182,0,0,0,255,0,0,0,171, +0,0,0,0,0,0,0,45,0,0,0,255,0,0,0,246,0,0,0,54,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,80,0,0,0,245,0,0,0,255,0,0,0,183,0,0,0,12,0,0,0,0,0,0,0,37,0,0, +0,236,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,237,0,0,0,36,0,0,0,0,0,0, +0,12,0,0,0,184,0,0,0,255,0,0,0,245,0,0,0,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,135,0,0,0,255,0,0,0,230,0,0,0,5,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,27,0,0,0, +169,0,0,0,241,0,0,0,241,0,0,0,171,0,0,0,36,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,5,0,0, +0,231,0,0,0,255,0,0,0,135,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,230, +0,0,0,255,0,0,0,155,0,0,0,199,0,0,0,219,0,0,0,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,47,0,0,0,219,0,0,0,198,0,0,0,156,0,0,0,255,0,0,0, +230,0,0,0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,95,0,0,0,255,0,0,0, +255,0,0,0,255,0,0,0,255,0,0,0,248,0,0,0,147,0,0,0,41,0,0,0,0,0,0,0,0,0,0,0,42,0, +0,0,148,0,0,0,249,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,95,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,192,0,0,0,173,0,0,0,86,0, +0,0,147,0,0,0,253,0,0,0,255,0,0,0,251,0,0,0,9,0,0,0,10,0,0,0,251,0,0,0,255,0, +0,0,253,0,0,0,147,0,0,0,86,0,0,0,173,0,0,0,192,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,0, +0,0,223,0,0,0,255,0,0,0,55,0,0,0,56,0,0,0,255,0,0,0,223,0,0,0,41,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,160,0,0,0,255,0,0,0,255,0, +0,0,255,0,0,0,255,0,0,0,158,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,111,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,109,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +static Fl_Image *image_settings() { + static Fl_Image *image = new Fl_RGB_Image(idata_settings, 24, 24, 4, 0); + return image; +} + +void flgui::cb_MP31_i(Fl_Menu_*, void*) { + choice_rec_codec_mp3_cb(); +} +void flgui::cb_MP31(Fl_Menu_* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_MP31_i(o,v); +} + +void flgui::cb_OGG1_i(Fl_Menu_*, void*) { + choice_rec_codec_ogg_cb(); +} +void flgui::cb_OGG1(Fl_Menu_* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_OGG1_i(o,v); +} + +void flgui::cb_OPUS1_i(Fl_Menu_*, void*) { + choice_rec_codec_opus_cb(); +} +void flgui::cb_OPUS1(Fl_Menu_* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_OPUS1_i(o,v); +} + +void flgui::cb_menu_item_rec_aac_i(Fl_Menu_*, void*) { + choice_rec_codec_aac_cb(); +} +void flgui::cb_menu_item_rec_aac(Fl_Menu_* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_menu_item_rec_aac_i(o,v); +} + +void flgui::cb_FLAC1_i(Fl_Menu_*, void*) { + choice_rec_codec_flac_cb(); +} +void flgui::cb_FLAC1(Fl_Menu_* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_FLAC1_i(o,v); +} + +void flgui::cb_WAV_i(Fl_Menu_*, void*) { + choice_rec_codec_wav_cb(); +} +void flgui::cb_WAV(Fl_Menu_* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_WAV_i(o,v); +} + +unsigned char flgui::menu_choice_rec_codec_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_codec[] = { + {"MP3", 0, (Fl_Callback*)flgui::cb_MP31, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"OGG/VORBIS", 0, (Fl_Callback*)flgui::cb_OGG1, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"OPUS", 0, (Fl_Callback*)flgui::cb_OPUS1, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"AAC+", 0, (Fl_Callback*)flgui::cb_menu_item_rec_aac, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"FLAC", 0, (Fl_Callback*)flgui::cb_FLAC1, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"WAV", 0, (Fl_Callback*)flgui::cb_WAV, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; +Fl_Menu_Item* flgui::menu_item_rec_aac = flgui::menu_choice_rec_codec + 3; + +void flgui::cb_choice_rec_bitrate_i(Fl_Choice*, void*) { + choice_rec_bitrate_cb(); +} +void flgui::cb_choice_rec_bitrate(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_rec_bitrate_i(o,v); +} + +void flgui::cb_2_i(Fl_Button*, void*) { + button_rec_codec_settings_cb(); +} +void flgui::cb_2(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_2_i(o,v); +} + +void flgui::cb_button_advanced_i(Fl_Button*, void*) { + static int show_advanced = 0; +if (!show_advanced) +{ + window_cfg->size(window_cfg->w(), 450); + show_advanced = 1; + fl_g->button_advanced->label("Standard..."); +} +else +{ + window_cfg->size(window_cfg->w(), 380); + show_advanced = 0; + fl_g->button_advanced->label("Advanced..."); + +}; +} +void flgui::cb_button_advanced(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_button_advanced_i(o,v); +} + +void flgui::cb_input_cfg_buffer_i(Fl_Value_Input*, void*) { + input_cfg_buffer_cb(1); +} +void flgui::cb_input_cfg_buffer(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_input_cfg_buffer_i(o,v); +} + +void flgui::cb_choice_cfg_resample_mode_i(Fl_Choice*, void*) { + choice_cfg_resample_mode_cb(); +} +void flgui::cb_choice_cfg_resample_mode(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_cfg_resample_mode_i(o,v); +} + +unsigned char flgui::menu_choice_cfg_resample_mode_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_cfg_resample_mode[] = { + {"SINC_BEST", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"SINC_MEDIUM", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"SINC_FASTEST", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"ZERO_ORDER_HOLD", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"LINEAR", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_input_cfg_present_level_i(Fl_Value_Input*, void*) { + input_cfg_present_level_cb(); +} +void flgui::cb_input_cfg_present_level(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_cfg_present_level_i(o,v); +} + +void flgui::cb_input_cfg_absent_level_i(Fl_Value_Input*, void*) { + input_cfg_absent_level_cb(); +} +void flgui::cb_input_cfg_absent_level(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_cfg_absent_level_i(o,v); +} + +void flgui::cb_input_cfg_song_file_i(Fl_Input*, void*) { + input_cfg_song_file_cb(); +} +void flgui::cb_input_cfg_song_file(Fl_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_cfg_song_file_i(o,v); +} + +void flgui::cb_button_songfile_browse_i(Fl_Button*, void*) { + button_cfg_browse_songfile_cb(); +} +void flgui::cb_button_songfile_browse(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_songfile_browse_i(o,v); +} + +void flgui::cb_check_song_update_active_i(Fl_Check_Button*, void*) { + check_song_update_active_cb(); +} +void flgui::cb_check_song_update_active(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_song_update_active_i(o,v); +} + +void flgui::cb_check_read_last_line_i(Fl_Check_Button*, void*) { + check_read_last_line_cb(); +} +void flgui::cb_check_read_last_line(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_read_last_line_i(o,v); +} + +void flgui::cb_choice_cfg_app_i(Fl_Choice*, void*) { + choice_cfg_app_cb(); +} +void flgui::cb_choice_cfg_app(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_cfg_app_i(o,v); +} + +void flgui::cb_radio_cfg_title_artist_i(Fl_Round_Button*, void*) { + radio_cfg_title_artist_cb(); +} +void flgui::cb_radio_cfg_title_artist(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_radio_cfg_title_artist_i(o,v); +} + +void flgui::cb_radio_cfg_artist_title_i(Fl_Round_Button*, void*) { + radio_cfg_artist_title_cb(); +} +void flgui::cb_radio_cfg_artist_title(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_radio_cfg_artist_title_i(o,v); +} + +void flgui::cb_check_cfg_use_app_i(Fl_Check_Button*, void*) { + check_cfg_use_app_cb(); +} +void flgui::cb_check_cfg_use_app(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_cfg_use_app_i(o,v); +} + +void flgui::cb_input_cfg_song_i(Fl_Input*, void*) { + input_cfg_song_cb(); +} +void flgui::cb_input_cfg_song(Fl_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_cfg_song_i(o,v); +} + +void flgui::cb_button_cfg_song_go_i(Fl_Button*, void*) { + button_cfg_song_go_cb(); +} +void flgui::cb_button_cfg_song_go(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_cfg_song_go_i(o,v); +} + +void flgui::cb_choice_cfg_song_delay_i(Fl_Choice*, void*) { + choice_cfg_song_delay_cb(); +} +void flgui::cb_choice_cfg_song_delay(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_cfg_song_delay_i(o,v); +} + +void flgui::cb_input_cfg_song_prefix_i(Fl_Input*, void*) { + input_cfg_song_prefix_cb(); +} +void flgui::cb_input_cfg_song_prefix(Fl_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_cfg_song_prefix_i(o,v); +} + +void flgui::cb_input_cfg_song_suffix_i(Fl_Input*, void*) { + input_cfg_song_suffix_cb(); +} +void flgui::cb_input_cfg_song_suffix(Fl_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_cfg_song_suffix_i(o,v); +} + +void flgui::cb_check_stream_signal_i(Fl_Check_Button*, void*) { + check_stream_signal_cb(); +} +void flgui::cb_check_stream_signal(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_stream_signal_i(o,v); +} + +void flgui::cb_input_cfg_signal_i(Fl_Value_Input*, void*) { + input_cfg_signal_cb(); +} +void flgui::cb_input_cfg_signal(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_cfg_signal_i(o,v); +} + +void flgui::cb_check_stream_silence_i(Fl_Check_Button*, void*) { + check_stream_silence_cb(); +} +void flgui::cb_check_stream_silence(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_stream_silence_i(o,v); +} + +void flgui::cb_input_cfg_silence_i(Fl_Value_Input*, void*) { + input_cfg_silence_cb(); +} +void flgui::cb_input_cfg_silence(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_cfg_silence_i(o,v); +} + +void flgui::cb_check_cfg_connect_i(Fl_Check_Button*, void*) { + check_cfg_connect_cb(); +} +void flgui::cb_check_cfg_connect(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_cfg_connect_i(o,v); +} + +void flgui::cb_check_cfg_force_reconnecting_i(Fl_Check_Button*, void*) { + check_cfg_force_reconnecting_cb(); +} +void flgui::cb_check_cfg_force_reconnecting(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_cfg_force_reconnecting_i(o,v); +} + +void flgui::cb_input_cfg_reconnect_delay_i(Fl_Value_Input*, void*) { + input_cfg_reconnect_delay_cb(); +} +void flgui::cb_input_cfg_reconnect_delay(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_cfg_reconnect_delay_i(o,v); +} + +void flgui::cb_input_cfg_song_url_i(Fl_Input*, void*) { + input_cfg_song_url_cb(); +} +void flgui::cb_input_cfg_song_url(Fl_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_cfg_song_url_i(o,v); +} + +void flgui::cb_input_cfg_url_update_song_interval_i(Fl_Value_Input*, void*) { + input_cfg_url_update_song_interval_cb(); +} +void flgui::cb_input_cfg_url_update_song_interval(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_cfg_url_update_song_interval_i(o,v); +} + +void flgui::cb_check_cfg_update_from_url_i(Fl_Check_Button*, void*) { + check_cfg_update_from_url_cb(); +} +void flgui::cb_check_cfg_update_from_url(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_cfg_update_from_url_i(o,v); +} + +void flgui::cb_input_rec_filename_i(Fl_Input*, void*) { + input_rec_filename_cb(); +} +void flgui::cb_input_rec_filename(Fl_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_input_rec_filename_i(o,v); +} + +void flgui::cb_input_rec_folder_i(Fl_Input*, void*) { + input_rec_folder_cb(); +} +void flgui::cb_input_rec_folder(Fl_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_input_rec_folder_i(o,v); +} + +void flgui::cb_button_rec_browse_i(Fl_Button*, void*) { + button_rec_browse_cb(); +} +void flgui::cb_button_rec_browse(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_button_rec_browse_i(o,v); +} + +void flgui::cb_input_rec_split_time_i(Fl_Value_Input*, void*) { + input_rec_split_time_cb(); +} +void flgui::cb_input_rec_split_time(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_rec_split_time_i(o,v); +} + +void flgui::cb_check_sync_to_full_hour_i(Fl_Check_Button*, void*) { + check_sync_to_full_hour_cb(); +} +void flgui::cb_check_sync_to_full_hour(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_sync_to_full_hour_i(o,v); +} + +void flgui::cb_Split_i(Fl_Button*, void*) { + button_rec_split_now_cb(); +} +void flgui::cb_Split(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Split_i(o,v); +} + +void flgui::cb_check_cfg_auto_start_rec_i(Fl_Check_Button*, void*) { + check_cfg_auto_start_rec_cb(); +} +void flgui::cb_check_cfg_auto_start_rec(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_cfg_auto_start_rec_i(o,v); +} + +void flgui::cb_check_cfg_auto_stop_rec_i(Fl_Check_Button*, void*) { + check_cfg_auto_stop_rec_cb(); +} +void flgui::cb_check_cfg_auto_stop_rec(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_cfg_auto_stop_rec_i(o,v); +} + +void flgui::cb_check_cfg_rec_after_launch_i(Fl_Check_Button*, void*) { + check_cfg_rec_after_launch_cb(); +} +void flgui::cb_check_cfg_rec_after_launch(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_cfg_rec_after_launch_i(o,v); +} + +void flgui::cb_check_rec_signal_i(Fl_Check_Button*, void*) { + check_rec_signal_cb(); +} +void flgui::cb_check_rec_signal(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_rec_signal_i(o,v); +} + +void flgui::cb_input_rec_signal_i(Fl_Value_Input*, void*) { + input_rec_signal_cb(); +} +void flgui::cb_input_rec_signal(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_rec_signal_i(o,v); +} + +void flgui::cb_check_rec_silence_i(Fl_Check_Button*, void*) { + check_rec_silence_cb(); +} +void flgui::cb_check_rec_silence(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_rec_silence_i(o,v); +} + +void flgui::cb_input_rec_silence_i(Fl_Value_Input*, void*) { + input_rec_silence_cb(); +} +void flgui::cb_input_rec_silence(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_rec_silence_i(o,v); +} + +void flgui::cb_check_cfg_overwrite_existing_files_i(Fl_Check_Button*, void*) { + check_cfg_overwrite_existing_files_cb(); +} +void flgui::cb_check_cfg_overwrite_existing_files(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_cfg_overwrite_existing_files_i(o,v); +} + +void flgui::cb_Reset_i(Fl_Button*, void*) { + button_eq_reset_cb(); +} +void flgui::cb_Reset(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_Reset_i(o,v); +} + +void flgui::cb_check_stream_eq_i(Fl_Check_Button*, void*) { + check_stream_eq_cb(); +} +void flgui::cb_check_stream_eq(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_stream_eq_i(o,v); +} + +void flgui::cb_check_rec_eq_i(Fl_Check_Button*, void*) { + check_rec_eq_cb(); +} +void flgui::cb_check_rec_eq(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_rec_eq_i(o,v); +} + +void flgui::cb_choice_eq_preset_i(Fl_Choice*, void*) { + choice_eq_preset_cb(); +} +void flgui::cb_choice_eq_preset(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_eq_preset_i(o,v); +} + +unsigned char flgui::menu_choice_eq_preset_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_eq_preset[] = { + {"Manual", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Acoustic", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Bass Booster", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Bass Reducer", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Classical", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Dance", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Deep", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Electronic", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Hip-Hop", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Jazz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Latin", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Loudness", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Lounge", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Piano", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"RnB", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Rock", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Speech", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Treble Booster", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Treble Reducer", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Vocal Booster", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_equalizerSlider1_i(Fl_My_Value_Slider* o, void*) { + slider_equalizer1_cb(o->value()); +} +void flgui::cb_equalizerSlider1(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_equalizerSlider1_i(o,v); +} + +void flgui::cb_equalizerSlider2_i(Fl_My_Value_Slider* o, void*) { + slider_equalizer2_cb(o->value()); +} +void flgui::cb_equalizerSlider2(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_equalizerSlider2_i(o,v); +} + +void flgui::cb_equalizerSlider3_i(Fl_My_Value_Slider* o, void*) { + slider_equalizer3_cb(o->value()); +} +void flgui::cb_equalizerSlider3(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_equalizerSlider3_i(o,v); +} + +void flgui::cb_equalizerSlider4_i(Fl_My_Value_Slider* o, void*) { + slider_equalizer4_cb(o->value()); +} +void flgui::cb_equalizerSlider4(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_equalizerSlider4_i(o,v); +} + +void flgui::cb_equalizerSlider5_i(Fl_My_Value_Slider* o, void*) { + slider_equalizer5_cb(o->value()); +} +void flgui::cb_equalizerSlider5(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_equalizerSlider5_i(o,v); +} + +void flgui::cb_equalizerSlider6_i(Fl_My_Value_Slider* o, void*) { + slider_equalizer6_cb(o->value()); +} +void flgui::cb_equalizerSlider6(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_equalizerSlider6_i(o,v); +} + +void flgui::cb_equalizerSlider7_i(Fl_My_Value_Slider* o, void*) { + slider_equalizer7_cb(o->value()); +} +void flgui::cb_equalizerSlider7(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_equalizerSlider7_i(o,v); +} + +void flgui::cb_equalizerSlider8_i(Fl_My_Value_Slider* o, void*) { + slider_equalizer8_cb(o->value()); +} +void flgui::cb_equalizerSlider8(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_equalizerSlider8_i(o,v); +} + +void flgui::cb_equalizerSlider9_i(Fl_My_Value_Slider* o, void*) { + slider_equalizer9_cb(o->value()); +} +void flgui::cb_equalizerSlider9(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_equalizerSlider9_i(o,v); +} + +void flgui::cb_equalizerSlider10_i(Fl_My_Value_Slider* o, void*) { + slider_equalizer10_cb(o->value()); +} +void flgui::cb_equalizerSlider10(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_equalizerSlider10_i(o,v); +} + +void flgui::cb_Reset1_i(Fl_Button*, void*) { + button_drc_reset_cb(); +} +void flgui::cb_Reset1(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_Reset1_i(o,v); +} + +void flgui::cb_check_stream_drc_i(Fl_Check_Button*, void*) { + check_stream_drc_cb(); +} +void flgui::cb_check_stream_drc(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_stream_drc_i(o,v); +} + +void flgui::cb_check_rec_drc_i(Fl_Check_Button*, void*) { + check_rec_drc_cb(); +} +void flgui::cb_check_rec_drc(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_rec_drc_i(o,v); +} + +void flgui::cb_check_aggressive_mode_i(Fl_Check_Button*, void*) { + check_aggressive_mode_cb(); +} +void flgui::cb_check_aggressive_mode(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_aggressive_mode_i(o,v); +} + +void flgui::cb_thresholdSlider_i(Fl_My_Value_Slider* o, void*) { + slider_threshold_cb(o->value()); +} +void flgui::cb_thresholdSlider(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_thresholdSlider_i(o,v); +} + +void flgui::cb_ratioSlider_i(Fl_My_Value_Slider* o, void*) { + slider_ratio_cb(o->value()); +} +void flgui::cb_ratioSlider(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_ratioSlider_i(o,v); +} + +void flgui::cb_attackSlider_i(Fl_My_Value_Slider* o, void*) { + slider_attack_cb(o->value()); +} +void flgui::cb_attackSlider(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_attackSlider_i(o,v); +} + +void flgui::cb_releaseSlider_i(Fl_My_Value_Slider* o, void*) { + slider_release_cb(o->value()); +} +void flgui::cb_releaseSlider(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_releaseSlider_i(o,v); +} + +void flgui::cb_makeupSlider_i(Fl_My_Value_Slider* o, void*) { + slider_makeup_cb(o->value()); +} +void flgui::cb_makeupSlider(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_makeupSlider_i(o,v); +} + +void flgui::cb_choice_midi_dev_i(Fl_Choice*, void*) { + choice_midi_dev_cb(); +} +void flgui::cb_choice_midi_dev(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_midi_dev_i(o,v); +} + +void flgui::cb_button_midi_rescan_devices_i(Fl_Button*, void*) { + button_midi_rescan_devices_cb(); +} +void flgui::cb_button_midi_rescan_devices(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_button_midi_rescan_devices_i(o,v); +} + +void flgui::cb_browser_midi_command_i(Fl_Browser*, void*) { + browser_midi_command_cb(); +} +void flgui::cb_browser_midi_command(Fl_Browser* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_browser_midi_command_i(o,v); +} + +void flgui::cb_check_midi_command_enable_i(Fl_Check_Button*, void*) { + check_midi_command_enable_cb(); +} +void flgui::cb_check_midi_command_enable(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_check_midi_command_enable_i(o,v); +} + +void flgui::cb_choice_midi_channel_i(Fl_Choice*, void*) { + choice_midi_channel_cb(); +} +void flgui::cb_choice_midi_channel(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_midi_channel_i(o,v); +} + +unsigned char flgui::menu_choice_midi_channel_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_midi_channel[] = { + {"Any", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"1", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"2", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"3", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"4", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"5", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"6", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"7", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"8", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"9", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"10", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"11", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"12", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"13", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"14", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"15", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"16", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_input_midi_msg_num_i(Fl_Value_Input*, void*) { + input_midi_msg_num_cb(); +} +void flgui::cb_input_midi_msg_num(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_midi_msg_num_i(o,v); +} + +void flgui::cb_button_midi_learn_i(Fl_Button*, void*) { + button_midi_learn_cb(); +} +void flgui::cb_button_midi_learn(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_midi_learn_i(o,v); +} + +void flgui::cb_choice_midi_cc_mode_i(Fl_Choice*, void*) { + choice_midi_cc_mode_cb(); +} +void flgui::cb_choice_midi_cc_mode(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_midi_cc_mode_i(o,v); +} + +unsigned char flgui::menu_choice_midi_cc_mode_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_midi_cc_mode[] = { + {"Absolute", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Relative (Twos Complement)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Relative (Binary Offset)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Relative (Sign Magnitude)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_check_midi_soft_takeover_i(Fl_Check_Button*, void*) { + check_midi_soft_takeover_cb(); +} +void flgui::cb_check_midi_soft_takeover(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_midi_soft_takeover_i(o,v); +} + +void flgui::cb_input_tls_cert_file_i(Fl_Input*, void*) { + input_tls_cert_file_cb(); +} +void flgui::cb_input_tls_cert_file(Fl_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_tls_cert_file_i(o,v); +} + +void flgui::cb_button_tls_browse_file_i(Fl_Button*, void*) { + button_tls_browse_file_cb(); +} +void flgui::cb_button_tls_browse_file(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_tls_browse_file_i(o,v); +} + +void flgui::cb_input_tls_cert_dir_i(Fl_Input*, void*) { + input_tls_cert_dir_cb(); +} +void flgui::cb_input_tls_cert_dir(Fl_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_tls_cert_dir_i(o,v); +} + +void flgui::cb_button_tls_browse_dir_i(Fl_Button*, void*) { + button_tls_browse_dir_cb(); +} +void flgui::cb_button_tls_browse_dir(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_tls_browse_dir_i(o,v); +} + +void flgui::cb_choice_gui_language_i(Fl_Choice*, void*) { + choice_gui_language_cb(); +} +void flgui::cb_choice_gui_language(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_gui_language_i(o,v); +} + +unsigned char flgui::menu_choice_gui_language_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_gui_language[] = { + {"System", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"\330\247\331\204\330\271\330\261\330\250", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Deutsch", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"English", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Espa\303\261ol", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Fran\303\247""ais", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Nederlands", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Portugu\303\252s Brasileiro", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_button_gui_text_color_i(Fl_Button*, void*) { + button_gui_text_color_cb(); +} +void flgui::cb_button_gui_text_color(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_gui_text_color_i(o,v); +} + +void flgui::cb_button_gui_bg_color_i(Fl_Button*, void*) { + button_gui_bg_color_cb(); +} +void flgui::cb_button_gui_bg_color(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_gui_bg_color_i(o,v); +} + +void flgui::cb_radio_gui_vu_gradient_i(Fl_Round_Button*, void*) { + radio_gui_vu_gradient_cb(); +} +void flgui::cb_radio_gui_vu_gradient(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_radio_gui_vu_gradient_i(o,v); +} + +void flgui::cb_radio_gui_vu_solid_i(Fl_Round_Button*, void*) { + radio_gui_vu_solid_cb(); +} +void flgui::cb_radio_gui_vu_solid(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_radio_gui_vu_solid_i(o,v); +} + +void flgui::cb_check_gui_always_show_vu_tabs_i(Fl_Check_Button*, void*) { + check_gui_always_show_vu_tabs_cb(); +} +void flgui::cb_check_gui_always_show_vu_tabs(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_gui_always_show_vu_tabs_i(o,v); +} + +void flgui::cb_button_gui_vu_low_color_i(Fl_Button*, void*) { + button_gui_vu_low_color_cb(); +} +void flgui::cb_button_gui_vu_low_color(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_gui_vu_low_color_i(o,v); +} + +void flgui::cb_button_gui_vu_mid_color_i(Fl_Button*, void*) { + button_gui_vu_mid_color_cb(); +} +void flgui::cb_button_gui_vu_mid_color(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_gui_vu_mid_color_i(o,v); +} + +void flgui::cb_button_gui_vu_high_color_i(Fl_Button*, void*) { + button_gui_vu_high_color_cb(); +} +void flgui::cb_button_gui_vu_high_color(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_button_gui_vu_high_color_i(o,v); +} + +void flgui::cb_input_gui_vu_mid_range_start_i(Fl_Value_Input*, void*) { + input_gui_vu_mid_range_start_cb(); +} +void flgui::cb_input_gui_vu_mid_range_start(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_gui_vu_mid_range_start_i(o,v); +} + +void flgui::cb_input_gui_vu_high_range_start_i(Fl_Value_Input*, void*) { + input_gui_vu_high_range_start_cb(); +} +void flgui::cb_input_gui_vu_high_range_start(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_gui_vu_high_range_start_i(o,v); +} + +void flgui::cb_check_gui_attach_i(Fl_Check_Button*, void*) { + check_gui_attach_cb(); +} +void flgui::cb_check_gui_attach(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_gui_attach_i(o,v); +} + +void flgui::cb_check_gui_ontop_i(Fl_Check_Button*, void*) { + check_gui_ontop_cb(); +} +void flgui::cb_check_gui_ontop(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_gui_ontop_i(o,v); +} + +void flgui::cb_check_gui_remember_pos_i(Fl_Check_Button*, void*) { + check_gui_remember_pos_cb(); +} +void flgui::cb_check_gui_remember_pos(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_gui_remember_pos_i(o,v); +} + +void flgui::cb_check_gui_hide_log_window_i(Fl_Check_Button*, void*) { + check_gui_hide_log_window_cb(); +} +void flgui::cb_check_gui_hide_log_window(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_gui_hide_log_window_i(o,v); +} + +void flgui::cb_check_gui_lcd_auto_i(Fl_Check_Button*, void*) { + check_gui_lcd_auto_cb(); +} +void flgui::cb_check_gui_lcd_auto(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_gui_lcd_auto_i(o,v); +} + +void flgui::cb_check_gui_start_minimized_i(Fl_Check_Button*, void*) { + check_gui_start_minimized_cb(); +} +void flgui::cb_check_gui_start_minimized(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_gui_start_minimized_i(o,v); +} + +void flgui::cb_check_gui_disable_gain_slider_i(Fl_Check_Button*, void*) { + check_gui_disable_gain_slider_cb(); +} +void flgui::cb_check_gui_disable_gain_slider(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_gui_disable_gain_slider_i(o,v); +} + +void flgui::cb_check_gui_show_listeners_i(Fl_Check_Button*, void*) { + check_gui_show_listeners_cb(); +} +void flgui::cb_check_gui_show_listeners(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_check_gui_show_listeners_i(o,v); +} + +void flgui::cb_input_gui_listeners_update_rate_i(Fl_Value_Input*, void*) { + input_gui_listeners_update_rate_cb(); +} +void flgui::cb_input_gui_listeners_update_rate(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_input_gui_listeners_update_rate_i(o,v); +} + +void flgui::cb_input_gui_window_title_i(Fl_Input*, void*) { + input_gui_window_title_cb(); +} +void flgui::cb_input_gui_window_title(Fl_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_gui_window_title_i(o,v); +} + +void flgui::cb_Donate_i(Fl_Button*, void*) { + fl_open_uri("https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=LTRSQNTWN4L6L&source=url"); +} +void flgui::cb_Donate(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Donate_i(o,v); +} + +void flgui::cb_Become_i(Fl_Button*, void*) { + fl_open_uri("https://www.patreon.com/butt_broadcast"); +} +void flgui::cb_Become(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Become_i(o,v); +} + +void flgui::cb_Apple_i(Fl_Button*, void*) { + fl_open_uri("https://donorbox.org/butt"); +} +void flgui::cb_Apple(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Apple_i(o,v); +} + +void flgui::cb_Bitcoin_i(Fl_Button*, void*) { + this->window_donate_crypto->position(this->window_cfg->x(), this->window_cfg->y()); +this->window_donate_crypto->show(); +} +void flgui::cb_Bitcoin(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_Bitcoin_i(o,v); +} + +void flgui::cb_button_cfg_show_pw_i(Fl_Button*, void*) { + button_add_srv_show_pwd_cb(); +} +void flgui::cb_button_cfg_show_pw(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_button_cfg_show_pw_i(o,v); +} + +void flgui::cb_radio_add_srv_shoutcast_i(Fl_Round_Button*, void*) { + radio_add_srv_shoutcast_cb(); +} +void flgui::cb_radio_add_srv_shoutcast(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->user_data()))->cb_radio_add_srv_shoutcast_i(o,v); +} + +void flgui::cb_radio_add_srv_icecast_i(Fl_Round_Button*, void*) { + radio_add_srv_icecast_cb(); +} +void flgui::cb_radio_add_srv_icecast(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->user_data()))->cb_radio_add_srv_icecast_i(o,v); +} + +void flgui::cb_radio_add_srv_webrtc_i(Fl_Round_Button*, void*) { + radio_add_srv_webrtc_cb(); +} +void flgui::cb_radio_add_srv_webrtc(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->user_data()))->cb_radio_add_srv_webrtc_i(o,v); +} + +void flgui::cb_radio_add_srv_radioco_i(Fl_Round_Button*, void*) { + radio_add_srv_radioco_cb(); +} +void flgui::cb_radio_add_srv_radioco(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->user_data()))->cb_radio_add_srv_radioco_i(o,v); +} + +void flgui::cb_Cancel_i(Fl_Button*, void*) { + button_add_srv_cancel_cb(); +} +void flgui::cb_Cancel(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_Cancel_i(o,v); +} + +void flgui::cb_button_add_srv_add_i(Fl_Button*, void*) { + button_add_srv_add_cb(); +} +void flgui::cb_button_add_srv_add(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_button_add_srv_add_i(o,v); +} + +void flgui::cb_button_add_srv_save_i(Fl_Button*, void*) { + button_add_srv_save_cb(); +} +void flgui::cb_button_add_srv_save(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_button_add_srv_save_i(o,v); +} + +void flgui::cb_button_add_srv_revoke_cert_i(Fl_Button*, void*) { + button_add_srv_revoke_cert_cb(); +} +void flgui::cb_button_add_srv_revoke_cert(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->user_data()))->cb_button_add_srv_revoke_cert_i(o,v); +} + +void flgui::cb_button_add_srv_get_stations_i(Fl_Button*, void*) { + button_add_srv_get_stations_cb(); +} +void flgui::cb_button_add_srv_get_stations(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_button_add_srv_get_stations_i(o,v); +} + +void flgui::cb_button_add_srv_select_all_i(Fl_Button*, void*) { + button_add_srv_select_all_cb(); +} +void flgui::cb_button_add_srv_select_all(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_button_add_srv_select_all_i(o,v); +} + +void flgui::cb_button_add_srv_deselect_all_i(Fl_Button*, void*) { + button_add_srv_deselect_all_cb(); +} +void flgui::cb_button_add_srv_deselect_all(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_button_add_srv_deselect_all_i(o,v); +} + +void flgui::cb_Cancel1_i(Fl_Button*, void*) { + button_add_icy_cancel_cb(); +} +void flgui::cb_Cancel1(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_Cancel1_i(o,v); +} + +void flgui::cb_button_add_icy_add_i(Fl_Button*, void*) { + button_add_icy_add_cb(); +} +void flgui::cb_button_add_icy_add(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_button_add_icy_add_i(o,v); +} + +void flgui::cb_button_add_icy_save_i(Fl_Button*, void*) { + button_add_icy_save_cb(); +} +void flgui::cb_button_add_icy_save(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_button_add_icy_save_i(o,v); +} + +void flgui::cb_Copy_i(Fl_Button*, void*) { + int len = this->output_bitcoin_addr->size(); +this->output_bitcoin_addr->position(0, len); +this->output_bitcoin_addr->copy(1); + +fl_message(_("Bitcoin address has been copied to clipboard.")); +} +void flgui::cb_Copy(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_Copy_i(o,v); +} + +void flgui::cb_Copy1_i(Fl_Button*, void*) { + int len = this->output_litecoin_addr->size(); +this->output_litecoin_addr->position(0, len); +this->output_litecoin_addr->copy(1); + +fl_message(_("Litecoin address has been copied to clipboard.")); +} +void flgui::cb_Copy1(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_Copy1_i(o,v); +} + +void flgui::cb_Copy2_i(Fl_Button*, void*) { + int len = this->output_monero_addr->size(); +this->output_monero_addr->position(0, len); +this->output_monero_addr->copy(1); + +fl_message(_("Monero address has been copied to clipboard.")); +} +void flgui::cb_Copy2(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_Copy2_i(o,v); +} + +void flgui::cb_Close_i(Fl_Button*, void*) { + this->window_donate_crypto->hide(); +} +void flgui::cb_Close(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_Close_i(o,v); +} + +void flgui::cb_choice_stream_mp3_enc_quality_i(Fl_Choice*, void*) { + choice_stream_mp3_enc_quality_cb(); +} +void flgui::cb_choice_stream_mp3_enc_quality(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_stream_mp3_enc_quality_i(o,v); +} + +unsigned char flgui::menu_choice_stream_mp3_enc_quality_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_mp3_enc_quality[] = { + {"0 (best)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"1", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"2", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"3 (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"4", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"5", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"6", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"7", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"8", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"9 (worst)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_stream_mp3_stereo_mode_i(Fl_Choice*, void*) { + choice_stream_mp3_stereo_mode_cb(); +} +void flgui::cb_choice_stream_mp3_stereo_mode(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_stream_mp3_stereo_mode_i(o,v); +} + +unsigned char flgui::menu_choice_stream_mp3_stereo_mode_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_mp3_stereo_mode[] = { + {"Auto (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Stereo", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Joint Stereo", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_stream_mp3_bitrate_mode_i(Fl_Choice*, void*) { + choice_stream_mp3_bitrate_mode_cb(); +} +void flgui::cb_choice_stream_mp3_bitrate_mode(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_stream_mp3_bitrate_mode_i(o,v); +} + +unsigned char flgui::menu_choice_stream_mp3_bitrate_mode_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_mp3_bitrate_mode[] = { + {"CBR (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"VBR", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"ABR", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_stream_mp3_vbr_quality_i(Fl_Choice*, void*) { + choice_stream_mp3_vbr_quality_cb(); +} +void flgui::cb_choice_stream_mp3_vbr_quality(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_stream_mp3_vbr_quality_i(o,v); +} + +unsigned char flgui::menu_choice_stream_mp3_vbr_quality_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_mp3_vbr_quality[] = { + {"0 (best)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"1", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"2", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"3", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"4 (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"5", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"6", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"7", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"8", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"9 (worst)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_stream_mp3_vbr_min_bitrate_i(Fl_Choice*, void*) { + choice_stream_mp3_vbr_min_bitrate_cb(); +} +void flgui::cb_choice_stream_mp3_vbr_min_bitrate(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_stream_mp3_vbr_min_bitrate_i(o,v); +} + +unsigned char flgui::menu_choice_stream_mp3_vbr_min_bitrate_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_mp3_vbr_min_bitrate[] = { + {"8k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"16k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"24k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"32k (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"40k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"48k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"56k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"64k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"80k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"96k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"112k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"128k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"160k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"192k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"224k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"256k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"320k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_stream_mp3_vbr_max_bitrate_i(Fl_Choice*, void*) { + choice_stream_mp3_vbr_max_bitrate_cb(); +} +void flgui::cb_choice_stream_mp3_vbr_max_bitrate(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_stream_mp3_vbr_max_bitrate_i(o,v); +} + +unsigned char flgui::menu_choice_stream_mp3_vbr_max_bitrate_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_mp3_vbr_max_bitrate[] = { + {"8k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"16k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"24k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"32k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"40k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"48k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"56k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"64k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"80k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"96k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"112k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"128k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"160k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"192k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"224k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"256k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"320k (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_check_stream_mp3_force_min_bitrate_i(Fl_Check_Button*, void*) { + check_stream_mp3_force_min_bitrate_cb(); +} +void flgui::cb_check_stream_mp3_force_min_bitrate(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_stream_mp3_force_min_bitrate_i(o,v); +} + +void flgui::cb_input_stream_mp3_lowpass_freq_i(Fl_Value_Input*, void*) { + input_stream_mp3_lowpass_freq_cb(); +} +void flgui::cb_input_stream_mp3_lowpass_freq(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_stream_mp3_lowpass_freq_i(o,v); +} + +void flgui::cb_input_stream_mp3_lowpass_width_i(Fl_Value_Input*, void*) { + input_stream_mp3_lowpass_width_cb(); +} +void flgui::cb_input_stream_mp3_lowpass_width(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_stream_mp3_lowpass_width_i(o,v); +} + +void flgui::cb_check_stream_mp3_activate_lowpass_freq_i(Fl_Check_Button*, void*) { + check_stream_mp3_activate_lowpass_freq_cb(); +} +void flgui::cb_check_stream_mp3_activate_lowpass_freq(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_stream_mp3_activate_lowpass_freq_i(o,v); +} + +void flgui::cb_check_stream_mp3_activate_lowpass_width_i(Fl_Check_Button*, void*) { + check_stream_mp3_activate_lowpass_width_cb(); +} +void flgui::cb_check_stream_mp3_activate_lowpass_width(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_stream_mp3_activate_lowpass_width_i(o,v); +} + +void flgui::cb_input_stream_mp3_highpass_freq_i(Fl_Value_Input*, void*) { + input_stream_mp3_highpass_freq_cb(); +} +void flgui::cb_input_stream_mp3_highpass_freq(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_stream_mp3_highpass_freq_i(o,v); +} + +void flgui::cb_input_stream_mp3_highpass_width_i(Fl_Value_Input*, void*) { + input_stream_mp3_highpass_width_cb(); +} +void flgui::cb_input_stream_mp3_highpass_width(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_stream_mp3_highpass_width_i(o,v); +} + +void flgui::cb_check_stream_mp3_activate_highpass_freq_i(Fl_Check_Button*, void*) { + check_stream_mp3_activate_highpass_freq_cb(); +} +void flgui::cb_check_stream_mp3_activate_highpass_freq(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_stream_mp3_activate_highpass_freq_i(o,v); +} + +void flgui::cb_check_stream_mp3_activate_highpass_width_i(Fl_Check_Button*, void*) { + check_stream_mp3_activate_highpass_width_cb(); +} +void flgui::cb_check_stream_mp3_activate_highpass_width(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_stream_mp3_activate_highpass_width_i(o,v); +} + +void flgui::cb_choice_stream_mp3_resampling_freq_i(Fl_Choice*, void*) { + choice_stream_mp3_resampling_freq_cb(); +} +void flgui::cb_choice_stream_mp3_resampling_freq(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_stream_mp3_resampling_freq_i(o,v); +} + +unsigned char flgui::menu_choice_stream_mp3_resampling_freq_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_mp3_resampling_freq[] = { + {"Disabled (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"8000 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"11025 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"12000 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"16000 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"22050 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"24000 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"32000 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"44100 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"48000 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_stream_vorbis_bitrate_mode_i(Fl_Choice*, void*) { + choice_stream_vorbis_bitrate_mode_cb(); +} +void flgui::cb_choice_stream_vorbis_bitrate_mode(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_stream_vorbis_bitrate_mode_i(o,v); +} + +unsigned char flgui::menu_choice_stream_vorbis_bitrate_mode_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_vorbis_bitrate_mode[] = { + {"CBR (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"VBR", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"ABR", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_stream_vorbis_vbr_quality_i(Fl_Choice*, void*) { + choice_stream_vorbis_vbr_quality_cb(); +} +void flgui::cb_choice_stream_vorbis_vbr_quality(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_stream_vorbis_vbr_quality_i(o,v); +} + +unsigned char flgui::menu_choice_stream_vorbis_vbr_quality_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_vorbis_vbr_quality[] = { + {"1.0 (best, default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.9", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.8", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.7", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.6", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.5", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.4", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.3", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.2", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.1", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.0 (worst)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_stream_vorbis_vbr_min_bitrate_i(Fl_Choice*, void*) { + choice_stream_vorbis_vbr_min_bitrate_cb(); +} +void flgui::cb_choice_stream_vorbis_vbr_min_bitrate(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_stream_vorbis_vbr_min_bitrate_i(o,v); +} + +void flgui::cb_choice_stream_vorbis_vbr_max_bitrate_i(Fl_Choice*, void*) { + choice_stream_vorbis_vbr_max_bitrate_cb(); +} +void flgui::cb_choice_stream_vorbis_vbr_max_bitrate(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_stream_vorbis_vbr_max_bitrate_i(o,v); +} + +void flgui::cb_choice_stream_opus_quality_i(Fl_Choice*, void*) { + choice_stream_opus_quality_cb(); +} +void flgui::cb_choice_stream_opus_quality(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_stream_opus_quality_i(o,v); +} + +unsigned char flgui::menu_choice_stream_opus_quality_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_opus_quality[] = { + {"10 (best, default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"9", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"8", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"7", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"6", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"5", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"4", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"3", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"2", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"1", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0 (worst)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_stream_opus_audio_type_i(Fl_Choice*, void*) { + choice_stream_opus_audio_type_cb(); +} +void flgui::cb_choice_stream_opus_audio_type(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_stream_opus_audio_type_i(o,v); +} + +unsigned char flgui::menu_choice_stream_opus_audio_type_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_opus_audio_type[] = { + {"Music (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Speech", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_stream_opus_bitrate_mode_i(Fl_Choice*, void*) { + choice_stream_opus_bitrate_mode_cb(); +} +void flgui::cb_choice_stream_opus_bitrate_mode(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_stream_opus_bitrate_mode_i(o,v); +} + +unsigned char flgui::menu_choice_stream_opus_bitrate_mode_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_opus_bitrate_mode[] = { + {"CBR", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"VBR (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_stream_opus_bandwidth_i(Fl_Choice*, void*) { + choice_stream_opus_bandwidth_cb(); +} +void flgui::cb_choice_stream_opus_bandwidth(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_stream_opus_bandwidth_i(o,v); +} + +unsigned char flgui::menu_choice_stream_opus_bandwidth_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_opus_bandwidth[] = { + {"20kHz (best,default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"12kHz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"8kHz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"6kHz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"4kHz (worst)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_stream_aac_profile_i(Fl_Choice*, void*) { + choice_stream_aac_profile_cb(); +} +void flgui::cb_choice_stream_aac_profile(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_stream_aac_profile_i(o,v); +} + +unsigned char flgui::menu_choice_stream_aac_profile_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_aac_profile[] = { + {"Auto (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"AAC-LC", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"HE-AACv1 (AAC+)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"HE-AACv2 (eAAC+)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_stream_aac_afterburner_i(Fl_Choice*, void*) { + choice_stream_aac_afterburner_cb(); +} +void flgui::cb_choice_stream_aac_afterburner(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_stream_aac_afterburner_i(o,v); +} + +unsigned char flgui::menu_choice_stream_aac_afterburner_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_aac_afterburner[] = { + {"On (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Off", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_stream_aac_bitrate_mode_i(Fl_Choice*, void*) { + choice_stream_aac_bitrate_mode_cb(); +} +void flgui::cb_choice_stream_aac_bitrate_mode(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_stream_aac_bitrate_mode_i(o,v); +} + +unsigned char flgui::menu_choice_stream_aac_bitrate_mode_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_stream_aac_bitrate_mode[] = { + {"CBR (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"VBR", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_radio_stream_flac_bit_depth_16_i(Fl_Round_Button*, void*) { + radio_stream_flac_bit_depth_16_cb(); +} +void flgui::cb_radio_stream_flac_bit_depth_16(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_radio_stream_flac_bit_depth_16_i(o,v); +} + +void flgui::cb_radio_stream_flac_bit_depth_24_i(Fl_Round_Button*, void*) { + radio_stream_flac_bit_depth_24_cb(); +} +void flgui::cb_radio_stream_flac_bit_depth_24(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_radio_stream_flac_bit_depth_24_i(o,v); +} + +void flgui::cb_Close1_i(Fl_Button*, void*) { + this->window_stream_codec_settings->hide(); +} +void flgui::cb_Close1(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_Close1_i(o,v); +} + +void flgui::cb_choice_rec_mp3_enc_quality_i(Fl_Choice*, void*) { + choice_rec_mp3_enc_quality_cb(); +} +void flgui::cb_choice_rec_mp3_enc_quality(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_rec_mp3_enc_quality_i(o,v); +} + +unsigned char flgui::menu_choice_rec_mp3_enc_quality_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_mp3_enc_quality[] = { + {"0 (best)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"1", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"2", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"3 (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"4", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"5", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"6", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"7", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"8", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"9 (worst)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_rec_mp3_stereo_mode_i(Fl_Choice*, void*) { + choice_rec_mp3_stereo_mode_cb(); +} +void flgui::cb_choice_rec_mp3_stereo_mode(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_rec_mp3_stereo_mode_i(o,v); +} + +unsigned char flgui::menu_choice_rec_mp3_stereo_mode_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_mp3_stereo_mode[] = { + {"Auto (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Stereo", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Joint Stereo", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_rec_mp3_bitrate_mode_i(Fl_Choice*, void*) { + choice_rec_mp3_bitrate_mode_cb(); +} +void flgui::cb_choice_rec_mp3_bitrate_mode(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_rec_mp3_bitrate_mode_i(o,v); +} + +unsigned char flgui::menu_choice_rec_mp3_bitrate_mode_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_mp3_bitrate_mode[] = { + {"CBR (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"VBR", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"ABR", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_rec_mp3_vbr_quality_i(Fl_Choice*, void*) { + choice_rec_mp3_vbr_quality_cb(); +} +void flgui::cb_choice_rec_mp3_vbr_quality(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_rec_mp3_vbr_quality_i(o,v); +} + +unsigned char flgui::menu_choice_rec_mp3_vbr_quality_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_mp3_vbr_quality[] = { + {"0 (best)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"1", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"2", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"3", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"4 (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"5", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"6", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"7", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"8", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"9 (worst)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_rec_mp3_vbr_min_bitrate_i(Fl_Choice*, void*) { + choice_rec_mp3_vbr_min_bitrate_cb(); +} +void flgui::cb_choice_rec_mp3_vbr_min_bitrate(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_rec_mp3_vbr_min_bitrate_i(o,v); +} + +unsigned char flgui::menu_choice_rec_mp3_vbr_min_bitrate_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_mp3_vbr_min_bitrate[] = { + {"8k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"16k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"24k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"32k (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"40k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"48k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"56k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"64k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"80k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"96k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"112k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"128k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"160k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"192k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"224k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"256k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"320k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_rec_mp3_vbr_max_bitrate_i(Fl_Choice*, void*) { + choice_rec_mp3_vbr_max_bitrate_cb(); +} +void flgui::cb_choice_rec_mp3_vbr_max_bitrate(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_choice_rec_mp3_vbr_max_bitrate_i(o,v); +} + +unsigned char flgui::menu_choice_rec_mp3_vbr_max_bitrate_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_mp3_vbr_max_bitrate[] = { + {"8k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"16k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"24k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"32k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"40k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"48k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"56k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"64k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"80k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"96k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"112k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"128k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"160k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"192k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"224k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"256k", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"320k (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_check_rec_mp3_force_min_bitrate_i(Fl_Check_Button*, void*) { + check_rec_mp3_force_min_bitrate_cb(); +} +void flgui::cb_check_rec_mp3_force_min_bitrate(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_rec_mp3_force_min_bitrate_i(o,v); +} + +void flgui::cb_choice_rec_mp3_resampling_freq_i(Fl_Choice*, void*) { + choice_rec_mp3_resampling_freq_cb(); +} +void flgui::cb_choice_rec_mp3_resampling_freq(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_rec_mp3_resampling_freq_i(o,v); +} + +unsigned char flgui::menu_choice_rec_mp3_resampling_freq_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_mp3_resampling_freq[] = { + {"Disabled (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"8000 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"11025 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"12000 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"16000 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"22050 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"24000 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"32000 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"44100 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"48000 Hz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_input_rec_mp3_lowpass_freq_i(Fl_Value_Input*, void*) { + input_rec_mp3_lowpass_freq_cb(); +} +void flgui::cb_input_rec_mp3_lowpass_freq(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_rec_mp3_lowpass_freq_i(o,v); +} + +void flgui::cb_input_rec_mp3_lowpass_width_i(Fl_Value_Input*, void*) { + input_rec_mp3_lowpass_width_cb(); +} +void flgui::cb_input_rec_mp3_lowpass_width(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_rec_mp3_lowpass_width_i(o,v); +} + +void flgui::cb_check_rec_mp3_activate_lowpass_freq_i(Fl_Check_Button*, void*) { + check_rec_mp3_activate_lowpass_freq_cb(); +} +void flgui::cb_check_rec_mp3_activate_lowpass_freq(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_rec_mp3_activate_lowpass_freq_i(o,v); +} + +void flgui::cb_check_rec_mp3_activate_lowpass_width_i(Fl_Check_Button*, void*) { + check_rec_mp3_activate_lowpass_width_cb(); +} +void flgui::cb_check_rec_mp3_activate_lowpass_width(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_rec_mp3_activate_lowpass_width_i(o,v); +} + +void flgui::cb_input_rec_mp3_highpass_freq_i(Fl_Value_Input*, void*) { + input_rec_mp3_highpass_freq_cb(); +} +void flgui::cb_input_rec_mp3_highpass_freq(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_rec_mp3_highpass_freq_i(o,v); +} + +void flgui::cb_input_rec_mp3_highpass_width_i(Fl_Value_Input*, void*) { + input_rec_mp3_highpass_width_cb(); +} +void flgui::cb_input_rec_mp3_highpass_width(Fl_Value_Input* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_input_rec_mp3_highpass_width_i(o,v); +} + +void flgui::cb_check_rec_mp3_activate_highpass_freq_i(Fl_Check_Button*, void*) { + check_rec_mp3_activate_highpass_freq_cb(); +} +void flgui::cb_check_rec_mp3_activate_highpass_freq(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_rec_mp3_activate_highpass_freq_i(o,v); +} + +void flgui::cb_check_rec_mp3_activate_highpass_width_i(Fl_Check_Button*, void*) { + check_rec_mp3_activate_highpass_width_cb(); +} +void flgui::cb_check_rec_mp3_activate_highpass_width(Fl_Check_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_check_rec_mp3_activate_highpass_width_i(o,v); +} + +void flgui::cb_choice_rec_vorbis_bitrate_mode_i(Fl_Choice*, void*) { + choice_rec_vorbis_bitrate_mode_cb(); +} +void flgui::cb_choice_rec_vorbis_bitrate_mode(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_rec_vorbis_bitrate_mode_i(o,v); +} + +unsigned char flgui::menu_choice_rec_vorbis_bitrate_mode_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_vorbis_bitrate_mode[] = { + {"CBR (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"VBR", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"ABR", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_rec_vorbis_vbr_quality_i(Fl_Choice*, void*) { + choice_rec_vorbis_vbr_quality_cb(); +} +void flgui::cb_choice_rec_vorbis_vbr_quality(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_rec_vorbis_vbr_quality_i(o,v); +} + +unsigned char flgui::menu_choice_rec_vorbis_vbr_quality_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_vorbis_vbr_quality[] = { + {"1.0 (best, default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.9", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.8", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.7", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.6", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.5", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.4", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.3", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.2", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.1", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0.0 (worst)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_rec_vorbis_vbr_min_bitrate_i(Fl_Choice*, void*) { + choice_rec_vorbis_vbr_min_bitrate_cb(); +} +void flgui::cb_choice_rec_vorbis_vbr_min_bitrate(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_rec_vorbis_vbr_min_bitrate_i(o,v); +} + +void flgui::cb_choice_rec_vorbis_vbr_max_bitrate_i(Fl_Choice*, void*) { + choice_rec_vorbis_vbr_max_bitrate_cb(); +} +void flgui::cb_choice_rec_vorbis_vbr_max_bitrate(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_rec_vorbis_vbr_max_bitrate_i(o,v); +} + +void flgui::cb_choice_rec_opus_audio_type_i(Fl_Choice*, void*) { + choice_rec_opus_audio_type_cb(); +} +void flgui::cb_choice_rec_opus_audio_type(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_rec_opus_audio_type_i(o,v); +} + +unsigned char flgui::menu_choice_rec_opus_audio_type_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_opus_audio_type[] = { + {"Music (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Speech", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_rec_opus_bitrate_mode_i(Fl_Choice*, void*) { + choice_rec_opus_bitrate_mode_cb(); +} +void flgui::cb_choice_rec_opus_bitrate_mode(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_rec_opus_bitrate_mode_i(o,v); +} + +unsigned char flgui::menu_choice_rec_opus_bitrate_mode_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_opus_bitrate_mode[] = { + {"CBR", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"VBR (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_rec_opus_quality_i(Fl_Choice*, void*) { + choice_rec_opus_quality_cb(); +} +void flgui::cb_choice_rec_opus_quality(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_rec_opus_quality_i(o,v); +} + +unsigned char flgui::menu_choice_rec_opus_quality_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_opus_quality[] = { + {"10 (best, default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"9", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"8", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"7", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"6", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"5", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"4", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"3", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"2", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"1", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"0 (worst)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_rec_opus_bandwidth_i(Fl_Choice*, void*) { + choice_rec_opus_bandwidth_cb(); +} +void flgui::cb_choice_rec_opus_bandwidth(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_rec_opus_bandwidth_i(o,v); +} + +unsigned char flgui::menu_choice_rec_opus_bandwidth_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_opus_bandwidth[] = { + {"20kHz (best,default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"12kHz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"8kHz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"6kHz", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"4kHz (worst)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_rec_aac_profile_i(Fl_Choice*, void*) { + choice_rec_aac_profile_cb(); +} +void flgui::cb_choice_rec_aac_profile(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_rec_aac_profile_i(o,v); +} + +unsigned char flgui::menu_choice_rec_aac_profile_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_aac_profile[] = { + {"Auto (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"AAC-LC", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"HE-AACv1 (AAC+)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"HE-AACv2 (eAAC+)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_rec_aac_afterburner_i(Fl_Choice*, void*) { + choice_rec_aac_afterburner_cb(); +} +void flgui::cb_choice_rec_aac_afterburner(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_rec_aac_afterburner_i(o,v); +} + +unsigned char flgui::menu_choice_rec_aac_afterburner_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_aac_afterburner[] = { + {"On (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"Off", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_choice_rec_aac_bitrate_mode_i(Fl_Choice*, void*) { + choice_rec_aac_bitrate_mode_cb(); +} +void flgui::cb_choice_rec_aac_bitrate_mode(Fl_Choice* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->user_data()))->cb_choice_rec_aac_bitrate_mode_i(o,v); +} + +unsigned char flgui::menu_choice_rec_aac_bitrate_mode_i18n_done = 0; +Fl_Menu_Item flgui::menu_choice_rec_aac_bitrate_mode[] = { + {"CBR (default)", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {"VBR", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void flgui::cb_radio_rec_flac_bit_depth_16_i(Fl_Round_Button*, void*) { + radio_rec_flac_bit_depth_16_cb(); +} +void flgui::cb_radio_rec_flac_bit_depth_16(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_radio_rec_flac_bit_depth_16_i(o,v); +} + +void flgui::cb_radio_rec_flac_bit_depth_24_i(Fl_Round_Button*, void*) { + radio_rec_flac_bit_depth_24_cb(); +} +void flgui::cb_radio_rec_flac_bit_depth_24(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_radio_rec_flac_bit_depth_24_i(o,v); +} + +void flgui::cb_radio_rec_wav_bit_depth_16_i(Fl_Round_Button*, void*) { + radio_rec_wav_bit_depth_16_cb(); +} +void flgui::cb_radio_rec_wav_bit_depth_16(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_radio_rec_wav_bit_depth_16_i(o,v); +} + +void flgui::cb_radio_rec_wav_bit_depth_32_i(Fl_Round_Button*, void*) { + radio_rec_wav_bit_depth_32_cb(); +} +void flgui::cb_radio_rec_wav_bit_depth_32(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_radio_rec_wav_bit_depth_32_i(o,v); +} + +void flgui::cb_radio_rec_wav_bit_depth_24_i(Fl_Round_Button*, void*) { + radio_rec_wav_bit_depth_24_cb(); +} +void flgui::cb_radio_rec_wav_bit_depth_24(Fl_Round_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_radio_rec_wav_bit_depth_24_i(o,v); +} + +void flgui::cb_Close2_i(Fl_Button*, void*) { + this->window_rec_codec_settings->hide(); +} +void flgui::cb_Close2(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_Close2_i(o,v); +} + +void flgui::cb_Reset2_i(Fl_Button*, void*) { + button_mixer_reset_cb(); +} +void flgui::cb_Reset2(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_Reset2_i(o,v); +} + +void flgui::cb_slider_mixer_primary_device_i(Fl_My_Value_Slider* o, void* v) { + slider_mixer_primary_device_cb(o->value(),v); +} +void flgui::cb_slider_mixer_primary_device(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->user_data()))->cb_slider_mixer_primary_device_i(o,v); +} + +void flgui::cb_button_mixer_mute_primary_device_i(Fl_Light_Button*, void*) { + button_mixer_mute_primary_device_cb(); +} +void flgui::cb_button_mixer_mute_primary_device(Fl_Light_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->user_data()))->cb_button_mixer_mute_primary_device_i(o,v); +} + +void flgui::cb_slider_mixer_secondary_device_i(Fl_My_Value_Slider* o, void* v) { + slider_mixer_secondary_device_cb(o->value(),v); +} +void flgui::cb_slider_mixer_secondary_device(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->user_data()))->cb_slider_mixer_secondary_device_i(o,v); +} + +void flgui::cb_button_mixer_mute_secondary_device_i(Fl_Light_Button*, void*) { + button_mixer_mute_secondary_device_cb(); +} +void flgui::cb_button_mixer_mute_secondary_device(Fl_Light_Button* o, void* v) { + ((flgui*)(o->parent()->parent()->user_data()))->cb_button_mixer_mute_secondary_device_i(o,v); +} + +void flgui::cb_slider_mixer_streaming_gain_i(Fl_My_Value_Slider* o, void* v) { + slider_mixer_streaming_gain_cb(o->value(),v); +} +void flgui::cb_slider_mixer_streaming_gain(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->user_data()))->cb_slider_mixer_streaming_gain_i(o,v); +} + +void flgui::cb_slider_mixer_recording_gain_i(Fl_My_Value_Slider* o, void* v) { + slider_mixer_recording_gain_cb(o->value(),v); +} +void flgui::cb_slider_mixer_recording_gain(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->user_data()))->cb_slider_mixer_recording_gain_i(o,v); +} + +void flgui::cb_slider_mixer_master_gain_i(Fl_My_Value_Slider* o, void* v) { + slider_mixer_master_gain_cb(o->value(),v); +} +void flgui::cb_slider_mixer_master_gain(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->user_data()))->cb_slider_mixer_master_gain_i(o,v); +} + +void flgui::cb_slider_mixer_cross_fader_i(Fl_My_Value_Slider* o, void* v) { + slider_mixer_cross_fader_cb(o->value(),v); +} +void flgui::cb_slider_mixer_cross_fader(Fl_My_Value_Slider* o, void* v) { + ((flgui*)(o->parent()->parent()->user_data()))->cb_slider_mixer_cross_fader_i(o,v); +} + +void flgui::cb_Open_i(Fl_Button*, void*) { + char uri[128]; +snprintf(uri, sizeof(uri), "https://danielnoethen.de/butt/release/%s/butt-%s_manual.html", VERSION, VERSION); +fl_open_uri(uri); +this->window_missing_aac_lib->hide(); +} +void flgui::cb_Open(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_Open_i(o,v); +} + +void flgui::cb_Close3_i(Fl_Button*, void*) { + this->window_missing_aac_lib->hide(); +} +void flgui::cb_Close3(Fl_Button* o, void* v) { + ((flgui*)(o->parent()->user_data()))->cb_Close3_i(o,v); +} + +flgui::flgui() { + { window_main = new Fl_My_Double_Window(430, 395); + window_main->box(FL_FLAT_BOX); + window_main->color(FL_BACKGROUND_COLOR); + window_main->selection_color(FL_BACKGROUND_COLOR); + window_main->labeltype(FL_NO_LABEL); + window_main->labelfont(0); + window_main->labelsize(14); + window_main->labelcolor(FL_FOREGROUND_COLOR); + window_main->callback((Fl_Callback*)cb_window_main, (void*)(this)); + window_main->align(Fl_Align(FL_ALIGN_TOP)); + window_main->when(FL_WHEN_RELEASE); + { lcd = new Fl_ILM216(10, 10, 410, 95); + lcd->tooltip(gettext("press left mouse to toggle lcd info")); + lcd->box(FL_ENGRAVED_BOX); + lcd->color(FL_GRAY0); + lcd->selection_color((Fl_Color)41); + lcd->labeltype(FL_NORMAL_LABEL); + lcd->labelfont(0); + lcd->labelsize(14); + lcd->labelcolor(FL_FOREGROUND_COLOR); + lcd->callback((Fl_Callback*)cb_lcd); + lcd->align(Fl_Align(FL_ALIGN_CENTER)); + lcd->when(FL_WHEN_RELEASE); + } // Fl_ILM216* lcd + { label_volume = new Fl_Box(154, 119, 135, 16, gettext("Streaming volume")); + label_volume->labelsize(10); + label_volume->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); + } // Fl_Box* label_volume + { button_mixer = new Fl_Button(10, 113, 122, 22, gettext("Mixer")); + button_mixer->tooltip(gettext("show/hide mixer window")); + button_mixer->box(FL_ENGRAVED_BOX); + button_mixer->shortcut(0x40066); + button_mixer->color((Fl_Color)48); + button_mixer->labelsize(11); + button_mixer->callback((Fl_Callback*)cb_button_mixer); + } // Fl_Button* button_mixer + { button_record = new Fl_Button(10, 148, 30, 30, gettext("@circle")); + button_record->tooltip(gettext("start/stop recording")); + button_record->box(FL_ENGRAVED_BOX); + button_record->shortcut(0x40072); + button_record->down_box(FL_ENGRAVED_BOX); + button_record->color((Fl_Color)48); + button_record->selection_color((Fl_Color)40); + button_record->labelfont(1); + button_record->labelsize(12); + button_record->labelcolor((Fl_Color)1); + button_record->callback((Fl_Callback*)cb_button_record); + } // Fl_Button* button_record + { button_disconnect = new Fl_Button(62, 148, 30, 30, gettext("@square")); + button_disconnect->tooltip(gettext("disconnect from server")); + button_disconnect->box(FL_ENGRAVED_BOX); + button_disconnect->shortcut(0x40064); + button_disconnect->down_box(FL_ENGRAVED_BOX); + button_disconnect->color((Fl_Color)48); + button_disconnect->selection_color((Fl_Color)40); + button_disconnect->labelfont(1); + button_disconnect->labelsize(12); + button_disconnect->labelcolor(FL_BACKGROUND2_COLOR); + button_disconnect->callback((Fl_Callback*)cb_button_disconnect); + } // Fl_Button* button_disconnect + { button_connect = new Fl_Button(102, 148, 30, 30, gettext("@>")); + button_connect->tooltip(gettext("connect to server")); + button_connect->box(FL_ENGRAVED_BOX); + button_connect->shortcut(0x40063); + button_connect->down_box(FL_ENGRAVED_BOX); + button_connect->color((Fl_Color)48); + button_connect->selection_color((Fl_Color)40); + button_connect->labelfont(1); + button_connect->labelsize(21); + button_connect->labelcolor(FL_BACKGROUND2_COLOR); + button_connect->callback((Fl_Callback*)cb_button_connect); + } // Fl_Button* button_connect + { vu_tabs = new Fl_Tabs(140, 110, 196, 74); + vu_tabs->box(FL_GTK_THIN_UP_BOX); + vu_tabs->selection_color(FL_DARK1); + vu_tabs->labelsize(13); + vu_tabs->callback((Fl_Callback*)cb_vu_tabs); + { Fl_Group* o = new Fl_Group(150, 128, 177, 47, gettext("Streaming")); + o->labelsize(11); + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(150, 130, 185, 50, gettext("Recording")); + o->labelsize(11); + o->hide(); + o->end(); + } // Fl_Group* o + vu_tabs->end(); + } // Fl_Tabs* vu_tabs + { vumeter = new VUMeter(156, 135, 174, 43); + vumeter->box(FL_BORDER_BOX); + vumeter->color(FL_BACKGROUND_COLOR); + vumeter->selection_color(FL_BACKGROUND_COLOR); + vumeter->labeltype(FL_NORMAL_LABEL); + vumeter->labelfont(0); + vumeter->labelsize(14); + vumeter->labelcolor(FL_FOREGROUND_COLOR); + vumeter->align(Fl_Align(FL_ALIGN_TOP)); + vumeter->when(FL_WHEN_RELEASE); + vumeter->end(); + } // VUMeter* vumeter + { invisible_tab_box = new Fl_My_Invisible_Box(140, 108, 197, 76); + invisible_tab_box->box(FL_NO_BOX); + invisible_tab_box->color(FL_BACKGROUND_COLOR); + invisible_tab_box->selection_color(FL_BACKGROUND_COLOR); + invisible_tab_box->labeltype(FL_NORMAL_LABEL); + invisible_tab_box->labelfont(0); + invisible_tab_box->labelsize(14); + invisible_tab_box->labelcolor(FL_FOREGROUND_COLOR); + invisible_tab_box->align(Fl_Align(FL_ALIGN_CENTER)); + invisible_tab_box->when(FL_WHEN_RELEASE); + } // Fl_My_Invisible_Box* invisible_tab_box + { button_cfg = new Fl_Button(340, 135, 80, 22, gettext("Settings")); + button_cfg->tooltip(gettext("show/hide config window")); + button_cfg->box(FL_ENGRAVED_BOX); + button_cfg->shortcut(0x40066); + button_cfg->color((Fl_Color)48); + button_cfg->labelsize(11); + button_cfg->callback((Fl_Callback*)cb_button_cfg); + } // Fl_Button* button_cfg + { button_info = new Fl_Button(340, 163, 80, 15, gettext("Show log")); + button_info->tooltip(gettext("show/hide info window")); + button_info->box(FL_ENGRAVED_BOX); + button_info->shortcut(0x40076); + button_info->color((Fl_Color)48); + button_info->labelsize(10); + button_info->callback((Fl_Callback*)cb_button_info); + } // Fl_Button* button_info + { label_n24dB = new Fl_Box(10, 190, 30, 16, gettext("-24 dB")); + label_n24dB->labelsize(10); + } // Fl_Box* label_n24dB + { slider_gain = new Fl_My_Value_Slider(50, 191, 335, 15, gettext("Gain")); + slider_gain->tooltip(gettext("Master Gain")); + slider_gain->type(5); + slider_gain->box(FL_NO_BOX); + slider_gain->color(FL_BACKGROUND_COLOR); + slider_gain->selection_color(FL_BACKGROUND_COLOR); + slider_gain->labeltype(FL_NO_LABEL); + slider_gain->labelfont(0); + slider_gain->labelsize(14); + slider_gain->labelcolor(FL_FOREGROUND_COLOR); + slider_gain->minimum(-24); + slider_gain->maximum(24); + slider_gain->step(0.1); + slider_gain->slider_size(0.1); + slider_gain->callback((Fl_Callback*)cb_slider_gain, (void*)(CB_CALLED_BY_USER)); + slider_gain->align(Fl_Align(FL_ALIGN_CENTER)); + slider_gain->when(FL_WHEN_CHANGED); + slider_gain->default_value = 0.0; + } // Fl_My_Value_Slider* slider_gain + { label_p24dB = new Fl_Box(390, 190, 30, 16, gettext("+24 dB")); + label_p24dB->labelsize(10); + } // Fl_Box* label_p24dB + { sponsor_logo = new Fl_Button(237, 27, 128, 61); + sponsor_logo->box(FL_NO_BOX); + sponsor_logo->image( image_radio_co_badge() ); + } // Fl_Button* sponsor_logo + { label_current_listeners = new Fl_Box(211, 83, 165, 16, gettext("Listeners: 0")); + label_current_listeners->labelsize(18); + label_current_listeners->labelcolor(FL_BACKGROUND2_COLOR); + label_current_listeners->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); + } // Fl_Box* label_current_listeners + { info_output = new Fl_Text_Display(0, 212, 430, 184); + info_output->box(FL_EMBOSSED_BOX); + info_output->textfont(4); + info_output->textsize(15); + Fl_Group::current()->resizable(info_output); + } // Fl_Text_Display* info_output + window_main->size_range(430, 155, 430); window_main->is_main_window = true; + window_main->size_range(430, 276, 430, 0); + window_main->end(); + } // Fl_My_Double_Window* window_main + { window_cfg = new Fl_My_Double_Window(430, 680, gettext("butt settings")); + window_cfg->box(FL_FLAT_BOX); + window_cfg->color(FL_BACKGROUND_COLOR); + window_cfg->selection_color(FL_BACKGROUND_COLOR); + window_cfg->labeltype(FL_NO_LABEL); + window_cfg->labelfont(0); + window_cfg->labelsize(14); + window_cfg->labelcolor(FL_FOREGROUND_COLOR); + window_cfg->callback((Fl_Callback*)cb_window_cfg, (void*)(this)); + window_cfg->align(Fl_Align(FL_ALIGN_TOP)); + window_cfg->when(FL_WHEN_RELEASE); + { Settings = new Fl_Tabs(-1, 0, 436, 681); + Settings->selection_color(FL_DARK2); + { Fl_Group* o = new Fl_Group(0, 20, 434, 660, gettext("Main")); + o->when(FL_WHEN_RELEASE_ALWAYS); + { Fl_Group* o = new Fl_Group(50, 55, 328, 155, gettext("Server Settings")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { choice_cfg_act_srv = new Fl_Choice(58, 75, 310, 20, gettext("Server")); + choice_cfg_act_srv->tooltip(gettext("Server to connect to")); + choice_cfg_act_srv->down_box(FL_BORDER_BOX); + choice_cfg_act_srv->callback((Fl_Callback*)cb_choice_cfg_act_srv); + choice_cfg_act_srv->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_cfg_act_srv + { Fl_Button* o = new Fl_Button(58, 100, 80, 20, gettext("ADD")); + o->tooltip(gettext("Add server")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_ADD); + } // Fl_Button* o + { button_cfg_edit_srv = new Fl_Button(173, 100, 80, 20, gettext("EDIT")); + button_cfg_edit_srv->tooltip(gettext("Edit selected server")); + button_cfg_edit_srv->box(FL_ENGRAVED_BOX); + button_cfg_edit_srv->callback((Fl_Callback*)cb_button_cfg_edit_srv); + } // Fl_Button* button_cfg_edit_srv + { button_cfg_del_srv = new Fl_Button(288, 100, 80, 20, gettext("DEL")); + button_cfg_del_srv->tooltip(gettext("Delete selected server")); + button_cfg_del_srv->box(FL_ENGRAVED_BOX); + button_cfg_del_srv->callback((Fl_Callback*)cb_button_cfg_del_srv); + } // Fl_Button* button_cfg_del_srv + { choice_cfg_act_icy = new Fl_Choice(58, 155, 310, 20, gettext("Stream Infos")); + choice_cfg_act_icy->tooltip(gettext("Stream info that shall be used")); + choice_cfg_act_icy->down_box(FL_BORDER_BOX); + choice_cfg_act_icy->callback((Fl_Callback*)cb_choice_cfg_act_icy); + choice_cfg_act_icy->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_cfg_act_icy + { Fl_Button* o = new Fl_Button(58, 180, 80, 20, gettext("ADD")); + o->tooltip(gettext("Add stream info")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_ADD1); + } // Fl_Button* o + { button_cfg_edit_icy = new Fl_Button(173, 180, 80, 20, gettext("EDIT")); + button_cfg_edit_icy->tooltip(gettext("Edit stream info")); + button_cfg_edit_icy->box(FL_ENGRAVED_BOX); + button_cfg_edit_icy->callback((Fl_Callback*)cb_button_cfg_edit_icy); + } // Fl_Button* button_cfg_edit_icy + { button_cfg_del_icy = new Fl_Button(288, 180, 80, 20, gettext("DEL")); + button_cfg_del_icy->tooltip(gettext("Delete stream info")); + button_cfg_del_icy->box(FL_ENGRAVED_BOX); + button_cfg_del_icy->callback((Fl_Callback*)cb_button_cfg_del_icy); + } // Fl_Button* button_cfg_del_icy + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(50, 237, 326, 40, gettext("Log File")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { input_log_filename = new Fl_Input(58, 245, 280, 25); + input_log_filename->tooltip(gettext("Log file path")); + input_log_filename->callback((Fl_Callback*)cb_input_log_filename); + input_log_filename->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Input* input_log_filename + { Fl_Button* o = new Fl_Button(344, 245, 25, 25); + o->tooltip(gettext("Select log file")); + o->box(FL_ENGRAVED_BOX); + o->image( image_folder() ); + o->callback((Fl_Callback*)cb_); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(50, 304, 326, 50, gettext("Configuration")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { button_cfg_import = new Fl_Button(58, 315, 70, 28, gettext("Import...")); + button_cfg_import->tooltip(gettext("Import settings from config file")); + button_cfg_import->box(FL_ENGRAVED_BOX); + button_cfg_import->callback((Fl_Callback*)cb_button_cfg_import); + } // Fl_Button* button_cfg_import + { Fl_Button* o = new Fl_Button(166, 315, 95, 28, gettext("&Save")); + o->tooltip(gettext("Save settings")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Save); + } // Fl_Button* o + { Fl_Button* o = new Fl_Button(298, 315, 70, 28, gettext("Export...")); + o->tooltip(gettext("export settings")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Export); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + { group_agent = new Fl_Group(50, 385, 326, 75, gettext("Butt Agent")); + group_agent->box(FL_ENGRAVED_FRAME); + group_agent->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { check_start_agent = new Fl_Check_Button(56, 400, 157, 15, gettext("Start agent at startup")); + check_start_agent->tooltip(gettext("Start the butt agent when butt starts")); + check_start_agent->down_box(FL_DOWN_BOX); + check_start_agent->callback((Fl_Callback*)cb_check_start_agent); + } // Fl_Check_Button* check_start_agent + { check_minimize_to_tray = new Fl_Check_Button(56, 430, 150, 15, gettext("Minimize butt to tray")); + check_minimize_to_tray->tooltip(gettext("Minimize butt to tray")); + check_minimize_to_tray->down_box(FL_DOWN_BOX); + check_minimize_to_tray->callback((Fl_Callback*)cb_check_minimize_to_tray); + } // Fl_Check_Button* check_minimize_to_tray + { Fl_Button* o = new Fl_Button(261, 391, 105, 28, gettext("Start Agent")); + o->tooltip(gettext("Start the butt agent now")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Start); + } // Fl_Button* o + { Fl_Button* o = new Fl_Button(261, 425, 105, 28, gettext("Stop Agent")); + o->tooltip(gettext("Stop the butt agent")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Stop); + } // Fl_Button* o + group_agent->end(); + } // Fl_Group* group_agent + { Fl_Group* o = new Fl_Group(50, 485, 326, 50, gettext("Updates")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { check_update_at_startup = new Fl_Check_Button(56, 504, 145, 15, gettext("Check at startup")); + check_update_at_startup->tooltip(gettext("Check for updates at start")); + check_update_at_startup->down_box(FL_DOWN_BOX); + check_update_at_startup->callback((Fl_Callback*)cb_check_update_at_startup); + } // Fl_Check_Button* check_update_at_startup + { Fl_Button* o = new Fl_Button(261, 497, 105, 28, gettext("Check now")); + o->tooltip(gettext("Check if a new version is available")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Check); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(50, 565, 330, 50, gettext("Help")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { Fl_Button* o = new Fl_Button(58, 576, 135, 28, gettext("Manual")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Manual); + } // Fl_Button* o + { Fl_Button* o = new Fl_Button(235, 577, 135, 28, gettext(" YouTube")); + o->box(FL_ENGRAVED_BOX); + o->image( image_yt_icon() ); + o->callback((Fl_Callback*)cb_YouTube); + o->align(Fl_Align(256)); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(0, 20, 434, 660, gettext("Audio")); + o->hide(); + { Fl_Group* o = new Fl_Group(50, 55, 326, 245, gettext("Main Audio Settings")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { choice_cfg_channel = new Fl_Choice(58, 84, 150, 21, gettext("Channel mode")); + choice_cfg_channel->tooltip(gettext("Select input channel")); + choice_cfg_channel->box(FL_ENGRAVED_BOX); + choice_cfg_channel->down_box(FL_BORDER_BOX); + choice_cfg_channel->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_cfg_channel_i18n_done) { + int i=0; + for ( ; i<2; i++) + if (menu_choice_cfg_channel[i].label()) + menu_choice_cfg_channel[i].label(gettext(menu_choice_cfg_channel[i].label())); + menu_choice_cfg_channel_i18n_done = 1; + } + choice_cfg_channel->menu(menu_choice_cfg_channel); + } // Fl_Choice* choice_cfg_channel + { choice_cfg_samplerate = new Fl_Choice(228, 85, 135, 20, gettext("Samplerate")); + choice_cfg_samplerate->tooltip(gettext("Select input sample rate")); + choice_cfg_samplerate->down_box(FL_BORDER_BOX); + choice_cfg_samplerate->callback((Fl_Callback*)cb_choice_cfg_samplerate); + choice_cfg_samplerate->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_cfg_samplerate + { Fl_Group* o = new Fl_Group(58, 133, 162, 25, gettext("Remember Device by")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { radio_cfg_ID = new Fl_Round_Button(67, 138, 40, 14, gettext("ID")); + radio_cfg_ID->type(102); + radio_cfg_ID->down_box(FL_ROUND_DOWN_BOX); + radio_cfg_ID->callback((Fl_Callback*)cb_radio_cfg_ID); + } // Fl_Round_Button* radio_cfg_ID + { radio_cfg_name = new Fl_Round_Button(143, 138, 65, 15, gettext("Name")); + radio_cfg_name->type(102); + radio_cfg_name->down_box(FL_ROUND_DOWN_BOX); + radio_cfg_name->callback((Fl_Callback*)cb_radio_cfg_name); + } // Fl_Round_Button* radio_cfg_name + o->end(); + } // Fl_Group* o + { button_cfg_rescan_devices = new Fl_Button(228, 133, 135, 25, gettext("Update devices")); + button_cfg_rescan_devices->tooltip(gettext("Rescan audio devices")); + button_cfg_rescan_devices->box(FL_ENGRAVED_BOX); + button_cfg_rescan_devices->callback((Fl_Callback*)cb_button_cfg_rescan_devices); + } // Fl_Button* button_cfg_rescan_devices + { choice_cfg_dev = new Fl_Choice(58, 190, 170, 20, gettext("Primary Audio Device")); + choice_cfg_dev->tooltip(gettext("Select your primary sound card device")); + choice_cfg_dev->down_box(FL_FLAT_BOX); + choice_cfg_dev->callback((Fl_Callback*)cb_choice_cfg_dev); + choice_cfg_dev->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_cfg_dev + { choice_cfg_left_channel = new Fl_Choice(248, 190, 50, 20, gettext("Left")); + choice_cfg_left_channel->tooltip(gettext("Select left audio channel")); + choice_cfg_left_channel->down_box(FL_BORDER_BOX); + choice_cfg_left_channel->callback((Fl_Callback*)cb_choice_cfg_left_channel); + choice_cfg_left_channel->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_cfg_left_channel + { choice_cfg_right_channel = new Fl_Choice(313, 190, 50, 20, gettext("Right")); + choice_cfg_right_channel->tooltip(gettext("Select right audio channel")); + choice_cfg_right_channel->down_box(FL_BORDER_BOX); + choice_cfg_right_channel->callback((Fl_Callback*)cb_choice_cfg_right_channel); + choice_cfg_right_channel->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_cfg_right_channel + { choice_cfg_dev2 = new Fl_Choice(58, 256, 170, 20, gettext("Secondary Audio Device")); + choice_cfg_dev2->tooltip(gettext("Select your secondary sound card device")); + choice_cfg_dev2->down_box(FL_FLAT_BOX); + choice_cfg_dev2->callback((Fl_Callback*)cb_choice_cfg_dev2); + choice_cfg_dev2->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_cfg_dev2 + { choice_cfg_left_channel2 = new Fl_Choice(248, 256, 50, 20, gettext("Left")); + choice_cfg_left_channel2->tooltip(gettext("Select left audio channel")); + choice_cfg_left_channel2->down_box(FL_BORDER_BOX); + choice_cfg_left_channel2->callback((Fl_Callback*)cb_choice_cfg_left_channel2); + choice_cfg_left_channel2->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_cfg_left_channel2 + { choice_cfg_right_channel2 = new Fl_Choice(313, 256, 50, 20, gettext("Right")); + choice_cfg_right_channel2->tooltip(gettext("Select right audio channel")); + choice_cfg_right_channel2->down_box(FL_BORDER_BOX); + choice_cfg_right_channel2->callback((Fl_Callback*)cb_choice_cfg_right_channel2); + choice_cfg_right_channel2->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_cfg_right_channel2 + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(50, 330, 326, 60, gettext("Streaming")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { choice_cfg_codec = new Fl_Choice(58, 357, 125, 20, gettext("Codec")); + choice_cfg_codec->tooltip(gettext("Select streaming codec")); + choice_cfg_codec->box(FL_ENGRAVED_BOX); + choice_cfg_codec->down_box(FL_BORDER_BOX); + choice_cfg_codec->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_cfg_codec_i18n_done) { + int i=0; + for ( ; i<5; i++) + if (menu_choice_cfg_codec[i].label()) + menu_choice_cfg_codec[i].label(gettext(menu_choice_cfg_codec[i].label())); + menu_choice_cfg_codec_i18n_done = 1; + } + choice_cfg_codec->menu(menu_choice_cfg_codec); + } // Fl_Choice* choice_cfg_codec + { choice_cfg_bitrate = new Fl_Choice(200, 357, 115, 20, gettext("Bitrate")); + choice_cfg_bitrate->tooltip(gettext("Select streaming bitrate")); + choice_cfg_bitrate->box(FL_ENGRAVED_BOX); + choice_cfg_bitrate->down_box(FL_BORDER_BOX); + choice_cfg_bitrate->callback((Fl_Callback*)cb_choice_cfg_bitrate); + choice_cfg_bitrate->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_cfg_bitrate + { Fl_Button* o = new Fl_Button(323, 355, 22, 22); + o->box(FL_NO_BOX); + o->image( image_settings() ); + o->callback((Fl_Callback*)cb_1); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(50, 415, 326, 60, gettext("Recording")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { choice_rec_codec = new Fl_Choice(58, 442, 125, 20, gettext("Codec")); + choice_rec_codec->tooltip(gettext("Select recording codec")); + choice_rec_codec->box(FL_ENGRAVED_BOX); + choice_rec_codec->down_box(FL_BORDER_BOX); + choice_rec_codec->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_codec_i18n_done) { + int i=0; + for ( ; i<6; i++) + if (menu_choice_rec_codec[i].label()) + menu_choice_rec_codec[i].label(gettext(menu_choice_rec_codec[i].label())); + menu_choice_rec_codec_i18n_done = 1; + } + choice_rec_codec->menu(menu_choice_rec_codec); + } // Fl_Choice* choice_rec_codec + { choice_rec_bitrate = new Fl_Choice(200, 442, 115, 20, gettext("Bitrate")); + choice_rec_bitrate->tooltip(gettext("Select recording bitrate")); + choice_rec_bitrate->down_box(FL_BORDER_BOX); + choice_rec_bitrate->callback((Fl_Callback*)cb_choice_rec_bitrate); + choice_rec_bitrate->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_rec_bitrate + { Fl_Button* o = new Fl_Button(323, 440, 22, 22); + o->box(FL_NO_BOX); + o->image( image_settings() ); + o->callback((Fl_Callback*)cb_2); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + { button_advanced = new Fl_Button(37, 345, 89, 25, gettext("Advanced...")); + button_advanced->box(FL_ENGRAVED_BOX); + button_advanced->callback((Fl_Callback*)cb_button_advanced); + button_advanced->hide(); + button_advanced->deactivate(); + } // Fl_Button* button_advanced + { input_cfg_buffer = new Fl_Value_Input(37, 405, 75, 20, gettext("Buffer (ms)")); + input_cfg_buffer->maximum(0); + input_cfg_buffer->value(50); + input_cfg_buffer->callback((Fl_Callback*)cb_input_cfg_buffer); + input_cfg_buffer->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + input_cfg_buffer->when(FL_WHEN_ENTER_KEY); + input_cfg_buffer->hide(); + input_cfg_buffer->deactivate(); + } // Fl_Value_Input* input_cfg_buffer + { choice_cfg_resample_mode = new Fl_Choice(177, 405, 125, 20, gettext("Resample Quality")); + choice_cfg_resample_mode->down_box(FL_BORDER_BOX); + choice_cfg_resample_mode->callback((Fl_Callback*)cb_choice_cfg_resample_mode); + choice_cfg_resample_mode->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + choice_cfg_resample_mode->hide(); + choice_cfg_resample_mode->deactivate(); + if (!menu_choice_cfg_resample_mode_i18n_done) { + int i=0; + for ( ; i<5; i++) + if (menu_choice_cfg_resample_mode[i].label()) + menu_choice_cfg_resample_mode[i].label(gettext(menu_choice_cfg_resample_mode[i].label())); + menu_choice_cfg_resample_mode_i18n_done = 1; + } + choice_cfg_resample_mode->menu(menu_choice_cfg_resample_mode); + } // Fl_Choice* choice_cfg_resample_mode + { Fl_Group* o = new Fl_Group(50, 500, 326, 50, gettext("Signal detection levels")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { input_cfg_present_level = new Fl_Value_Input(58, 524, 70, 19, gettext("Signal present")); + input_cfg_present_level->minimum(-90); + input_cfg_present_level->maximum(0); + input_cfg_present_level->value(-50); + input_cfg_present_level->callback((Fl_Callback*)cb_input_cfg_present_level); + input_cfg_present_level->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Value_Input* input_cfg_present_level + { Fl_Box* o = new Fl_Box(128, 526, 25, 17, gettext("dB")); + o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); + } // Fl_Box* o + { input_cfg_absent_level = new Fl_Value_Input(253, 524, 65, 19, gettext("Signal absent")); + input_cfg_absent_level->minimum(-90); + input_cfg_absent_level->maximum(0); + input_cfg_absent_level->value(-50); + input_cfg_absent_level->callback((Fl_Callback*)cb_input_cfg_absent_level); + input_cfg_absent_level->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Value_Input* input_cfg_absent_level + { Fl_Box* o = new Fl_Box(318, 525, 25, 17, gettext("dB")); + o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); + } // Fl_Box* o + o->end(); + } // Fl_Group* o + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(0, 20, 434, 660, gettext("Stream")); + o->hide(); + { Fl_Group* o = new Fl_Group(50, 47, 329, 65, gettext("Update song name from file")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { input_cfg_song_file = new Fl_Input(55, 56, 283, 26); + input_cfg_song_file->tooltip(gettext("Filename that holds the current song name")); + input_cfg_song_file->callback((Fl_Callback*)cb_input_cfg_song_file); + input_cfg_song_file->align(Fl_Align(FL_ALIGN_TOP_RIGHT)); + this->input_cfg_song_file->maximum_size(500); + } // Fl_Input* input_cfg_song_file + { button_songfile_browse = new Fl_Button(343, 57, 25, 25); + button_songfile_browse->tooltip(gettext("Select file that holds the current song name")); + button_songfile_browse->box(FL_ENGRAVED_FRAME); + button_songfile_browse->image( image_folder() ); + button_songfile_browse->callback((Fl_Callback*)cb_button_songfile_browse); + } // Fl_Button* button_songfile_browse + { check_song_update_active = new Fl_Check_Button(53, 83, 77, 25, gettext("Activate")); + check_song_update_active->tooltip(gettext("Activate auto update song name from file")); + check_song_update_active->down_box(FL_DOWN_BOX); + check_song_update_active->callback((Fl_Callback*)cb_check_song_update_active); + } // Fl_Check_Button* check_song_update_active + { check_read_last_line = new Fl_Check_Button(133, 83, 215, 25, gettext("Read last line instead of first")); + check_read_last_line->tooltip(gettext("Activate auto update song name from file")); + check_read_last_line->down_box(FL_DOWN_BOX); + check_read_last_line->callback((Fl_Callback*)cb_check_read_last_line); + } // Fl_Check_Button* check_read_last_line + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(50, 137, 329, 65, gettext("Update song name from application")); + o->box(FL_ENGRAVED_BOX); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { choice_cfg_app = new Fl_Choice(55, 148, 203, 20); + choice_cfg_app->tooltip(gettext("Changes the song through an running application")); + choice_cfg_app->down_box(FL_BORDER_BOX); + choice_cfg_app->callback((Fl_Callback*)cb_choice_cfg_app); + } // Fl_Choice* choice_cfg_app + { Fl_Group* o = new Fl_Group(268, 145, 105, 40); + { radio_cfg_title_artist = new Fl_Round_Button(268, 145, 105, 20, gettext("Title - Artist")); + radio_cfg_title_artist->type(102); + radio_cfg_title_artist->down_box(FL_ROUND_DOWN_BOX); + radio_cfg_title_artist->callback((Fl_Callback*)cb_radio_cfg_title_artist); + } // Fl_Round_Button* radio_cfg_title_artist + { radio_cfg_artist_title = new Fl_Round_Button(268, 170, 105, 15, gettext("Artist - Title")); + radio_cfg_artist_title->type(102); + radio_cfg_artist_title->down_box(FL_ROUND_DOWN_BOX); + radio_cfg_artist_title->callback((Fl_Callback*)cb_radio_cfg_artist_title); + } // Fl_Round_Button* radio_cfg_artist_title + o->end(); + } // Fl_Group* o + { check_cfg_use_app = new Fl_Check_Button(53, 167, 85, 33, gettext("Activate")); + check_cfg_use_app->down_box(FL_DOWN_BOX); + check_cfg_use_app->callback((Fl_Callback*)cb_check_cfg_use_app); + } // Fl_Check_Button* check_cfg_use_app + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(50, 314, 329, 40, gettext("Update song name manually")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { input_cfg_song = new Fl_Input(55, 322, 283, 25); + input_cfg_song->tooltip(gettext("Current song name")); + input_cfg_song->callback((Fl_Callback*)cb_input_cfg_song); + input_cfg_song->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + input_cfg_song->when(FL_WHEN_CHANGED); + this->input_cfg_song->maximum_size(500); + } // Fl_Input* input_cfg_song + { button_cfg_song_go = new Fl_Button(343, 322, 25, 25, gettext("OK")); + button_cfg_song_go->tooltip(gettext("Send current song name to the server")); + button_cfg_song_go->box(FL_ENGRAVED_BOX); + button_cfg_song_go->shortcut(0xff0d); + button_cfg_song_go->labelsize(12); + button_cfg_song_go->callback((Fl_Callback*)cb_button_cfg_song_go); + } // Fl_Button* button_cfg_song_go + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(50, 373, 329, 32, gettext("Update song name delay")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { choice_cfg_song_delay = new Fl_Choice(55, 379, 153, 20); + choice_cfg_song_delay->tooltip(gettext("Introduces a delay until the song name is actually updated")); + choice_cfg_song_delay->down_box(FL_BORDER_BOX); + choice_cfg_song_delay->callback((Fl_Callback*)cb_choice_cfg_song_delay); + choice_cfg_song_delay->align(Fl_Align(FL_ALIGN_RIGHT)); + } // Fl_Choice* choice_cfg_song_delay + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(50, 426, 330, 75, gettext("Extend song name")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { input_cfg_song_prefix = new Fl_Input(103, 434, 255, 24, gettext("Prefix:")); + input_cfg_song_prefix->callback((Fl_Callback*)cb_input_cfg_song_prefix); + input_cfg_song_prefix->when(FL_WHEN_CHANGED); + this->input_cfg_song_prefix->maximum_size(500); + } // Fl_Input* input_cfg_song_prefix + { input_cfg_song_suffix = new Fl_Input(103, 469, 255, 24, gettext("Suffix:")); + input_cfg_song_suffix->callback((Fl_Callback*)cb_input_cfg_song_suffix); + input_cfg_song_suffix->when(FL_WHEN_CHANGED); + this->input_cfg_song_suffix->maximum_size(500); + } // Fl_Input* input_cfg_song_suffix + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(50, 525, 329, 152, gettext("Streaming")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { check_stream_signal = new Fl_Check_Button(55, 535, 205, 18, gettext("Start if signal is present for")); + check_stream_signal->tooltip(gettext("Start streaming if the audio level exceeds the \"Signal present\" level set i\ +n the \"Audio\" tab")); + check_stream_signal->down_box(FL_DOWN_BOX); + check_stream_signal->callback((Fl_Callback*)cb_check_stream_signal); + } // Fl_Check_Button* check_stream_signal + { input_cfg_signal = new Fl_Value_Input(272, 533, 42, 19); + input_cfg_signal->callback((Fl_Callback*)cb_input_cfg_signal); + input_cfg_signal->when(FL_WHEN_RELEASE); + } // Fl_Value_Input* input_cfg_signal + { Fl_Box* o = new Fl_Box(313, 533, 62, 16, gettext("seconds")); + o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); + } // Fl_Box* o + { check_stream_silence = new Fl_Check_Button(55, 557, 205, 18, gettext("Stop if signal is absent for")); + check_stream_silence->tooltip(gettext("Stop streaming if the audio level falls below the \"Signal absent level set i\ +n the \"Audio\" tab")); + check_stream_silence->down_box(FL_DOWN_BOX); + check_stream_silence->callback((Fl_Callback*)cb_check_stream_silence); + } // Fl_Check_Button* check_stream_silence + { input_cfg_silence = new Fl_Value_Input(272, 557, 42, 19); + input_cfg_silence->callback((Fl_Callback*)cb_input_cfg_silence); + input_cfg_silence->when(FL_WHEN_RELEASE); + } // Fl_Value_Input* input_cfg_silence + { Fl_Box* o = new Fl_Box(313, 557, 62, 16, gettext("seconds")); + o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); + } // Fl_Box* o + { check_cfg_connect = new Fl_Check_Button(55, 583, 205, 18, gettext("Start streaming after launch")); + check_cfg_connect->tooltip(gettext("Connect automatically to a server after launch")); + check_cfg_connect->down_box(FL_DOWN_BOX); + check_cfg_connect->callback((Fl_Callback*)cb_check_cfg_connect); + } // Fl_Check_Button* check_cfg_connect + { check_cfg_force_reconnecting = new Fl_Check_Button(55, 606, 205, 18, gettext("Force reconnecting")); + check_cfg_force_reconnecting->tooltip(gettext("If enabled butt keeps reconnecting regardless of the error message")); + check_cfg_force_reconnecting->down_box(FL_DOWN_BOX); + check_cfg_force_reconnecting->callback((Fl_Callback*)cb_check_cfg_force_reconnecting); + } // Fl_Check_Button* check_cfg_force_reconnecting + { Fl_Box* o = new Fl_Box(55, 631, 190, 17, gettext("Reconnect delay:")); + o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); + } // Fl_Box* o + { input_cfg_reconnect_delay = new Fl_Value_Input(58, 651, 42, 19); + input_cfg_reconnect_delay->callback((Fl_Callback*)cb_input_cfg_reconnect_delay); + } // Fl_Value_Input* input_cfg_reconnect_delay + { Fl_Box* o = new Fl_Box(104, 652, 62, 16, gettext("seconds")); + o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); + } // Fl_Box* o + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(50, 225, 329, 65, gettext("Update song name from URL")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { input_cfg_song_url = new Fl_Input(55, 233, 318, 25); + input_cfg_song_url->tooltip(gettext("URL to get song name from")); + input_cfg_song_url->callback((Fl_Callback*)cb_input_cfg_song_url); + input_cfg_song_url->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_cfg_song_url->maximum_size(1024); + } // Fl_Input* input_cfg_song_url + { input_cfg_url_update_song_interval = new Fl_Value_Input(340, 263, 30, 19, gettext("Update interval")); + input_cfg_url_update_song_interval->tooltip(gettext("Update interval in seconds")); + input_cfg_url_update_song_interval->minimum(1); + input_cfg_url_update_song_interval->maximum(1000); + input_cfg_url_update_song_interval->value(1); + input_cfg_url_update_song_interval->callback((Fl_Callback*)cb_input_cfg_url_update_song_interval); + input_cfg_url_update_song_interval->when(FL_WHEN_RELEASE); + } // Fl_Value_Input* input_cfg_url_update_song_interval + { check_cfg_update_from_url = new Fl_Check_Button(55, 259, 85, 31, gettext("Activate")); + check_cfg_update_from_url->down_box(FL_DOWN_BOX); + check_cfg_update_from_url->callback((Fl_Callback*)cb_check_cfg_update_from_url); + } // Fl_Check_Button* check_cfg_update_from_url + o->end(); + } // Fl_Group* o + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(0, 20, 434, 660, gettext("Record")); + o->hide(); + { input_rec_filename = new Fl_Input(50, 55, 326, 25, gettext("Record File Name:")); + input_rec_filename->tooltip(gettext("Record file name")); + input_rec_filename->callback((Fl_Callback*)cb_input_rec_filename); + input_rec_filename->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_rec_filename->maximum_size(500); + } // Fl_Input* input_rec_filename + { input_rec_folder = new Fl_Input(50, 106, 298, 25, gettext("Record Directory:")); + input_rec_folder->tooltip(gettext("Directory of recordings")); + input_rec_folder->callback((Fl_Callback*)cb_input_rec_folder); + input_rec_folder->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_rec_folder->maximum_size(500); + } // Fl_Input* input_rec_folder + { button_rec_browse = new Fl_Button(350, 106, 25, 25); + button_rec_browse->tooltip(gettext("Select recording directory")); + button_rec_browse->box(FL_ENGRAVED_BOX); + button_rec_browse->image( image_folder() ); + button_rec_browse->callback((Fl_Callback*)cb_button_rec_browse); + } // Fl_Button* button_rec_browse + { Fl_Group* o = new Fl_Group(50, 164, 326, 57, gettext("Split file")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { input_rec_split_time = new Fl_Value_Input(97, 171, 40, 19, gettext("every")); + input_rec_split_time->callback((Fl_Callback*)cb_input_rec_split_time); + } // Fl_Value_Input* input_rec_split_time + { text_rec_split_time = new Fl_Box(143, 171, 50, 16, gettext("minutes")); + } // Fl_Box* text_rec_split_time + { check_sync_to_full_hour = new Fl_Check_Button(55, 196, 124, 15, gettext("Sync to full hour")); + check_sync_to_full_hour->tooltip(gettext("Sync to full hour")); + check_sync_to_full_hour->down_box(FL_DOWN_BOX); + check_sync_to_full_hour->callback((Fl_Callback*)cb_check_sync_to_full_hour); + } // Fl_Check_Button* check_sync_to_full_hour + { Fl_Button* o = new Fl_Button(288, 179, 80, 28, gettext("Split now")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Split); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(50, 250, 326, 173, gettext("Recording")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { check_cfg_auto_start_rec = new Fl_Check_Button(55, 290, 265, 20, gettext("Start recording when connected")); + check_cfg_auto_start_rec->tooltip(gettext("Start recording when connected")); + check_cfg_auto_start_rec->down_box(FL_DOWN_BOX); + check_cfg_auto_start_rec->callback((Fl_Callback*)cb_check_cfg_auto_start_rec); + } // Fl_Check_Button* check_cfg_auto_start_rec + { check_cfg_auto_stop_rec = new Fl_Check_Button(55, 314, 265, 20, gettext("Stop recording when disconnected")); + check_cfg_auto_stop_rec->tooltip(gettext("Start recording when disconnected")); + check_cfg_auto_stop_rec->down_box(FL_DOWN_BOX); + check_cfg_auto_stop_rec->callback((Fl_Callback*)cb_check_cfg_auto_stop_rec); + } // Fl_Check_Button* check_cfg_auto_stop_rec + { check_cfg_rec_after_launch = new Fl_Check_Button(55, 339, 265, 20, gettext("Start recording after launch")); + check_cfg_rec_after_launch->tooltip(gettext("Start recording after launch")); + check_cfg_rec_after_launch->down_box(FL_DOWN_BOX); + check_cfg_rec_after_launch->callback((Fl_Callback*)cb_check_cfg_rec_after_launch); + } // Fl_Check_Button* check_cfg_rec_after_launch + { check_rec_signal = new Fl_Check_Button(55, 362, 205, 18, gettext("Start if signal is present for")); + check_rec_signal->tooltip(gettext("Start recording if the audio level exceeds the \"Signal present\" level set i\ +n the \"Audio\" tab")); + check_rec_signal->down_box(FL_DOWN_BOX); + check_rec_signal->callback((Fl_Callback*)cb_check_rec_signal); + } // Fl_Check_Button* check_rec_signal + { input_rec_signal = new Fl_Value_Input(266, 362, 42, 19); + input_rec_signal->callback((Fl_Callback*)cb_input_rec_signal); + input_rec_signal->when(FL_WHEN_RELEASE); + } // Fl_Value_Input* input_rec_signal + { Fl_Box* o = new Fl_Box(308, 363, 64, 16, gettext("seconds")); + o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); + } // Fl_Box* o + { check_rec_silence = new Fl_Check_Button(55, 385, 205, 18, gettext("Stop if signal is absent for")); + check_rec_silence->tooltip(gettext("Stop recording if the audio level falls below the \"Signal absent level set i\ +n the \"Audio\" tab")); + check_rec_silence->down_box(FL_DOWN_BOX); + check_rec_silence->callback((Fl_Callback*)cb_check_rec_silence); + } // Fl_Check_Button* check_rec_silence + { input_rec_silence = new Fl_Value_Input(266, 386, 42, 19); + input_rec_silence->callback((Fl_Callback*)cb_input_rec_silence); + input_rec_silence->when(FL_WHEN_RELEASE); + } // Fl_Value_Input* input_rec_silence + { Fl_Box* o = new Fl_Box(308, 386, 62, 16, gettext("seconds")); + o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); + } // Fl_Box* o + { check_cfg_overwrite_existing_files = new Fl_Check_Button(55, 266, 300, 20, gettext("Overwrite existing files")); + check_cfg_overwrite_existing_files->down_box(FL_DOWN_BOX); + check_cfg_overwrite_existing_files->callback((Fl_Callback*)cb_check_cfg_overwrite_existing_files); + } // Fl_Check_Button* check_cfg_overwrite_existing_files + o->end(); + } // Fl_Group* o + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(0, 20, 434, 660, gettext("DSP")); + o->hide(); + { Fl_Button* o = new Fl_Button(320, 33, 80, 19, gettext("Reset")); + o->box(FL_ENGRAVED_BOX); + o->labelsize(12); + o->callback((Fl_Callback*)cb_Reset); + } // Fl_Button* o + { Fl_Group* o = new Fl_Group(30, 55, 371, 225, gettext("Equalizer")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { check_stream_eq = new Fl_Check_Button(35, 57, 79, 25, gettext("Stream")); + check_stream_eq->down_box(FL_DOWN_BOX); + check_stream_eq->callback((Fl_Callback*)cb_check_stream_eq); + } // Fl_Check_Button* check_stream_eq + { check_rec_eq = new Fl_Check_Button(115, 57, 60, 25, gettext("Rec")); + check_rec_eq->down_box(FL_DOWN_BOX); + check_rec_eq->callback((Fl_Callback*)cb_check_rec_eq); + } // Fl_Check_Button* check_rec_eq + { choice_eq_preset = new Fl_Choice(250, 62, 140, 18); + choice_eq_preset->tooltip(gettext("Equalizer Preset")); + choice_eq_preset->down_box(FL_BORDER_BOX); + choice_eq_preset->callback((Fl_Callback*)cb_choice_eq_preset); + if (!menu_choice_eq_preset_i18n_done) { + int i=0; + for ( ; i<20; i++) + if (menu_choice_eq_preset[i].label()) + menu_choice_eq_preset[i].label(gettext(menu_choice_eq_preset[i].label())); + menu_choice_eq_preset_i18n_done = 1; + } + choice_eq_preset->menu(menu_choice_eq_preset); + } // Fl_Choice* choice_eq_preset + { equalizerGain1 = new Fl_Text_Display(31, 105, 51, 10, gettext("+0.0")); + equalizerGain1->box(FL_NO_BOX); + equalizerGain1->labelsize(11); + } // Fl_Text_Display* equalizerGain1 + { equalizerSlider1 = new Fl_My_Value_Slider(53, 105, 15, 150, gettext("32Hz")); + equalizerSlider1->type(4); + equalizerSlider1->box(FL_NO_BOX); + equalizerSlider1->color(FL_BACKGROUND_COLOR); + equalizerSlider1->selection_color(FL_BACKGROUND_COLOR); + equalizerSlider1->labeltype(FL_NORMAL_LABEL); + equalizerSlider1->labelfont(0); + equalizerSlider1->labelsize(11); + equalizerSlider1->labelcolor(FL_FOREGROUND_COLOR); + equalizerSlider1->minimum(15); + equalizerSlider1->maximum(-15); + equalizerSlider1->step(0.1); + equalizerSlider1->slider_size(0.151515); + equalizerSlider1->callback((Fl_Callback*)cb_equalizerSlider1); + equalizerSlider1->align(Fl_Align(FL_ALIGN_BOTTOM)); + equalizerSlider1->when(FL_WHEN_CHANGED); + equalizerSlider1->default_value = 0.0; + } // Fl_My_Value_Slider* equalizerSlider1 + { equalizerGain2 = new Fl_Text_Display(74, 105, 35, 10, gettext("+0.0")); + equalizerGain2->box(FL_NO_BOX); + equalizerGain2->labelsize(11); + } // Fl_Text_Display* equalizerGain2 + { equalizerSlider2 = new Fl_My_Value_Slider(88, 105, 15, 150, gettext("64Hz")); + equalizerSlider2->type(4); + equalizerSlider2->box(FL_NO_BOX); + equalizerSlider2->color(FL_BACKGROUND_COLOR); + equalizerSlider2->selection_color(FL_BACKGROUND_COLOR); + equalizerSlider2->labeltype(FL_NORMAL_LABEL); + equalizerSlider2->labelfont(0); + equalizerSlider2->labelsize(11); + equalizerSlider2->labelcolor(FL_FOREGROUND_COLOR); + equalizerSlider2->minimum(15); + equalizerSlider2->maximum(-15); + equalizerSlider2->step(0.1); + equalizerSlider2->slider_size(0.151515); + equalizerSlider2->callback((Fl_Callback*)cb_equalizerSlider2); + equalizerSlider2->align(Fl_Align(FL_ALIGN_BOTTOM)); + equalizerSlider2->when(FL_WHEN_CHANGED); + equalizerSlider2->default_value = 0.0; + } // Fl_My_Value_Slider* equalizerSlider2 + { equalizerGain3 = new Fl_Text_Display(109, 105, 35, 10, gettext("+0.0")); + equalizerGain3->box(FL_NO_BOX); + equalizerGain3->labelsize(11); + } // Fl_Text_Display* equalizerGain3 + { equalizerSlider3 = new Fl_My_Value_Slider(123, 105, 15, 150, gettext("125Hz")); + equalizerSlider3->type(4); + equalizerSlider3->box(FL_NO_BOX); + equalizerSlider3->color(FL_BACKGROUND_COLOR); + equalizerSlider3->selection_color(FL_BACKGROUND_COLOR); + equalizerSlider3->labeltype(FL_NORMAL_LABEL); + equalizerSlider3->labelfont(0); + equalizerSlider3->labelsize(11); + equalizerSlider3->labelcolor(FL_FOREGROUND_COLOR); + equalizerSlider3->minimum(15); + equalizerSlider3->maximum(-15); + equalizerSlider3->step(0.1); + equalizerSlider3->slider_size(0.151515); + equalizerSlider3->callback((Fl_Callback*)cb_equalizerSlider3); + equalizerSlider3->align(Fl_Align(FL_ALIGN_BOTTOM)); + equalizerSlider3->when(FL_WHEN_CHANGED); + equalizerSlider3->default_value = 0.0; + } // Fl_My_Value_Slider* equalizerSlider3 + { equalizerGain4 = new Fl_Text_Display(144, 105, 35, 10, gettext("+0.0")); + equalizerGain4->box(FL_NO_BOX); + equalizerGain4->labelsize(11); + } // Fl_Text_Display* equalizerGain4 + { equalizerSlider4 = new Fl_My_Value_Slider(158, 105, 15, 150, gettext("250Hz")); + equalizerSlider4->type(4); + equalizerSlider4->box(FL_NO_BOX); + equalizerSlider4->color(FL_BACKGROUND_COLOR); + equalizerSlider4->selection_color(FL_BACKGROUND_COLOR); + equalizerSlider4->labeltype(FL_NORMAL_LABEL); + equalizerSlider4->labelfont(0); + equalizerSlider4->labelsize(11); + equalizerSlider4->labelcolor(FL_FOREGROUND_COLOR); + equalizerSlider4->minimum(15); + equalizerSlider4->maximum(-15); + equalizerSlider4->step(0.1); + equalizerSlider4->slider_size(0.151515); + equalizerSlider4->callback((Fl_Callback*)cb_equalizerSlider4); + equalizerSlider4->align(Fl_Align(FL_ALIGN_BOTTOM)); + equalizerSlider4->when(FL_WHEN_CHANGED); + equalizerSlider4->default_value = 0.0; + } // Fl_My_Value_Slider* equalizerSlider4 + { equalizerGain5 = new Fl_Text_Display(179, 105, 35, 10, gettext("+0.0")); + equalizerGain5->box(FL_NO_BOX); + equalizerGain5->labelsize(11); + } // Fl_Text_Display* equalizerGain5 + { equalizerSlider5 = new Fl_My_Value_Slider(193, 105, 15, 150, gettext("500Hz")); + equalizerSlider5->type(4); + equalizerSlider5->box(FL_NO_BOX); + equalizerSlider5->color(FL_BACKGROUND_COLOR); + equalizerSlider5->selection_color(FL_BACKGROUND_COLOR); + equalizerSlider5->labeltype(FL_NORMAL_LABEL); + equalizerSlider5->labelfont(0); + equalizerSlider5->labelsize(11); + equalizerSlider5->labelcolor(FL_FOREGROUND_COLOR); + equalizerSlider5->minimum(15); + equalizerSlider5->maximum(-15); + equalizerSlider5->step(0.1); + equalizerSlider5->slider_size(0.151515); + equalizerSlider5->callback((Fl_Callback*)cb_equalizerSlider5); + equalizerSlider5->align(Fl_Align(FL_ALIGN_BOTTOM)); + equalizerSlider5->when(FL_WHEN_CHANGED); + equalizerSlider5->default_value = 0.0; + } // Fl_My_Value_Slider* equalizerSlider5 + { equalizerGain6 = new Fl_Text_Display(214, 105, 35, 10, gettext("+0.0")); + equalizerGain6->box(FL_NO_BOX); + equalizerGain6->labelsize(11); + } // Fl_Text_Display* equalizerGain6 + { equalizerSlider6 = new Fl_My_Value_Slider(228, 105, 15, 150, gettext("1kHz")); + equalizerSlider6->type(4); + equalizerSlider6->box(FL_NO_BOX); + equalizerSlider6->color(FL_BACKGROUND_COLOR); + equalizerSlider6->selection_color(FL_BACKGROUND_COLOR); + equalizerSlider6->labeltype(FL_NORMAL_LABEL); + equalizerSlider6->labelfont(0); + equalizerSlider6->labelsize(11); + equalizerSlider6->labelcolor(FL_FOREGROUND_COLOR); + equalizerSlider6->minimum(15); + equalizerSlider6->maximum(-15); + equalizerSlider6->step(0.1); + equalizerSlider6->slider_size(0.151515); + equalizerSlider6->callback((Fl_Callback*)cb_equalizerSlider6); + equalizerSlider6->align(Fl_Align(FL_ALIGN_BOTTOM)); + equalizerSlider6->when(FL_WHEN_CHANGED); + equalizerSlider6->default_value = 0.0; + } // Fl_My_Value_Slider* equalizerSlider6 + { equalizerGain7 = new Fl_Text_Display(249, 105, 35, 10, gettext("+0.0")); + equalizerGain7->box(FL_NO_BOX); + equalizerGain7->labelsize(11); + } // Fl_Text_Display* equalizerGain7 + { equalizerSlider7 = new Fl_My_Value_Slider(263, 105, 15, 150, gettext("2kHz")); + equalizerSlider7->type(4); + equalizerSlider7->box(FL_NO_BOX); + equalizerSlider7->color(FL_BACKGROUND_COLOR); + equalizerSlider7->selection_color(FL_BACKGROUND_COLOR); + equalizerSlider7->labeltype(FL_NORMAL_LABEL); + equalizerSlider7->labelfont(0); + equalizerSlider7->labelsize(11); + equalizerSlider7->labelcolor(FL_FOREGROUND_COLOR); + equalizerSlider7->minimum(15); + equalizerSlider7->maximum(-15); + equalizerSlider7->step(0.1); + equalizerSlider7->slider_size(0.151515); + equalizerSlider7->callback((Fl_Callback*)cb_equalizerSlider7); + equalizerSlider7->align(Fl_Align(FL_ALIGN_BOTTOM)); + equalizerSlider7->when(FL_WHEN_CHANGED); + equalizerSlider7->default_value = 0.0; + } // Fl_My_Value_Slider* equalizerSlider7 + { equalizerGain8 = new Fl_Text_Display(284, 105, 35, 10, gettext("+0.0")); + equalizerGain8->box(FL_NO_BOX); + equalizerGain8->labelsize(11); + } // Fl_Text_Display* equalizerGain8 + { equalizerSlider8 = new Fl_My_Value_Slider(298, 105, 15, 150, gettext("4kHz")); + equalizerSlider8->type(4); + equalizerSlider8->box(FL_NO_BOX); + equalizerSlider8->color(FL_BACKGROUND_COLOR); + equalizerSlider8->selection_color(FL_BACKGROUND_COLOR); + equalizerSlider8->labeltype(FL_NORMAL_LABEL); + equalizerSlider8->labelfont(0); + equalizerSlider8->labelsize(11); + equalizerSlider8->labelcolor(FL_FOREGROUND_COLOR); + equalizerSlider8->minimum(15); + equalizerSlider8->maximum(-15); + equalizerSlider8->step(0.1); + equalizerSlider8->slider_size(0.151515); + equalizerSlider8->callback((Fl_Callback*)cb_equalizerSlider8); + equalizerSlider8->align(Fl_Align(FL_ALIGN_BOTTOM)); + equalizerSlider8->when(FL_WHEN_CHANGED); + equalizerSlider8->default_value = 0.0; + } // Fl_My_Value_Slider* equalizerSlider8 + { equalizerGain9 = new Fl_Text_Display(319, 105, 35, 10, gettext("+0.0")); + equalizerGain9->box(FL_NO_BOX); + equalizerGain9->labelsize(11); + } // Fl_Text_Display* equalizerGain9 + { equalizerSlider9 = new Fl_My_Value_Slider(333, 105, 15, 150, gettext("8kHz")); + equalizerSlider9->type(4); + equalizerSlider9->box(FL_NO_BOX); + equalizerSlider9->color(FL_BACKGROUND_COLOR); + equalizerSlider9->selection_color(FL_BACKGROUND_COLOR); + equalizerSlider9->labeltype(FL_NORMAL_LABEL); + equalizerSlider9->labelfont(0); + equalizerSlider9->labelsize(11); + equalizerSlider9->labelcolor(FL_FOREGROUND_COLOR); + equalizerSlider9->minimum(15); + equalizerSlider9->maximum(-15); + equalizerSlider9->step(0.1); + equalizerSlider9->slider_size(0.151515); + equalizerSlider9->callback((Fl_Callback*)cb_equalizerSlider9); + equalizerSlider9->align(Fl_Align(FL_ALIGN_BOTTOM)); + equalizerSlider9->when(FL_WHEN_CHANGED); + equalizerSlider9->default_value = 0.0; + } // Fl_My_Value_Slider* equalizerSlider9 + { equalizerGain10 = new Fl_Text_Display(354, 105, 35, 10, gettext("+0.0")); + equalizerGain10->box(FL_NO_BOX); + equalizerGain10->labelsize(11); + } // Fl_Text_Display* equalizerGain10 + { equalizerSlider10 = new Fl_My_Value_Slider(368, 105, 15, 150, gettext("16kHz")); + equalizerSlider10->type(4); + equalizerSlider10->box(FL_NO_BOX); + equalizerSlider10->color(FL_BACKGROUND_COLOR); + equalizerSlider10->selection_color(FL_BACKGROUND_COLOR); + equalizerSlider10->labeltype(FL_NORMAL_LABEL); + equalizerSlider10->labelfont(0); + equalizerSlider10->labelsize(11); + equalizerSlider10->labelcolor(FL_FOREGROUND_COLOR); + equalizerSlider10->minimum(15); + equalizerSlider10->maximum(-15); + equalizerSlider10->step(0.1); + equalizerSlider10->slider_size(0.151515); + equalizerSlider10->callback((Fl_Callback*)cb_equalizerSlider10); + equalizerSlider10->align(Fl_Align(FL_ALIGN_BOTTOM)); + equalizerSlider10->when(FL_WHEN_CHANGED); + equalizerSlider10->default_value = 0.0; + } // Fl_My_Value_Slider* equalizerSlider10 + o->end(); + } // Fl_Group* o + { Fl_Button* o = new Fl_Button(320, 301, 80, 19, gettext("Reset")); + o->box(FL_ENGRAVED_BOX); + o->labelsize(12); + o->callback((Fl_Callback*)cb_Reset1); + } // Fl_Button* o + { Fl_Group* o = new Fl_Group(30, 323, 371, 225, gettext("Dynamic Range Compressor")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { check_stream_drc = new Fl_Check_Button(35, 326, 79, 25, gettext("Stream")); + check_stream_drc->down_box(FL_DOWN_BOX); + check_stream_drc->callback((Fl_Callback*)cb_check_stream_drc); + } // Fl_Check_Button* check_stream_drc + { check_rec_drc = new Fl_Check_Button(110, 325, 60, 25, gettext("Rec")); + check_rec_drc->down_box(FL_DOWN_BOX); + check_rec_drc->callback((Fl_Callback*)cb_check_rec_drc); + } // Fl_Check_Button* check_rec_drc + { check_aggressive_mode = new Fl_Check_Button(259, 328, 130, 20, gettext("Aggressive Mode")); + check_aggressive_mode->down_box(FL_DOWN_BOX); + check_aggressive_mode->callback((Fl_Callback*)cb_check_aggressive_mode); + } // Fl_Check_Button* check_aggressive_mode + { threshold = new Fl_Text_Display(54, 378, 35, 10, gettext("+0.0")); + threshold->box(FL_NO_BOX); + threshold->labelsize(11); + } // Fl_Text_Display* threshold + { thresholdSlider = new Fl_My_Value_Slider(68, 378, 15, 150, gettext("Threshold")); + thresholdSlider->type(4); + thresholdSlider->box(FL_NO_BOX); + thresholdSlider->color(FL_BACKGROUND_COLOR); + thresholdSlider->selection_color(FL_BACKGROUND_COLOR); + thresholdSlider->labeltype(FL_NORMAL_LABEL); + thresholdSlider->labelfont(0); + thresholdSlider->labelsize(11); + thresholdSlider->labelcolor(FL_FOREGROUND_COLOR); + thresholdSlider->maximum(-60); + thresholdSlider->step(0.1); + thresholdSlider->value(-20); + thresholdSlider->slider_size(0.151515); + thresholdSlider->callback((Fl_Callback*)cb_thresholdSlider); + thresholdSlider->align(Fl_Align(FL_ALIGN_BOTTOM)); + thresholdSlider->when(FL_WHEN_CHANGED); + thresholdSlider->default_value = -20.0; + } // Fl_My_Value_Slider* thresholdSlider + { ratio = new Fl_Text_Display(124, 378, 35, 10, gettext("+0.0")); + ratio->box(FL_NO_BOX); + ratio->labelsize(11); + } // Fl_Text_Display* ratio + { ratioSlider = new Fl_My_Value_Slider(138, 378, 15, 150, gettext("Ratio")); + ratioSlider->type(4); + ratioSlider->box(FL_NO_BOX); + ratioSlider->color(FL_BACKGROUND_COLOR); + ratioSlider->selection_color(FL_BACKGROUND_COLOR); + ratioSlider->labeltype(FL_NORMAL_LABEL); + ratioSlider->labelfont(0); + ratioSlider->labelsize(11); + ratioSlider->labelcolor(FL_FOREGROUND_COLOR); + ratioSlider->minimum(10); + ratioSlider->step(0.1); + ratioSlider->value(5); + ratioSlider->slider_size(0.151515); + ratioSlider->callback((Fl_Callback*)cb_ratioSlider); + ratioSlider->align(Fl_Align(FL_ALIGN_BOTTOM)); + ratioSlider->when(FL_WHEN_CHANGED); + ratioSlider->default_value = 5.0; + } // Fl_My_Value_Slider* ratioSlider + { attack = new Fl_Text_Display(197, 378, 35, 10, gettext("+0.00")); + attack->box(FL_NO_BOX); + attack->labelsize(11); + } // Fl_Text_Display* attack + { attackSlider = new Fl_My_Value_Slider(208, 378, 15, 150, gettext("Attack")); + attackSlider->type(4); + attackSlider->box(FL_NO_BOX); + attackSlider->color(FL_BACKGROUND_COLOR); + attackSlider->selection_color(FL_BACKGROUND_COLOR); + attackSlider->labeltype(FL_NORMAL_LABEL); + attackSlider->labelfont(0); + attackSlider->labelsize(11); + attackSlider->labelcolor(FL_FOREGROUND_COLOR); + attackSlider->minimum(1); + attackSlider->maximum(0); + attackSlider->step(0.001); + attackSlider->value(0.01); + attackSlider->slider_size(0.151515); + attackSlider->callback((Fl_Callback*)cb_attackSlider); + attackSlider->align(Fl_Align(FL_ALIGN_BOTTOM)); + attackSlider->when(FL_WHEN_CHANGED); + attackSlider->default_value = 0.01; + } // Fl_My_Value_Slider* attackSlider + { release = new Fl_Text_Display(267, 378, 35, 10, gettext("+0.00")); + release->box(FL_NO_BOX); + release->labelsize(11); + } // Fl_Text_Display* release + { releaseSlider = new Fl_My_Value_Slider(278, 378, 14, 150, gettext("Release")); + releaseSlider->type(4); + releaseSlider->box(FL_NO_BOX); + releaseSlider->color(FL_BACKGROUND_COLOR); + releaseSlider->selection_color(FL_BACKGROUND_COLOR); + releaseSlider->labeltype(FL_NORMAL_LABEL); + releaseSlider->labelfont(0); + releaseSlider->labelsize(11); + releaseSlider->labelcolor(FL_FOREGROUND_COLOR); + releaseSlider->minimum(10); + releaseSlider->maximum(0); + releaseSlider->step(0.01); + releaseSlider->value(1); + releaseSlider->slider_size(0.151515); + releaseSlider->callback((Fl_Callback*)cb_releaseSlider); + releaseSlider->align(Fl_Align(FL_ALIGN_BOTTOM)); + releaseSlider->when(FL_WHEN_CHANGED); + releaseSlider->default_value = 1.0; + } // Fl_My_Value_Slider* releaseSlider + { makeup = new Fl_Text_Display(334, 378, 35, 10, gettext("+0.0")); + makeup->box(FL_NO_BOX); + makeup->labelsize(11); + } // Fl_Text_Display* makeup + { makeupSlider = new Fl_My_Value_Slider(348, 378, 15, 150, gettext("MakeupGain")); + makeupSlider->type(4); + makeupSlider->box(FL_NO_BOX); + makeupSlider->color(FL_BACKGROUND_COLOR); + makeupSlider->selection_color(FL_BACKGROUND_COLOR); + makeupSlider->labeltype(FL_NORMAL_LABEL); + makeupSlider->labelfont(0); + makeupSlider->labelsize(11); + makeupSlider->labelcolor(FL_FOREGROUND_COLOR); + makeupSlider->minimum(30); + makeupSlider->maximum(0); + makeupSlider->step(0.01); + makeupSlider->value(1); + makeupSlider->slider_size(0.151515); + makeupSlider->callback((Fl_Callback*)cb_makeupSlider); + makeupSlider->align(Fl_Align(FL_ALIGN_BOTTOM)); + makeupSlider->when(FL_WHEN_CHANGED); + } // Fl_My_Value_Slider* makeupSlider + { LED_comp_threshold = new LED(36, 529, 10, 10); + LED_comp_threshold->box(FL_BORDER_BOX); + LED_comp_threshold->color(FL_BACKGROUND_COLOR); + LED_comp_threshold->selection_color(FL_BACKGROUND_COLOR); + LED_comp_threshold->labeltype(FL_NORMAL_LABEL); + LED_comp_threshold->labelfont(0); + LED_comp_threshold->labelsize(14); + LED_comp_threshold->labelcolor(FL_FOREGROUND_COLOR); + LED_comp_threshold->align(Fl_Align(FL_ALIGN_TOP)); + LED_comp_threshold->when(FL_WHEN_RELEASE); + LED_comp_threshold->end(); + } // LED* LED_comp_threshold + o->end(); + } // Fl_Group* o + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(1, 20, 434, 660, gettext("MIDI")); + o->hide(); + { choice_midi_dev = new Fl_Choice(51, 65, 330, 20, gettext("MIDI Device")); + choice_midi_dev->tooltip(gettext("Select your MIDI device")); + choice_midi_dev->down_box(FL_FLAT_BOX); + choice_midi_dev->callback((Fl_Callback*)cb_choice_midi_dev); + choice_midi_dev->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_midi_dev + { button_midi_rescan_devices = new Fl_Button(51, 90, 120, 25, gettext("Rescan")); + button_midi_rescan_devices->tooltip(gettext("Rescan MIDI devices")); + button_midi_rescan_devices->box(FL_ENGRAVED_BOX); + button_midi_rescan_devices->callback((Fl_Callback*)cb_button_midi_rescan_devices); + } // Fl_Button* button_midi_rescan_devices + { LED_midi_command = new LED(336, 95, 10, 10, gettext("MIDI")); + LED_midi_command->tooltip(gettext("MIDI signal indicator")); + LED_midi_command->box(FL_BORDER_BOX); + LED_midi_command->color(FL_BACKGROUND_COLOR); + LED_midi_command->selection_color(FL_BACKGROUND_COLOR); + LED_midi_command->labeltype(FL_NORMAL_LABEL); + LED_midi_command->labelfont(0); + LED_midi_command->labelsize(14); + LED_midi_command->labelcolor(FL_FOREGROUND_COLOR); + LED_midi_command->align(Fl_Align(FL_ALIGN_RIGHT)); + LED_midi_command->when(FL_WHEN_RELEASE); + LED_midi_command->end(); + } // LED* LED_midi_command + { browser_midi_command = new Fl_Browser(51, 165, 330, 190, gettext("MIDI Commands")); + browser_midi_command->type(2); + browser_midi_command->callback((Fl_Callback*)cb_browser_midi_command); + browser_midi_command->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Browser* browser_midi_command + { check_midi_command_enable = new Fl_Check_Button(51, 364, 145, 33, gettext("Enable")); + check_midi_command_enable->tooltip(gettext("Enable/Disable the selected MIDI command")); + check_midi_command_enable->down_box(FL_DOWN_BOX); + check_midi_command_enable->callback((Fl_Callback*)cb_check_midi_command_enable); + } // Fl_Check_Button* check_midi_command_enable + { group_midi_command_settings = new Fl_Group(51, 392, 330, 141); + group_midi_command_settings->box(FL_ENGRAVED_FRAME); + { choice_midi_channel = new Fl_Choice(61, 419, 80, 25, gettext("Channel")); + choice_midi_channel->tooltip(gettext("Select MIDI channel")); + choice_midi_channel->box(FL_ENGRAVED_BOX); + choice_midi_channel->down_box(FL_BORDER_BOX); + choice_midi_channel->callback((Fl_Callback*)cb_choice_midi_channel); + choice_midi_channel->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_midi_channel_i18n_done) { + int i=0; + for ( ; i<17; i++) + if (menu_choice_midi_channel[i].label()) + menu_choice_midi_channel[i].label(gettext(menu_choice_midi_channel[i].label())); + menu_choice_midi_channel_i18n_done = 1; + } + choice_midi_channel->menu(menu_choice_midi_channel); + } // Fl_Choice* choice_midi_channel + { input_midi_msg_num = new Fl_Value_Input(156, 418, 45, 25, gettext("CC")); + input_midi_msg_num->tooltip(gettext("Select CC number")); + input_midi_msg_num->maximum(127); + input_midi_msg_num->callback((Fl_Callback*)cb_input_midi_msg_num); + input_midi_msg_num->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Value_Input* input_midi_msg_num + { button_midi_learn = new Fl_Button(215, 417, 151, 25, gettext("Learn")); + button_midi_learn->tooltip(gettext("Activate to auto detect the channel and CC number")); + button_midi_learn->type(1); + button_midi_learn->box(FL_ENGRAVED_BOX); + button_midi_learn->callback((Fl_Callback*)cb_button_midi_learn); + } // Fl_Button* button_midi_learn + { choice_midi_cc_mode = new Fl_Choice(61, 470, 143, 25, gettext("CC Mode")); + choice_midi_cc_mode->tooltip(gettext("Select CC mode")); + choice_midi_cc_mode->box(FL_ENGRAVED_BOX); + choice_midi_cc_mode->down_box(FL_BORDER_BOX); + choice_midi_cc_mode->callback((Fl_Callback*)cb_choice_midi_cc_mode); + choice_midi_cc_mode->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_midi_cc_mode_i18n_done) { + int i=0; + for ( ; i<4; i++) + if (menu_choice_midi_cc_mode[i].label()) + menu_choice_midi_cc_mode[i].label(gettext(menu_choice_midi_cc_mode[i].label())); + menu_choice_midi_cc_mode_i18n_done = 1; + } + choice_midi_cc_mode->menu(menu_choice_midi_cc_mode); + } // Fl_Choice* choice_midi_cc_mode + { check_midi_soft_takeover = new Fl_Check_Button(60, 494, 145, 33, gettext("Soft takeover")); + check_midi_soft_takeover->tooltip(gettext("Prevents jumps when controlling a slider in absolute mode")); + check_midi_soft_takeover->down_box(FL_DOWN_BOX); + check_midi_soft_takeover->callback((Fl_Callback*)cb_check_midi_soft_takeover); + } // Fl_Check_Button* check_midi_soft_takeover + group_midi_command_settings->end(); + } // Fl_Group* group_midi_command_settings + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(0, 20, 434, 660, gettext("TLS")); + o->hide(); + { Fl_Group* o = new Fl_Group(50, 55, 326, 184, gettext("SSL/TLS")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { Fl_Box* o = new Fl_Box(56, 67, 272, 60, gettext("If your server uses a certificate from\nLet\'s Encrypt or another well known\ +\nCA, you can leave these fields blank.")); + o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); + } // Fl_Box* o + { input_tls_cert_file = new Fl_Input(58, 149, 275, 25, gettext("CA Certificate File:")); + input_tls_cert_file->tooltip(gettext("Certificate file")); + input_tls_cert_file->callback((Fl_Callback*)cb_input_tls_cert_file); + input_tls_cert_file->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_tls_cert_file->maximum_size(500); + } // Fl_Input* input_tls_cert_file + { button_tls_browse_file = new Fl_Button(338, 149, 25, 25); + button_tls_browse_file->tooltip(gettext("Select certificate file")); + button_tls_browse_file->box(FL_ENGRAVED_BOX); + button_tls_browse_file->image( image_folder() ); + button_tls_browse_file->callback((Fl_Callback*)cb_button_tls_browse_file); + } // Fl_Button* button_tls_browse_file + { input_tls_cert_dir = new Fl_Input(58, 200, 275, 25, gettext("CA Certificate Directory:")); + input_tls_cert_dir->tooltip(gettext("Certificate directory")); + input_tls_cert_dir->callback((Fl_Callback*)cb_input_tls_cert_dir); + input_tls_cert_dir->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_tls_cert_dir->maximum_size(500); + } // Fl_Input* input_tls_cert_dir + { button_tls_browse_dir = new Fl_Button(338, 200, 25, 25); + button_tls_browse_dir->tooltip(gettext("Select certificate directory")); + button_tls_browse_dir->box(FL_ENGRAVED_BOX); + button_tls_browse_dir->image( image_folder() ); + button_tls_browse_dir->callback((Fl_Callback*)cb_button_tls_browse_dir); + } // Fl_Button* button_tls_browse_dir + o->end(); + } // Fl_Group* o + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(0, 20, 434, 660, gettext("GUI")); + o->hide(); + { Fl_Group* o = new Fl_Group(45, 58, 129, 42, gettext("Language")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { choice_gui_language = new Fl_Choice(58, 68, 102, 20); + choice_gui_language->down_box(FL_BORDER_BOX); + choice_gui_language->callback((Fl_Callback*)cb_choice_gui_language); + if (!menu_choice_gui_language_i18n_done) { + int i=0; + for ( ; i<8; i++) + if (menu_choice_gui_language[i].label()) + menu_choice_gui_language[i].label(gettext(menu_choice_gui_language[i].label())); + menu_choice_gui_language_i18n_done = 1; + } + choice_gui_language->menu(menu_choice_gui_language); + } // Fl_Choice* choice_gui_language + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(185, 58, 209, 42, gettext("Display Color")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { button_gui_text_color = new Fl_Button(198, 68, 25, 25, gettext("Text")); + button_gui_text_color->tooltip(gettext("Select text color")); + button_gui_text_color->box(FL_SHADOW_BOX); + button_gui_text_color->color(FL_BACKGROUND2_COLOR); + button_gui_text_color->callback((Fl_Callback*)cb_button_gui_text_color); + button_gui_text_color->align(Fl_Align(FL_ALIGN_RIGHT)); + } // Fl_Button* button_gui_text_color + { button_gui_bg_color = new Fl_Button(277, 68, 25, 25, gettext("Background")); + button_gui_bg_color->tooltip(gettext("Select background color")); + button_gui_bg_color->box(FL_SHADOW_BOX); + button_gui_bg_color->color(FL_SELECTION_COLOR); + button_gui_bg_color->callback((Fl_Callback*)cb_button_gui_bg_color); + button_gui_bg_color->align(Fl_Align(FL_ALIGN_RIGHT)); + } // Fl_Button* button_gui_bg_color + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(45, 135, 350, 130, gettext("VU meter")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { radio_gui_vu_gradient = new Fl_Round_Button(56, 150, 144, 15, gettext("Gradient colors")); + radio_gui_vu_gradient->type(102); + radio_gui_vu_gradient->down_box(FL_ROUND_DOWN_BOX); + radio_gui_vu_gradient->callback((Fl_Callback*)cb_radio_gui_vu_gradient); + } // Fl_Round_Button* radio_gui_vu_gradient + { radio_gui_vu_solid = new Fl_Round_Button(56, 175, 139, 15, gettext("Solid colors")); + radio_gui_vu_solid->type(102); + radio_gui_vu_solid->down_box(FL_ROUND_DOWN_BOX); + radio_gui_vu_solid->callback((Fl_Callback*)cb_radio_gui_vu_solid); + } // Fl_Round_Button* radio_gui_vu_solid + { check_gui_always_show_vu_tabs = new Fl_Check_Button(200, 150, 165, 15, gettext("Always show tabs")); + check_gui_always_show_vu_tabs->down_box(FL_DOWN_BOX); + check_gui_always_show_vu_tabs->callback((Fl_Callback*)cb_check_gui_always_show_vu_tabs); + } // Fl_Check_Button* check_gui_always_show_vu_tabs + { button_gui_vu_low_color = new Fl_Button(55, 200, 40, 25); + button_gui_vu_low_color->tooltip(gettext("Select lower range color")); + button_gui_vu_low_color->box(FL_SHADOW_BOX); + button_gui_vu_low_color->color((Fl_Color)61); + button_gui_vu_low_color->callback((Fl_Callback*)cb_button_gui_vu_low_color); + button_gui_vu_low_color->align(Fl_Align(FL_ALIGN_RIGHT)); + } // Fl_Button* button_gui_vu_low_color + { button_gui_vu_mid_color = new Fl_Button(100, 200, 40, 25); + button_gui_vu_mid_color->tooltip(gettext("Select mid range color")); + button_gui_vu_mid_color->box(FL_SHADOW_BOX); + button_gui_vu_mid_color->color((Fl_Color)94); + button_gui_vu_mid_color->callback((Fl_Callback*)cb_button_gui_vu_mid_color); + button_gui_vu_mid_color->align(Fl_Align(FL_ALIGN_RIGHT)); + } // Fl_Button* button_gui_vu_mid_color + { button_gui_vu_high_color = new Fl_Button(145, 200, 40, 25); + button_gui_vu_high_color->tooltip(gettext("Select high range color")); + button_gui_vu_high_color->box(FL_SHADOW_BOX); + button_gui_vu_high_color->color((Fl_Color)80); + button_gui_vu_high_color->callback((Fl_Callback*)cb_button_gui_vu_high_color); + button_gui_vu_high_color->align(Fl_Align(FL_ALIGN_RIGHT)); + } // Fl_Button* button_gui_vu_high_color + { Fl_Value_Output* o = new Fl_Value_Output(55, 236, 40, 19); + o->tooltip(gettext("Low range start value (dB)")); + o->value(-54); + } // Fl_Value_Output* o + { input_gui_vu_mid_range_start = new Fl_Value_Input(100, 236, 40, 19); + input_gui_vu_mid_range_start->tooltip(gettext("Mid range start value (dB)")); + input_gui_vu_mid_range_start->minimum(-54); + input_gui_vu_mid_range_start->maximum(0); + input_gui_vu_mid_range_start->value(-12); + input_gui_vu_mid_range_start->callback((Fl_Callback*)cb_input_gui_vu_mid_range_start); + input_gui_vu_mid_range_start->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + input_gui_vu_mid_range_start->when(FL_WHEN_RELEASE); + } // Fl_Value_Input* input_gui_vu_mid_range_start + { input_gui_vu_high_range_start = new Fl_Value_Input(145, 236, 40, 19); + input_gui_vu_high_range_start->tooltip(gettext("High range start value (dB)")); + input_gui_vu_high_range_start->minimum(-54); + input_gui_vu_high_range_start->maximum(0); + input_gui_vu_high_range_start->value(-6); + input_gui_vu_high_range_start->callback((Fl_Callback*)cb_input_gui_vu_high_range_start); + input_gui_vu_high_range_start->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + input_gui_vu_high_range_start->when(FL_WHEN_RELEASE); + } // Fl_Value_Input* input_gui_vu_high_range_start + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(45, 305, 350, 295, gettext("Misc")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { check_gui_attach = new Fl_Check_Button(56, 314, 300, 20, gettext("Attach settings window to main window")); + check_gui_attach->tooltip(gettext("Attach this window to the butt window")); + check_gui_attach->down_box(FL_DOWN_BOX); + check_gui_attach->callback((Fl_Callback*)cb_check_gui_attach); + } // Fl_Check_Button* check_gui_attach + { check_gui_ontop = new Fl_Check_Button(56, 339, 175, 20, gettext("Stay always on top")); + check_gui_ontop->tooltip(gettext("Stay always on top")); + check_gui_ontop->down_box(FL_DOWN_BOX); + check_gui_ontop->callback((Fl_Callback*)cb_check_gui_ontop); + } // Fl_Check_Button* check_gui_ontop + { check_gui_remember_pos = new Fl_Check_Button(56, 364, 260, 20, gettext("Remember main window position")); + check_gui_remember_pos->tooltip(gettext("Remember main window position")); + check_gui_remember_pos->down_box(FL_DOWN_BOX); + check_gui_remember_pos->callback((Fl_Callback*)cb_check_gui_remember_pos); + } // Fl_Check_Button* check_gui_remember_pos + { check_gui_hide_log_window = new Fl_Check_Button(56, 389, 220, 20, gettext("Hide log window after start up")); + check_gui_hide_log_window->tooltip(gettext("Hide log window after start up")); + check_gui_hide_log_window->down_box(FL_DOWN_BOX); + check_gui_hide_log_window->callback((Fl_Callback*)cb_check_gui_hide_log_window); + } // Fl_Check_Button* check_gui_hide_log_window + { check_gui_lcd_auto = new Fl_Check_Button(56, 414, 295, 20, gettext("Change display mode every 5 seconds")); + check_gui_lcd_auto->tooltip(gettext("Change display mode every 5 seconds")); + check_gui_lcd_auto->down_box(FL_DOWN_BOX); + check_gui_lcd_auto->callback((Fl_Callback*)cb_check_gui_lcd_auto); + } // Fl_Check_Button* check_gui_lcd_auto + { check_gui_start_minimized = new Fl_Check_Button(56, 439, 149, 20, gettext("Start minimized")); + check_gui_start_minimized->tooltip(gettext("Minimize butt at startup")); + check_gui_start_minimized->down_box(FL_DOWN_BOX); + check_gui_start_minimized->callback((Fl_Callback*)cb_check_gui_start_minimized); + } // Fl_Check_Button* check_gui_start_minimized + { check_gui_disable_gain_slider = new Fl_Check_Button(56, 464, 194, 20, gettext("Disable gain control")); + check_gui_disable_gain_slider->down_box(FL_DOWN_BOX); + check_gui_disable_gain_slider->callback((Fl_Callback*)cb_check_gui_disable_gain_slider); + } // Fl_Check_Button* check_gui_disable_gain_slider + { Fl_Group* o = new Fl_Group(56, 489, 324, 50); + o->box(FL_ENGRAVED_FRAME); + { check_gui_show_listeners = new Fl_Check_Button(61, 493, 194, 23, gettext("Show listeners")); + check_gui_show_listeners->tooltip(gettext("Show current listeners in the display (not always available)")); + check_gui_show_listeners->down_box(FL_DOWN_BOX); + check_gui_show_listeners->callback((Fl_Callback*)cb_check_gui_show_listeners); + } // Fl_Check_Button* check_gui_show_listeners + { input_gui_listeners_update_rate = new Fl_Value_Input(263, 513, 42, 19, gettext("Update rate:")); + input_gui_listeners_update_rate->callback((Fl_Callback*)cb_input_gui_listeners_update_rate); + input_gui_listeners_update_rate->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + input_gui_listeners_update_rate->when(FL_WHEN_RELEASE); + } // Fl_Value_Input* input_gui_listeners_update_rate + { Fl_Box* o = new Fl_Box(305, 514, 70, 17, gettext("seconds")); + o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); + } // Fl_Box* o + o->end(); + } // Fl_Group* o + { input_gui_window_title = new Fl_Input(55, 566, 325, 25, gettext("Custom window title:")); + input_gui_window_title->tooltip(gettext("Define a custom window title")); + input_gui_window_title->callback((Fl_Callback*)cb_input_gui_window_title); + input_gui_window_title->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + input_gui_window_title->when(FL_WHEN_CHANGED); + this->input_gui_window_title->maximum_size(500); + } // Fl_Input* input_gui_window_title + o->end(); + } // Fl_Group* o + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(0, 20, 434, 660, gettext("Donate")); + o->hide(); + { Fl_Group* o = new Fl_Group(55, 70, 326, 360, gettext("Donation")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { Fl_Box* o = new Fl_Box(67, 75, 308, 150, gettext("Keeping this software up to date, adding\nnew features and answering support \ +mails\ntakes a lot of time and effort. If you can\nafford it, please consider \ +supporting this\nproject.\n\nThank you!")); + o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); + } // Fl_Box* o + { Fl_Button* o = new Fl_Button(67, 225, 300, 28, gettext("&Donate via PayPal")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Donate); + } // Fl_Button* o + { Fl_Button* o = new Fl_Button(67, 272, 300, 27, gettext("Become a &patron")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Become); + } // Fl_Button* o + { Fl_Button* o = new Fl_Button(67, 317, 300, 28, gettext("&Apple Pay, Google Pay, CC and more")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Apple); + } // Fl_Button* o + { Fl_Button* o = new Fl_Button(67, 361, 300, 28, gettext("&Bitcoin && Co")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Bitcoin); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + o->end(); + } // Fl_Group* o + Settings->end(); + } // Fl_Tabs* Settings + window_cfg->size_range(430, 640, 430, 680); + window_cfg->end(); + } // Fl_My_Double_Window* window_cfg + { window_add_srv = new Fl_Double_Window(395, 522, gettext("Add server")); + window_add_srv->user_data((void*)(this)); + { input_add_srv_name = new Fl_Input(70, 27, 245, 23, gettext("Name:")); + input_add_srv_name->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_add_srv_name->maximum_size(100); + } // Fl_Input* input_add_srv_name + { input_add_srv_addr = new Fl_Input(10, 216, 295, 25, gettext("Address:")); + input_add_srv_addr->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_add_srv_addr->maximum_size(100); + } // Fl_Input* input_add_srv_addr + { input_add_srv_port = new Fl_Int_Input(315, 216, 75, 25, gettext("Port:")); + input_add_srv_port->type(2); + input_add_srv_port->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Int_Input* input_add_srv_port + { input_add_srv_pwd = new Fl_Input(10, 261, 295, 25, gettext("Password:")); + input_add_srv_pwd->type(5); + input_add_srv_pwd->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_add_srv_pwd->maximum_size(100); + } // Fl_Input* input_add_srv_pwd + { input_add_srv_mount = new Fl_Input(10, 311, 215, 25, gettext("Icecast mountpoint:")); + input_add_srv_mount->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_add_srv_mount->maximum_size(100); + } // Fl_Input* input_add_srv_mount + { input_add_srv_usr = new Fl_Input(235, 311, 155, 25, gettext("Icecast user:")); + input_add_srv_usr->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_add_srv_usr->maximum_size(100); + } // Fl_Input* input_add_srv_usr + { button_cfg_show_pw = new Fl_Button(315, 261, 75, 25, gettext("Show")); + button_cfg_show_pw->tooltip(gettext("show/hide password")); + button_cfg_show_pw->box(FL_ENGRAVED_BOX); + button_cfg_show_pw->callback((Fl_Callback*)cb_button_cfg_show_pw); + } // Fl_Button* button_cfg_show_pw + { Fl_Group* o = new Fl_Group(10, 96, 125, 97, gettext("Type")); + o->box(FL_ENGRAVED_BOX); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { radio_add_srv_shoutcast = new Fl_Round_Button(15, 105, 88, 15, gettext("Shoutcast")); + radio_add_srv_shoutcast->type(102); + radio_add_srv_shoutcast->down_box(FL_ROUND_DOWN_BOX); + radio_add_srv_shoutcast->callback((Fl_Callback*)cb_radio_add_srv_shoutcast); + } // Fl_Round_Button* radio_add_srv_shoutcast + { radio_add_srv_icecast = new Fl_Round_Button(15, 127, 80, 12, gettext("Icecast")); + radio_add_srv_icecast->type(102); + radio_add_srv_icecast->down_box(FL_ROUND_DOWN_BOX); + radio_add_srv_icecast->callback((Fl_Callback*)cb_radio_add_srv_icecast); + } // Fl_Round_Button* radio_add_srv_icecast + { radio_add_srv_webrtc = new Fl_Round_Button(15, 149, 80, 12, gettext("WebRTC")); + radio_add_srv_webrtc->type(102); + radio_add_srv_webrtc->down_box(FL_ROUND_DOWN_BOX); + radio_add_srv_webrtc->callback((Fl_Callback*)cb_radio_add_srv_webrtc); + } // Fl_Round_Button* radio_add_srv_webrtc + { radio_add_srv_radioco = new Fl_Round_Button(15, 171, 80, 12, gettext("Radio.co")); + radio_add_srv_radioco->type(102); + radio_add_srv_radioco->down_box(FL_ROUND_DOWN_BOX); + radio_add_srv_radioco->callback((Fl_Callback*)cb_radio_add_srv_radioco); + } // Fl_Round_Button* radio_add_srv_radioco + o->end(); + } // Fl_Group* o + { Fl_Button* o = new Fl_Button(10, 478, 85, 25, gettext("&Cancel")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Cancel); + } // Fl_Button* o + { button_add_srv_add = new Fl_Button(305, 478, 85, 25, gettext("&ADD")); + button_add_srv_add->box(FL_ENGRAVED_BOX); + button_add_srv_add->callback((Fl_Callback*)cb_button_add_srv_add); + } // Fl_Button* button_add_srv_add + { button_add_srv_save = new Fl_Button(305, 478, 85, 25, gettext("&Save")); + button_add_srv_save->box(FL_ENGRAVED_BOX); + button_add_srv_save->callback((Fl_Callback*)cb_button_add_srv_save); + } // Fl_Button* button_add_srv_save + { frame_add_srv_tls = new Fl_Group(140, 96, 250, 97, gettext("SSL/TLS")); + frame_add_srv_tls->box(FL_ENGRAVED_BOX); + frame_add_srv_tls->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { check_add_srv_tls = new Fl_Check_Button(148, 100, 190, 20, gettext("Use SSL/TLS")); + check_add_srv_tls->down_box(FL_DOWN_BOX); + } // Fl_Check_Button* check_add_srv_tls + { button_add_srv_revoke_cert = new Fl_Button(150, 157, 225, 25, gettext("Revoke certificate trust")); + button_add_srv_revoke_cert->box(FL_ENGRAVED_BOX); + button_add_srv_revoke_cert->callback((Fl_Callback*)cb_button_add_srv_revoke_cert); + } // Fl_Button* button_add_srv_revoke_cert + frame_add_srv_tls->end(); + } // Fl_Group* frame_add_srv_tls + { browser_add_srv_station_list = new Fl_Check_Browser(140, 216, 250, 83, gettext("Radio.co Stations")); + browser_add_srv_station_list->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Check_Browser* browser_add_srv_station_list + { button_add_srv_get_stations = new Fl_Button(10, 205, 120, 25, gettext("Get Stations")); + button_add_srv_get_stations->box(FL_ENGRAVED_BOX); + button_add_srv_get_stations->callback((Fl_Callback*)cb_button_add_srv_get_stations); + } // Fl_Button* button_add_srv_get_stations + { button_add_srv_select_all = new Fl_Button(140, 301, 120, 20, gettext("Select all")); + button_add_srv_select_all->box(FL_ENGRAVED_BOX); + button_add_srv_select_all->callback((Fl_Callback*)cb_button_add_srv_select_all); + } // Fl_Button* button_add_srv_select_all + { button_add_srv_deselect_all = new Fl_Button(265, 301, 125, 20, gettext("Deselect all")); + button_add_srv_deselect_all->box(FL_ENGRAVED_BOX); + button_add_srv_deselect_all->callback((Fl_Callback*)cb_button_add_srv_deselect_all); + } // Fl_Button* button_add_srv_deselect_all + { check_add_srv_protocol = new Fl_Check_Button(8, 345, 297, 15, gettext("Use legacy Icecast protocol")); + check_add_srv_protocol->tooltip(gettext("Activate this if you want to use the older SOURCE protocol instead of the new\ +er PUT protocol")); + check_add_srv_protocol->down_box(FL_DOWN_BOX); + } // Fl_Check_Button* check_add_srv_protocol + { input_webrtc_icesrv_url = new Fl_Input(10, 215, 380, 25, gettext("ICE server (optional):")); + input_webrtc_icesrv_url->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Input* input_webrtc_icesrv_url + { input_webrtc_whip_url = new Fl_Input(10, 260, 380, 25, gettext("WebRTC (WHIP) URL:")); + input_webrtc_whip_url->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Input* input_webrtc_whip_url + { input_webrtc_auth_token = new Fl_Input(10, 305, 380, 25, gettext("Bearer token (optional):")); + input_webrtc_auth_token->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Input* input_webrtc_auth_token + { input_add_srv_listener_url = new Fl_Input(10, 393, 380, 25, gettext("Custom listener URL (optional):")); + input_add_srv_listener_url->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_add_srv_listener_url->maximum_size(100); + } // Fl_Input* input_add_srv_listener_url + { input_add_srv_listener_mount = new Fl_Input(10, 441, 380, 25, gettext("Custom listener mountpoint (optional):")); + input_add_srv_listener_mount->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_add_srv_listener_mount->maximum_size(100); + } // Fl_Input* input_add_srv_listener_mount + window_add_srv->set_modal(); + window_add_srv->end(); + } // Fl_Double_Window* window_add_srv + { window_add_icy = new Fl_Double_Window(305, 380, gettext("Add stream info")); + window_add_icy->user_data((void*)(this)); + { input_add_icy_name = new Fl_Input(10, 35, 285, 25, gettext("Name:")); + input_add_icy_name->tooltip(gettext("The name of your new ICY-entrie")); + input_add_icy_name->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_add_icy_name->maximum_size(100); + } // Fl_Input* input_add_icy_name + { input_add_icy_desc = new Fl_Input(10, 145, 170, 25, gettext("Description:")); + input_add_icy_desc->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_add_icy_desc->maximum_size(100); + } // Fl_Input* input_add_icy_desc + { input_add_icy_genre = new Fl_Input(185, 145, 110, 25, gettext("Genre:")); + input_add_icy_genre->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_add_icy_genre->maximum_size(100); + } // Fl_Input* input_add_icy_genre + { input_add_icy_url = new Fl_Input(10, 190, 170, 25, gettext("URL:")); + input_add_icy_url->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_add_icy_url->maximum_size(100); + } // Fl_Input* input_add_icy_url + { input_add_icy_icq = new Fl_Input(185, 190, 110, 25, gettext("ICQ:")); + input_add_icy_icq->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_add_icy_icq->maximum_size(100); + } // Fl_Input* input_add_icy_icq + { input_add_icy_irc = new Fl_Input(10, 235, 170, 25, gettext("IRC:")); + input_add_icy_irc->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_add_icy_irc->maximum_size(100); + } // Fl_Input* input_add_icy_irc + { input_add_icy_aim = new Fl_Input(185, 235, 110, 25, gettext("AIM:")); + input_add_icy_aim->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + this->input_add_icy_aim->maximum_size(100); + } // Fl_Input* input_add_icy_aim + { check_add_icy_pub = new Fl_Check_Button(10, 270, 235, 20, gettext("Make server public")); + check_add_icy_pub->down_box(FL_DOWN_BOX); + } // Fl_Check_Button* check_add_icy_pub + { check_expand_variables = new Fl_Check_Button(10, 295, 235, 20, gettext("Expand variables")); + check_expand_variables->tooltip(gettext("Activate to expand date variables in name and description")); + check_expand_variables->down_box(FL_DOWN_BOX); + } // Fl_Check_Button* check_expand_variables + { Fl_Button* o = new Fl_Button(10, 340, 74, 25, gettext("&Cancel")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Cancel1); + } // Fl_Button* o + { button_add_icy_add = new Fl_Button(224, 340, 74, 25, gettext("&ADD")); + button_add_icy_add->box(FL_ENGRAVED_BOX); + button_add_icy_add->callback((Fl_Callback*)cb_button_add_icy_add); + } // Fl_Button* button_add_icy_add + { button_add_icy_save = new Fl_Button(224, 340, 74, 25, gettext("&Save")); + button_add_icy_save->box(FL_ENGRAVED_BOX); + button_add_icy_save->callback((Fl_Callback*)cb_button_add_icy_save); + } // Fl_Button* button_add_icy_save + window_add_icy->set_modal(); + window_add_icy->end(); + } // Fl_Double_Window* window_add_icy + Fl::scheme("standard"); + window_main->label(PACKAGE_STRING); + + info_buffer = new Fl_Text_Buffer(); + info_output->buffer(info_buffer); + + //window_cfg->size(window_cfg->w(), 380); + + // show info output... + info_visible = 1; + + info_output->show(); + { window_donate_crypto = new Fl_My_Double_Window(460, 255, gettext("Donate Cryptocurrency")); + window_donate_crypto->box(FL_FLAT_BOX); + window_donate_crypto->color(FL_BACKGROUND_COLOR); + window_donate_crypto->selection_color(FL_BACKGROUND_COLOR); + window_donate_crypto->labeltype(FL_NO_LABEL); + window_donate_crypto->labelfont(0); + window_donate_crypto->labelsize(14); + window_donate_crypto->labelcolor(FL_FOREGROUND_COLOR); + window_donate_crypto->user_data((void*)(this)); + window_donate_crypto->align(Fl_Align(FL_ALIGN_TOP)); + window_donate_crypto->when(FL_WHEN_RELEASE); + { output_bitcoin_addr = new Fl_Output(20, 40, 320, 22, gettext("Bitcoin")); + output_bitcoin_addr->box(FL_FLAT_BOX); + output_bitcoin_addr->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + output_bitcoin_addr->value("bc1q4uq7h464rsu2cudrmuuqmc4tcr98d0edrhe5au"); + } // Fl_Output* output_bitcoin_addr + { Fl_Button* o = new Fl_Button(350, 40, 88, 22, gettext("Copy")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Copy); + } // Fl_Button* o + { output_litecoin_addr = new Fl_Output(20, 100, 320, 22, gettext("Litecoin")); + output_litecoin_addr->box(FL_FLAT_BOX); + output_litecoin_addr->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + output_litecoin_addr->value("Ld9gntf8fsYpmVcbstFkzz5R3sNPC3AhTx"); + } // Fl_Output* output_litecoin_addr + { Fl_Button* o = new Fl_Button(350, 100, 88, 22, gettext("Copy")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Copy1); + } // Fl_Button* o + { output_monero_addr = new Fl_Output(20, 160, 320, 22, gettext("Monero")); + output_monero_addr->box(FL_FLAT_BOX); + output_monero_addr->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + output_monero_addr->value("85u8DacasxPNvKzY5kEiprBnbydDqg26yGAVEw7mdwccNFsrXMWCE4VQnV2JVfh5BTRheNnpDJqYjbqPrVRLEPAKP3dsYgc"); + } // Fl_Output* output_monero_addr + { Fl_Button* o = new Fl_Button(350, 160, 88, 22, gettext("Copy")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Copy2); + } // Fl_Button* o + { Fl_Button* o = new Fl_Button(20, 217, 88, 22, gettext("&Close")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Close); + } // Fl_Button* o + window_donate_crypto->end(); + } // Fl_My_Double_Window* window_donate_crypto + { window_stream_codec_settings = new Fl_My_Double_Window(395, 385, gettext("Streaming Codec Settings")); + window_stream_codec_settings->box(FL_FLAT_BOX); + window_stream_codec_settings->color(FL_BACKGROUND_COLOR); + window_stream_codec_settings->selection_color(FL_BACKGROUND_COLOR); + window_stream_codec_settings->labeltype(FL_NO_LABEL); + window_stream_codec_settings->labelfont(0); + window_stream_codec_settings->labelsize(14); + window_stream_codec_settings->labelcolor(FL_FOREGROUND_COLOR); + window_stream_codec_settings->user_data((void*)(this)); + window_stream_codec_settings->align(Fl_Align(FL_ALIGN_TOP)); + window_stream_codec_settings->when(FL_WHEN_RELEASE); + { tabs_stream_codec_settings = new Fl_Tabs(5, 0, 385, 350); + { tab_stream_mp3 = new Fl_Group(5, 20, 385, 330, gettext("MP3")); + { choice_stream_mp3_enc_quality = new Fl_Choice(25, 50, 165, 20, gettext("Encoding Quality")); + choice_stream_mp3_enc_quality->down_box(FL_BORDER_BOX); + choice_stream_mp3_enc_quality->callback((Fl_Callback*)cb_choice_stream_mp3_enc_quality); + choice_stream_mp3_enc_quality->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_mp3_enc_quality_i18n_done) { + int i=0; + for ( ; i<10; i++) + if (menu_choice_stream_mp3_enc_quality[i].label()) + menu_choice_stream_mp3_enc_quality[i].label(gettext(menu_choice_stream_mp3_enc_quality[i].label())); + menu_choice_stream_mp3_enc_quality_i18n_done = 1; + } + choice_stream_mp3_enc_quality->menu(menu_choice_stream_mp3_enc_quality); + } // Fl_Choice* choice_stream_mp3_enc_quality + { choice_stream_mp3_stereo_mode = new Fl_Choice(210, 50, 165, 20, gettext("Stereo Mode")); + choice_stream_mp3_stereo_mode->down_box(FL_BORDER_BOX); + choice_stream_mp3_stereo_mode->callback((Fl_Callback*)cb_choice_stream_mp3_stereo_mode); + choice_stream_mp3_stereo_mode->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_mp3_stereo_mode_i18n_done) { + int i=0; + for ( ; i<3; i++) + if (menu_choice_stream_mp3_stereo_mode[i].label()) + menu_choice_stream_mp3_stereo_mode[i].label(gettext(menu_choice_stream_mp3_stereo_mode[i].label())); + menu_choice_stream_mp3_stereo_mode_i18n_done = 1; + } + choice_stream_mp3_stereo_mode->menu(menu_choice_stream_mp3_stereo_mode); + } // Fl_Choice* choice_stream_mp3_stereo_mode + { choice_stream_mp3_bitrate_mode = new Fl_Choice(25, 110, 165, 20, gettext("Bitrate Mode")); + choice_stream_mp3_bitrate_mode->down_box(FL_BORDER_BOX); + choice_stream_mp3_bitrate_mode->callback((Fl_Callback*)cb_choice_stream_mp3_bitrate_mode); + choice_stream_mp3_bitrate_mode->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_mp3_bitrate_mode_i18n_done) { + int i=0; + for ( ; i<3; i++) + if (menu_choice_stream_mp3_bitrate_mode[i].label()) + menu_choice_stream_mp3_bitrate_mode[i].label(gettext(menu_choice_stream_mp3_bitrate_mode[i].label())); + menu_choice_stream_mp3_bitrate_mode_i18n_done = 1; + } + choice_stream_mp3_bitrate_mode->menu(menu_choice_stream_mp3_bitrate_mode); + } // Fl_Choice* choice_stream_mp3_bitrate_mode + { Fl_Group* o = new Fl_Group(19, 167, 125, 162, gettext("VBR")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { choice_stream_mp3_vbr_quality = new Fl_Choice(27, 191, 110, 20, gettext("Quality")); + choice_stream_mp3_vbr_quality->down_box(FL_BORDER_BOX); + choice_stream_mp3_vbr_quality->callback((Fl_Callback*)cb_choice_stream_mp3_vbr_quality); + choice_stream_mp3_vbr_quality->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_mp3_vbr_quality_i18n_done) { + int i=0; + for ( ; i<10; i++) + if (menu_choice_stream_mp3_vbr_quality[i].label()) + menu_choice_stream_mp3_vbr_quality[i].label(gettext(menu_choice_stream_mp3_vbr_quality[i].label())); + menu_choice_stream_mp3_vbr_quality_i18n_done = 1; + } + choice_stream_mp3_vbr_quality->menu(menu_choice_stream_mp3_vbr_quality); + } // Fl_Choice* choice_stream_mp3_vbr_quality + { choice_stream_mp3_vbr_min_bitrate = new Fl_Choice(27, 236, 110, 20, gettext("Min. Bitrate")); + choice_stream_mp3_vbr_min_bitrate->down_box(FL_BORDER_BOX); + choice_stream_mp3_vbr_min_bitrate->callback((Fl_Callback*)cb_choice_stream_mp3_vbr_min_bitrate); + choice_stream_mp3_vbr_min_bitrate->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_mp3_vbr_min_bitrate_i18n_done) { + int i=0; + for ( ; i<17; i++) + if (menu_choice_stream_mp3_vbr_min_bitrate[i].label()) + menu_choice_stream_mp3_vbr_min_bitrate[i].label(gettext(menu_choice_stream_mp3_vbr_min_bitrate[i].label())); + menu_choice_stream_mp3_vbr_min_bitrate_i18n_done = 1; + } + choice_stream_mp3_vbr_min_bitrate->menu(menu_choice_stream_mp3_vbr_min_bitrate); + } // Fl_Choice* choice_stream_mp3_vbr_min_bitrate + { choice_stream_mp3_vbr_max_bitrate = new Fl_Choice(27, 301, 110, 20, gettext("Max. Bitrate")); + choice_stream_mp3_vbr_max_bitrate->down_box(FL_BORDER_BOX); + choice_stream_mp3_vbr_max_bitrate->callback((Fl_Callback*)cb_choice_stream_mp3_vbr_max_bitrate); + choice_stream_mp3_vbr_max_bitrate->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_mp3_vbr_max_bitrate_i18n_done) { + int i=0; + for ( ; i<17; i++) + if (menu_choice_stream_mp3_vbr_max_bitrate[i].label()) + menu_choice_stream_mp3_vbr_max_bitrate[i].label(gettext(menu_choice_stream_mp3_vbr_max_bitrate[i].label())); + menu_choice_stream_mp3_vbr_max_bitrate_i18n_done = 1; + } + choice_stream_mp3_vbr_max_bitrate->menu(menu_choice_stream_mp3_vbr_max_bitrate); + } // Fl_Choice* choice_stream_mp3_vbr_max_bitrate + { check_stream_mp3_force_min_bitrate = new Fl_Check_Button(25, 259, 117, 15, gettext("Force")); + check_stream_mp3_force_min_bitrate->tooltip(gettext("Strictly enforce mininum Bitrate (-F option of the lame encoder)")); + check_stream_mp3_force_min_bitrate->down_box(FL_DOWN_BOX); + check_stream_mp3_force_min_bitrate->callback((Fl_Callback*)cb_check_stream_mp3_force_min_bitrate); + } // Fl_Check_Button* check_stream_mp3_force_min_bitrate + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(155, 167, 105, 162, gettext("Lowpass (kHz)")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { input_stream_mp3_lowpass_freq = new Fl_Value_Input(180, 190, 70, 20, gettext("Frequency")); + input_stream_mp3_lowpass_freq->callback((Fl_Callback*)cb_input_stream_mp3_lowpass_freq); + input_stream_mp3_lowpass_freq->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + input_stream_mp3_lowpass_freq->when(FL_WHEN_RELEASE); + input_stream_mp3_lowpass_freq->deactivate(); + } // Fl_Value_Input* input_stream_mp3_lowpass_freq + { input_stream_mp3_lowpass_width = new Fl_Value_Input(180, 235, 70, 20, gettext("Width")); + input_stream_mp3_lowpass_width->callback((Fl_Callback*)cb_input_stream_mp3_lowpass_width); + input_stream_mp3_lowpass_width->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + input_stream_mp3_lowpass_width->when(FL_WHEN_RELEASE); + input_stream_mp3_lowpass_width->deactivate(); + } // Fl_Value_Input* input_stream_mp3_lowpass_width + { check_stream_mp3_activate_lowpass_freq = new Fl_Check_Button(159, 193, 20, 15); + check_stream_mp3_activate_lowpass_freq->down_box(FL_DOWN_BOX); + check_stream_mp3_activate_lowpass_freq->callback((Fl_Callback*)cb_check_stream_mp3_activate_lowpass_freq); + } // Fl_Check_Button* check_stream_mp3_activate_lowpass_freq + { check_stream_mp3_activate_lowpass_width = new Fl_Check_Button(159, 238, 20, 15); + check_stream_mp3_activate_lowpass_width->down_box(FL_DOWN_BOX); + check_stream_mp3_activate_lowpass_width->callback((Fl_Callback*)cb_check_stream_mp3_activate_lowpass_width); + } // Fl_Check_Button* check_stream_mp3_activate_lowpass_width + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(270, 167, 105, 162, gettext("Highpass (kHz)")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { input_stream_mp3_highpass_freq = new Fl_Value_Input(295, 189, 70, 20, gettext("Frequency")); + input_stream_mp3_highpass_freq->callback((Fl_Callback*)cb_input_stream_mp3_highpass_freq); + input_stream_mp3_highpass_freq->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + input_stream_mp3_highpass_freq->when(FL_WHEN_RELEASE); + input_stream_mp3_highpass_freq->deactivate(); + } // Fl_Value_Input* input_stream_mp3_highpass_freq + { input_stream_mp3_highpass_width = new Fl_Value_Input(295, 234, 70, 20, gettext("Width")); + input_stream_mp3_highpass_width->callback((Fl_Callback*)cb_input_stream_mp3_highpass_width); + input_stream_mp3_highpass_width->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + input_stream_mp3_highpass_width->when(FL_WHEN_RELEASE); + input_stream_mp3_highpass_width->deactivate(); + } // Fl_Value_Input* input_stream_mp3_highpass_width + { check_stream_mp3_activate_highpass_freq = new Fl_Check_Button(274, 192, 20, 15); + check_stream_mp3_activate_highpass_freq->down_box(FL_DOWN_BOX); + check_stream_mp3_activate_highpass_freq->callback((Fl_Callback*)cb_check_stream_mp3_activate_highpass_freq); + } // Fl_Check_Button* check_stream_mp3_activate_highpass_freq + { check_stream_mp3_activate_highpass_width = new Fl_Check_Button(274, 237, 20, 15); + check_stream_mp3_activate_highpass_width->down_box(FL_DOWN_BOX); + check_stream_mp3_activate_highpass_width->callback((Fl_Callback*)cb_check_stream_mp3_activate_highpass_width); + } // Fl_Check_Button* check_stream_mp3_activate_highpass_width + o->end(); + } // Fl_Group* o + { choice_stream_mp3_resampling_freq = new Fl_Choice(210, 110, 165, 20, gettext("Resampling")); + choice_stream_mp3_resampling_freq->tooltip(gettext("Resample to the selected sample rate")); + choice_stream_mp3_resampling_freq->down_box(FL_BORDER_BOX); + choice_stream_mp3_resampling_freq->callback((Fl_Callback*)cb_choice_stream_mp3_resampling_freq); + choice_stream_mp3_resampling_freq->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_mp3_resampling_freq_i18n_done) { + int i=0; + for ( ; i<10; i++) + if (menu_choice_stream_mp3_resampling_freq[i].label()) + menu_choice_stream_mp3_resampling_freq[i].label(gettext(menu_choice_stream_mp3_resampling_freq[i].label())); + menu_choice_stream_mp3_resampling_freq_i18n_done = 1; + } + choice_stream_mp3_resampling_freq->menu(menu_choice_stream_mp3_resampling_freq); + } // Fl_Choice* choice_stream_mp3_resampling_freq + tab_stream_mp3->end(); + } // Fl_Group* tab_stream_mp3 + { tab_stream_ogg = new Fl_Group(5, 20, 385, 330, gettext("OGG")); + tab_stream_ogg->hide(); + { choice_stream_vorbis_bitrate_mode = new Fl_Choice(25, 50, 165, 20, gettext("Bitrate Mode")); + choice_stream_vorbis_bitrate_mode->down_box(FL_BORDER_BOX); + choice_stream_vorbis_bitrate_mode->callback((Fl_Callback*)cb_choice_stream_vorbis_bitrate_mode); + choice_stream_vorbis_bitrate_mode->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_vorbis_bitrate_mode_i18n_done) { + int i=0; + for ( ; i<3; i++) + if (menu_choice_stream_vorbis_bitrate_mode[i].label()) + menu_choice_stream_vorbis_bitrate_mode[i].label(gettext(menu_choice_stream_vorbis_bitrate_mode[i].label())); + menu_choice_stream_vorbis_bitrate_mode_i18n_done = 1; + } + choice_stream_vorbis_bitrate_mode->menu(menu_choice_stream_vorbis_bitrate_mode); + } // Fl_Choice* choice_stream_vorbis_bitrate_mode + { choice_stream_vorbis_vbr_quality = new Fl_Choice(210, 50, 165, 20, gettext("VBR Quality")); + choice_stream_vorbis_vbr_quality->down_box(FL_BORDER_BOX); + choice_stream_vorbis_vbr_quality->callback((Fl_Callback*)cb_choice_stream_vorbis_vbr_quality); + choice_stream_vorbis_vbr_quality->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_vorbis_vbr_quality_i18n_done) { + int i=0; + for ( ; i<11; i++) + if (menu_choice_stream_vorbis_vbr_quality[i].label()) + menu_choice_stream_vorbis_vbr_quality[i].label(gettext(menu_choice_stream_vorbis_vbr_quality[i].label())); + menu_choice_stream_vorbis_vbr_quality_i18n_done = 1; + } + choice_stream_vorbis_vbr_quality->menu(menu_choice_stream_vorbis_vbr_quality); + } // Fl_Choice* choice_stream_vorbis_vbr_quality + { choice_stream_vorbis_vbr_min_bitrate = new Fl_Choice(25, 110, 165, 20, gettext("VBR min. Bitrate")); + choice_stream_vorbis_vbr_min_bitrate->down_box(FL_BORDER_BOX); + choice_stream_vorbis_vbr_min_bitrate->callback((Fl_Callback*)cb_choice_stream_vorbis_vbr_min_bitrate); + choice_stream_vorbis_vbr_min_bitrate->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_stream_vorbis_vbr_min_bitrate + { choice_stream_vorbis_vbr_max_bitrate = new Fl_Choice(210, 110, 165, 20, gettext("VBR max. Bitrate")); + choice_stream_vorbis_vbr_max_bitrate->down_box(FL_BORDER_BOX); + choice_stream_vorbis_vbr_max_bitrate->callback((Fl_Callback*)cb_choice_stream_vorbis_vbr_max_bitrate); + choice_stream_vorbis_vbr_max_bitrate->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_stream_vorbis_vbr_max_bitrate + tab_stream_ogg->end(); + } // Fl_Group* tab_stream_ogg + { tab_stream_opus = new Fl_Group(5, 20, 385, 330, gettext("OPUS")); + tab_stream_opus->hide(); + { choice_stream_opus_quality = new Fl_Choice(25, 50, 165, 20, gettext("Quality")); + choice_stream_opus_quality->down_box(FL_BORDER_BOX); + choice_stream_opus_quality->callback((Fl_Callback*)cb_choice_stream_opus_quality); + choice_stream_opus_quality->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_opus_quality_i18n_done) { + int i=0; + for ( ; i<11; i++) + if (menu_choice_stream_opus_quality[i].label()) + menu_choice_stream_opus_quality[i].label(gettext(menu_choice_stream_opus_quality[i].label())); + menu_choice_stream_opus_quality_i18n_done = 1; + } + choice_stream_opus_quality->menu(menu_choice_stream_opus_quality); + } // Fl_Choice* choice_stream_opus_quality + { choice_stream_opus_audio_type = new Fl_Choice(210, 50, 165, 20, gettext("Optimize for")); + choice_stream_opus_audio_type->down_box(FL_BORDER_BOX); + choice_stream_opus_audio_type->callback((Fl_Callback*)cb_choice_stream_opus_audio_type); + choice_stream_opus_audio_type->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_opus_audio_type_i18n_done) { + int i=0; + for ( ; i<2; i++) + if (menu_choice_stream_opus_audio_type[i].label()) + menu_choice_stream_opus_audio_type[i].label(gettext(menu_choice_stream_opus_audio_type[i].label())); + menu_choice_stream_opus_audio_type_i18n_done = 1; + } + choice_stream_opus_audio_type->menu(menu_choice_stream_opus_audio_type); + } // Fl_Choice* choice_stream_opus_audio_type + { choice_stream_opus_bitrate_mode = new Fl_Choice(25, 110, 165, 20, gettext("Bitrate Mode")); + choice_stream_opus_bitrate_mode->down_box(FL_BORDER_BOX); + choice_stream_opus_bitrate_mode->callback((Fl_Callback*)cb_choice_stream_opus_bitrate_mode); + choice_stream_opus_bitrate_mode->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_opus_bitrate_mode_i18n_done) { + int i=0; + for ( ; i<2; i++) + if (menu_choice_stream_opus_bitrate_mode[i].label()) + menu_choice_stream_opus_bitrate_mode[i].label(gettext(menu_choice_stream_opus_bitrate_mode[i].label())); + menu_choice_stream_opus_bitrate_mode_i18n_done = 1; + } + choice_stream_opus_bitrate_mode->menu(menu_choice_stream_opus_bitrate_mode); + } // Fl_Choice* choice_stream_opus_bitrate_mode + { choice_stream_opus_bandwidth = new Fl_Choice(210, 110, 165, 20, gettext("Max. Bandwidth")); + choice_stream_opus_bandwidth->down_box(FL_BORDER_BOX); + choice_stream_opus_bandwidth->callback((Fl_Callback*)cb_choice_stream_opus_bandwidth); + choice_stream_opus_bandwidth->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_opus_bandwidth_i18n_done) { + int i=0; + for ( ; i<5; i++) + if (menu_choice_stream_opus_bandwidth[i].label()) + menu_choice_stream_opus_bandwidth[i].label(gettext(menu_choice_stream_opus_bandwidth[i].label())); + menu_choice_stream_opus_bandwidth_i18n_done = 1; + } + choice_stream_opus_bandwidth->menu(menu_choice_stream_opus_bandwidth); + } // Fl_Choice* choice_stream_opus_bandwidth + tab_stream_opus->end(); + } // Fl_Group* tab_stream_opus + { tab_stream_aac = new Fl_Group(5, 20, 385, 330, gettext("AAC")); + tab_stream_aac->hide(); + { choice_stream_aac_profile = new Fl_Choice(25, 50, 165, 20, gettext("Profile")); + choice_stream_aac_profile->down_box(FL_BORDER_BOX); + choice_stream_aac_profile->callback((Fl_Callback*)cb_choice_stream_aac_profile); + choice_stream_aac_profile->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_aac_profile_i18n_done) { + int i=0; + for ( ; i<4; i++) + if (menu_choice_stream_aac_profile[i].label()) + menu_choice_stream_aac_profile[i].label(gettext(menu_choice_stream_aac_profile[i].label())); + menu_choice_stream_aac_profile_i18n_done = 1; + } + choice_stream_aac_profile->menu(menu_choice_stream_aac_profile); + } // Fl_Choice* choice_stream_aac_profile + { choice_stream_aac_afterburner = new Fl_Choice(210, 50, 165, 20, gettext("Afterburner")); + choice_stream_aac_afterburner->down_box(FL_BORDER_BOX); + choice_stream_aac_afterburner->callback((Fl_Callback*)cb_choice_stream_aac_afterburner); + choice_stream_aac_afterburner->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_aac_afterburner_i18n_done) { + int i=0; + for ( ; i<2; i++) + if (menu_choice_stream_aac_afterburner[i].label()) + menu_choice_stream_aac_afterburner[i].label(gettext(menu_choice_stream_aac_afterburner[i].label())); + menu_choice_stream_aac_afterburner_i18n_done = 1; + } + choice_stream_aac_afterburner->menu(menu_choice_stream_aac_afterburner); + } // Fl_Choice* choice_stream_aac_afterburner + { choice_stream_aac_bitrate_mode = new Fl_Choice(25, 110, 165, 20, gettext("Bitrate Mode")); + choice_stream_aac_bitrate_mode->down_box(FL_BORDER_BOX); + choice_stream_aac_bitrate_mode->callback((Fl_Callback*)cb_choice_stream_aac_bitrate_mode); + choice_stream_aac_bitrate_mode->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_stream_aac_bitrate_mode_i18n_done) { + int i=0; + for ( ; i<2; i++) + if (menu_choice_stream_aac_bitrate_mode[i].label()) + menu_choice_stream_aac_bitrate_mode[i].label(gettext(menu_choice_stream_aac_bitrate_mode[i].label())); + menu_choice_stream_aac_bitrate_mode_i18n_done = 1; + } + choice_stream_aac_bitrate_mode->menu(menu_choice_stream_aac_bitrate_mode); + } // Fl_Choice* choice_stream_aac_bitrate_mode + tab_stream_aac->end(); + } // Fl_Group* tab_stream_aac + { tab_stream_flac = new Fl_Group(5, 20, 385, 330, gettext("FLAC")); + tab_stream_flac->hide(); + { Fl_Group* o = new Fl_Group(20, 50, 355, 50, gettext("Bit depth")); + o->box(FL_ENGRAVED_FRAME); + { radio_stream_flac_bit_depth_16 = new Fl_Round_Button(95, 65, 70, 20, gettext("16 bit")); + radio_stream_flac_bit_depth_16->type(102); + radio_stream_flac_bit_depth_16->down_box(FL_ROUND_DOWN_BOX); + radio_stream_flac_bit_depth_16->callback((Fl_Callback*)cb_radio_stream_flac_bit_depth_16); + } // Fl_Round_Button* radio_stream_flac_bit_depth_16 + { radio_stream_flac_bit_depth_24 = new Fl_Round_Button(236, 65, 79, 20, gettext("24 bit")); + radio_stream_flac_bit_depth_24->type(102); + radio_stream_flac_bit_depth_24->down_box(FL_ROUND_DOWN_BOX); + radio_stream_flac_bit_depth_24->callback((Fl_Callback*)cb_radio_stream_flac_bit_depth_24); + } // Fl_Round_Button* radio_stream_flac_bit_depth_24 + o->end(); + } // Fl_Group* o + tab_stream_flac->end(); + } // Fl_Group* tab_stream_flac + tabs_stream_codec_settings->end(); + } // Fl_Tabs* tabs_stream_codec_settings + { Fl_Button* o = new Fl_Button(150, 358, 88, 22, gettext("&Close")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Close1); + } // Fl_Button* o + window_stream_codec_settings->end(); + } // Fl_My_Double_Window* window_stream_codec_settings + { window_rec_codec_settings = new Fl_My_Double_Window(395, 385, gettext("Recording Codec Settings")); + window_rec_codec_settings->box(FL_FLAT_BOX); + window_rec_codec_settings->color(FL_BACKGROUND_COLOR); + window_rec_codec_settings->selection_color(FL_BACKGROUND_COLOR); + window_rec_codec_settings->labeltype(FL_NO_LABEL); + window_rec_codec_settings->labelfont(0); + window_rec_codec_settings->labelsize(14); + window_rec_codec_settings->labelcolor(FL_FOREGROUND_COLOR); + window_rec_codec_settings->user_data((void*)(this)); + window_rec_codec_settings->align(Fl_Align(FL_ALIGN_TOP)); + window_rec_codec_settings->when(FL_WHEN_RELEASE); + { tabs_rec_codec_settings = new Fl_Tabs(5, 0, 385, 350); + { tab_rec_mp3 = new Fl_Group(5, 20, 385, 330, gettext("MP3")); + { choice_rec_mp3_enc_quality = new Fl_Choice(25, 50, 165, 20, gettext("Encoding Quality")); + choice_rec_mp3_enc_quality->down_box(FL_BORDER_BOX); + choice_rec_mp3_enc_quality->callback((Fl_Callback*)cb_choice_rec_mp3_enc_quality); + choice_rec_mp3_enc_quality->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_mp3_enc_quality_i18n_done) { + int i=0; + for ( ; i<10; i++) + if (menu_choice_rec_mp3_enc_quality[i].label()) + menu_choice_rec_mp3_enc_quality[i].label(gettext(menu_choice_rec_mp3_enc_quality[i].label())); + menu_choice_rec_mp3_enc_quality_i18n_done = 1; + } + choice_rec_mp3_enc_quality->menu(menu_choice_rec_mp3_enc_quality); + } // Fl_Choice* choice_rec_mp3_enc_quality + { choice_rec_mp3_stereo_mode = new Fl_Choice(210, 50, 165, 20, gettext("Stereo Mode")); + choice_rec_mp3_stereo_mode->down_box(FL_BORDER_BOX); + choice_rec_mp3_stereo_mode->callback((Fl_Callback*)cb_choice_rec_mp3_stereo_mode); + choice_rec_mp3_stereo_mode->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_mp3_stereo_mode_i18n_done) { + int i=0; + for ( ; i<3; i++) + if (menu_choice_rec_mp3_stereo_mode[i].label()) + menu_choice_rec_mp3_stereo_mode[i].label(gettext(menu_choice_rec_mp3_stereo_mode[i].label())); + menu_choice_rec_mp3_stereo_mode_i18n_done = 1; + } + choice_rec_mp3_stereo_mode->menu(menu_choice_rec_mp3_stereo_mode); + } // Fl_Choice* choice_rec_mp3_stereo_mode + { choice_rec_mp3_bitrate_mode = new Fl_Choice(25, 110, 165, 20, gettext("Bitrate Mode")); + choice_rec_mp3_bitrate_mode->down_box(FL_BORDER_BOX); + choice_rec_mp3_bitrate_mode->callback((Fl_Callback*)cb_choice_rec_mp3_bitrate_mode); + choice_rec_mp3_bitrate_mode->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_mp3_bitrate_mode_i18n_done) { + int i=0; + for ( ; i<3; i++) + if (menu_choice_rec_mp3_bitrate_mode[i].label()) + menu_choice_rec_mp3_bitrate_mode[i].label(gettext(menu_choice_rec_mp3_bitrate_mode[i].label())); + menu_choice_rec_mp3_bitrate_mode_i18n_done = 1; + } + choice_rec_mp3_bitrate_mode->menu(menu_choice_rec_mp3_bitrate_mode); + } // Fl_Choice* choice_rec_mp3_bitrate_mode + { Fl_Group* o = new Fl_Group(19, 167, 125, 162, gettext("VBR")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { choice_rec_mp3_vbr_quality = new Fl_Choice(27, 191, 110, 20, gettext("Quality")); + choice_rec_mp3_vbr_quality->down_box(FL_BORDER_BOX); + choice_rec_mp3_vbr_quality->callback((Fl_Callback*)cb_choice_rec_mp3_vbr_quality); + choice_rec_mp3_vbr_quality->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_mp3_vbr_quality_i18n_done) { + int i=0; + for ( ; i<10; i++) + if (menu_choice_rec_mp3_vbr_quality[i].label()) + menu_choice_rec_mp3_vbr_quality[i].label(gettext(menu_choice_rec_mp3_vbr_quality[i].label())); + menu_choice_rec_mp3_vbr_quality_i18n_done = 1; + } + choice_rec_mp3_vbr_quality->menu(menu_choice_rec_mp3_vbr_quality); + } // Fl_Choice* choice_rec_mp3_vbr_quality + { choice_rec_mp3_vbr_min_bitrate = new Fl_Choice(27, 236, 110, 20, gettext("Min. Bitrate")); + choice_rec_mp3_vbr_min_bitrate->down_box(FL_BORDER_BOX); + choice_rec_mp3_vbr_min_bitrate->callback((Fl_Callback*)cb_choice_rec_mp3_vbr_min_bitrate); + choice_rec_mp3_vbr_min_bitrate->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_mp3_vbr_min_bitrate_i18n_done) { + int i=0; + for ( ; i<17; i++) + if (menu_choice_rec_mp3_vbr_min_bitrate[i].label()) + menu_choice_rec_mp3_vbr_min_bitrate[i].label(gettext(menu_choice_rec_mp3_vbr_min_bitrate[i].label())); + menu_choice_rec_mp3_vbr_min_bitrate_i18n_done = 1; + } + choice_rec_mp3_vbr_min_bitrate->menu(menu_choice_rec_mp3_vbr_min_bitrate); + } // Fl_Choice* choice_rec_mp3_vbr_min_bitrate + { choice_rec_mp3_vbr_max_bitrate = new Fl_Choice(27, 301, 110, 20, gettext("Max. Bitrate")); + choice_rec_mp3_vbr_max_bitrate->down_box(FL_BORDER_BOX); + choice_rec_mp3_vbr_max_bitrate->callback((Fl_Callback*)cb_choice_rec_mp3_vbr_max_bitrate); + choice_rec_mp3_vbr_max_bitrate->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_mp3_vbr_max_bitrate_i18n_done) { + int i=0; + for ( ; i<17; i++) + if (menu_choice_rec_mp3_vbr_max_bitrate[i].label()) + menu_choice_rec_mp3_vbr_max_bitrate[i].label(gettext(menu_choice_rec_mp3_vbr_max_bitrate[i].label())); + menu_choice_rec_mp3_vbr_max_bitrate_i18n_done = 1; + } + choice_rec_mp3_vbr_max_bitrate->menu(menu_choice_rec_mp3_vbr_max_bitrate); + } // Fl_Choice* choice_rec_mp3_vbr_max_bitrate + { check_rec_mp3_force_min_bitrate = new Fl_Check_Button(25, 259, 117, 19, gettext("Force")); + check_rec_mp3_force_min_bitrate->tooltip(gettext("Strictly enforce mininum Bitrate (-F option of the lame encoder)")); + check_rec_mp3_force_min_bitrate->down_box(FL_DOWN_BOX); + check_rec_mp3_force_min_bitrate->callback((Fl_Callback*)cb_check_rec_mp3_force_min_bitrate); + } // Fl_Check_Button* check_rec_mp3_force_min_bitrate + o->end(); + } // Fl_Group* o + { choice_rec_mp3_resampling_freq = new Fl_Choice(210, 110, 165, 20, gettext("Resampling")); + choice_rec_mp3_resampling_freq->tooltip(gettext("Resample to the selected sample rate")); + choice_rec_mp3_resampling_freq->down_box(FL_BORDER_BOX); + choice_rec_mp3_resampling_freq->callback((Fl_Callback*)cb_choice_rec_mp3_resampling_freq); + choice_rec_mp3_resampling_freq->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_mp3_resampling_freq_i18n_done) { + int i=0; + for ( ; i<10; i++) + if (menu_choice_rec_mp3_resampling_freq[i].label()) + menu_choice_rec_mp3_resampling_freq[i].label(gettext(menu_choice_rec_mp3_resampling_freq[i].label())); + menu_choice_rec_mp3_resampling_freq_i18n_done = 1; + } + choice_rec_mp3_resampling_freq->menu(menu_choice_rec_mp3_resampling_freq); + } // Fl_Choice* choice_rec_mp3_resampling_freq + { Fl_Group* o = new Fl_Group(155, 167, 105, 162, gettext("Lowpass (kHz)")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { input_rec_mp3_lowpass_freq = new Fl_Value_Input(180, 190, 70, 20, gettext("Frequency")); + input_rec_mp3_lowpass_freq->callback((Fl_Callback*)cb_input_rec_mp3_lowpass_freq); + input_rec_mp3_lowpass_freq->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + input_rec_mp3_lowpass_freq->when(FL_WHEN_RELEASE); + input_rec_mp3_lowpass_freq->deactivate(); + } // Fl_Value_Input* input_rec_mp3_lowpass_freq + { input_rec_mp3_lowpass_width = new Fl_Value_Input(180, 235, 70, 20, gettext("Width")); + input_rec_mp3_lowpass_width->callback((Fl_Callback*)cb_input_rec_mp3_lowpass_width); + input_rec_mp3_lowpass_width->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + input_rec_mp3_lowpass_width->when(FL_WHEN_RELEASE); + input_rec_mp3_lowpass_width->deactivate(); + } // Fl_Value_Input* input_rec_mp3_lowpass_width + { check_rec_mp3_activate_lowpass_freq = new Fl_Check_Button(159, 193, 20, 15); + check_rec_mp3_activate_lowpass_freq->down_box(FL_DOWN_BOX); + check_rec_mp3_activate_lowpass_freq->callback((Fl_Callback*)cb_check_rec_mp3_activate_lowpass_freq); + } // Fl_Check_Button* check_rec_mp3_activate_lowpass_freq + { check_rec_mp3_activate_lowpass_width = new Fl_Check_Button(159, 238, 20, 15); + check_rec_mp3_activate_lowpass_width->down_box(FL_DOWN_BOX); + check_rec_mp3_activate_lowpass_width->callback((Fl_Callback*)cb_check_rec_mp3_activate_lowpass_width); + } // Fl_Check_Button* check_rec_mp3_activate_lowpass_width + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(270, 167, 105, 162, gettext("Highpass (kHz)")); + o->box(FL_ENGRAVED_FRAME); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { input_rec_mp3_highpass_freq = new Fl_Value_Input(295, 189, 70, 20, gettext("Frequency")); + input_rec_mp3_highpass_freq->callback((Fl_Callback*)cb_input_rec_mp3_highpass_freq); + input_rec_mp3_highpass_freq->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + input_rec_mp3_highpass_freq->when(FL_WHEN_RELEASE); + input_rec_mp3_highpass_freq->deactivate(); + } // Fl_Value_Input* input_rec_mp3_highpass_freq + { input_rec_mp3_highpass_width = new Fl_Value_Input(295, 234, 70, 20, gettext("Width")); + input_rec_mp3_highpass_width->callback((Fl_Callback*)cb_input_rec_mp3_highpass_width); + input_rec_mp3_highpass_width->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + input_rec_mp3_highpass_width->when(FL_WHEN_RELEASE); + input_rec_mp3_highpass_width->deactivate(); + } // Fl_Value_Input* input_rec_mp3_highpass_width + { check_rec_mp3_activate_highpass_freq = new Fl_Check_Button(274, 192, 20, 15); + check_rec_mp3_activate_highpass_freq->down_box(FL_DOWN_BOX); + check_rec_mp3_activate_highpass_freq->callback((Fl_Callback*)cb_check_rec_mp3_activate_highpass_freq); + } // Fl_Check_Button* check_rec_mp3_activate_highpass_freq + { check_rec_mp3_activate_highpass_width = new Fl_Check_Button(274, 237, 20, 15); + check_rec_mp3_activate_highpass_width->down_box(FL_DOWN_BOX); + check_rec_mp3_activate_highpass_width->callback((Fl_Callback*)cb_check_rec_mp3_activate_highpass_width); + } // Fl_Check_Button* check_rec_mp3_activate_highpass_width + o->end(); + } // Fl_Group* o + tab_rec_mp3->end(); + } // Fl_Group* tab_rec_mp3 + { tab_rec_ogg = new Fl_Group(5, 20, 385, 330, gettext("OGG")); + tab_rec_ogg->hide(); + { choice_rec_vorbis_bitrate_mode = new Fl_Choice(25, 50, 165, 20, gettext("Bitrate Mode")); + choice_rec_vorbis_bitrate_mode->down_box(FL_BORDER_BOX); + choice_rec_vorbis_bitrate_mode->callback((Fl_Callback*)cb_choice_rec_vorbis_bitrate_mode); + choice_rec_vorbis_bitrate_mode->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_vorbis_bitrate_mode_i18n_done) { + int i=0; + for ( ; i<3; i++) + if (menu_choice_rec_vorbis_bitrate_mode[i].label()) + menu_choice_rec_vorbis_bitrate_mode[i].label(gettext(menu_choice_rec_vorbis_bitrate_mode[i].label())); + menu_choice_rec_vorbis_bitrate_mode_i18n_done = 1; + } + choice_rec_vorbis_bitrate_mode->menu(menu_choice_rec_vorbis_bitrate_mode); + } // Fl_Choice* choice_rec_vorbis_bitrate_mode + { choice_rec_vorbis_vbr_quality = new Fl_Choice(210, 50, 165, 20, gettext("VBR Quality")); + choice_rec_vorbis_vbr_quality->down_box(FL_BORDER_BOX); + choice_rec_vorbis_vbr_quality->callback((Fl_Callback*)cb_choice_rec_vorbis_vbr_quality); + choice_rec_vorbis_vbr_quality->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_vorbis_vbr_quality_i18n_done) { + int i=0; + for ( ; i<11; i++) + if (menu_choice_rec_vorbis_vbr_quality[i].label()) + menu_choice_rec_vorbis_vbr_quality[i].label(gettext(menu_choice_rec_vorbis_vbr_quality[i].label())); + menu_choice_rec_vorbis_vbr_quality_i18n_done = 1; + } + choice_rec_vorbis_vbr_quality->menu(menu_choice_rec_vorbis_vbr_quality); + } // Fl_Choice* choice_rec_vorbis_vbr_quality + { choice_rec_vorbis_vbr_min_bitrate = new Fl_Choice(25, 110, 165, 20, gettext("VBR min. Bitrate")); + choice_rec_vorbis_vbr_min_bitrate->down_box(FL_BORDER_BOX); + choice_rec_vorbis_vbr_min_bitrate->callback((Fl_Callback*)cb_choice_rec_vorbis_vbr_min_bitrate); + choice_rec_vorbis_vbr_min_bitrate->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_rec_vorbis_vbr_min_bitrate + { choice_rec_vorbis_vbr_max_bitrate = new Fl_Choice(210, 110, 165, 20, gettext("VBR max. Bitrate")); + choice_rec_vorbis_vbr_max_bitrate->down_box(FL_BORDER_BOX); + choice_rec_vorbis_vbr_max_bitrate->callback((Fl_Callback*)cb_choice_rec_vorbis_vbr_max_bitrate); + choice_rec_vorbis_vbr_max_bitrate->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Choice* choice_rec_vorbis_vbr_max_bitrate + tab_rec_ogg->end(); + } // Fl_Group* tab_rec_ogg + { tab_rec_opus = new Fl_Group(5, 20, 385, 330, gettext("OPUS")); + tab_rec_opus->hide(); + { choice_rec_opus_audio_type = new Fl_Choice(210, 50, 165, 20, gettext("Optimize for")); + choice_rec_opus_audio_type->down_box(FL_BORDER_BOX); + choice_rec_opus_audio_type->callback((Fl_Callback*)cb_choice_rec_opus_audio_type); + choice_rec_opus_audio_type->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_opus_audio_type_i18n_done) { + int i=0; + for ( ; i<2; i++) + if (menu_choice_rec_opus_audio_type[i].label()) + menu_choice_rec_opus_audio_type[i].label(gettext(menu_choice_rec_opus_audio_type[i].label())); + menu_choice_rec_opus_audio_type_i18n_done = 1; + } + choice_rec_opus_audio_type->menu(menu_choice_rec_opus_audio_type); + } // Fl_Choice* choice_rec_opus_audio_type + { choice_rec_opus_bitrate_mode = new Fl_Choice(25, 110, 165, 20, gettext("Bitrate Mode")); + choice_rec_opus_bitrate_mode->down_box(FL_BORDER_BOX); + choice_rec_opus_bitrate_mode->callback((Fl_Callback*)cb_choice_rec_opus_bitrate_mode); + choice_rec_opus_bitrate_mode->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_opus_bitrate_mode_i18n_done) { + int i=0; + for ( ; i<2; i++) + if (menu_choice_rec_opus_bitrate_mode[i].label()) + menu_choice_rec_opus_bitrate_mode[i].label(gettext(menu_choice_rec_opus_bitrate_mode[i].label())); + menu_choice_rec_opus_bitrate_mode_i18n_done = 1; + } + choice_rec_opus_bitrate_mode->menu(menu_choice_rec_opus_bitrate_mode); + } // Fl_Choice* choice_rec_opus_bitrate_mode + { choice_rec_opus_quality = new Fl_Choice(25, 50, 165, 20, gettext("Quality")); + choice_rec_opus_quality->down_box(FL_BORDER_BOX); + choice_rec_opus_quality->callback((Fl_Callback*)cb_choice_rec_opus_quality); + choice_rec_opus_quality->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_opus_quality_i18n_done) { + int i=0; + for ( ; i<11; i++) + if (menu_choice_rec_opus_quality[i].label()) + menu_choice_rec_opus_quality[i].label(gettext(menu_choice_rec_opus_quality[i].label())); + menu_choice_rec_opus_quality_i18n_done = 1; + } + choice_rec_opus_quality->menu(menu_choice_rec_opus_quality); + } // Fl_Choice* choice_rec_opus_quality + { choice_rec_opus_bandwidth = new Fl_Choice(210, 110, 165, 20, gettext("Max. Bandwidth")); + choice_rec_opus_bandwidth->down_box(FL_BORDER_BOX); + choice_rec_opus_bandwidth->callback((Fl_Callback*)cb_choice_rec_opus_bandwidth); + choice_rec_opus_bandwidth->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_opus_bandwidth_i18n_done) { + int i=0; + for ( ; i<5; i++) + if (menu_choice_rec_opus_bandwidth[i].label()) + menu_choice_rec_opus_bandwidth[i].label(gettext(menu_choice_rec_opus_bandwidth[i].label())); + menu_choice_rec_opus_bandwidth_i18n_done = 1; + } + choice_rec_opus_bandwidth->menu(menu_choice_rec_opus_bandwidth); + } // Fl_Choice* choice_rec_opus_bandwidth + tab_rec_opus->end(); + } // Fl_Group* tab_rec_opus + { tab_rec_aac = new Fl_Group(5, 20, 385, 330, gettext("AAC")); + tab_rec_aac->hide(); + { choice_rec_aac_profile = new Fl_Choice(25, 50, 165, 20, gettext("Profile")); + choice_rec_aac_profile->down_box(FL_BORDER_BOX); + choice_rec_aac_profile->callback((Fl_Callback*)cb_choice_rec_aac_profile); + choice_rec_aac_profile->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_aac_profile_i18n_done) { + int i=0; + for ( ; i<4; i++) + if (menu_choice_rec_aac_profile[i].label()) + menu_choice_rec_aac_profile[i].label(gettext(menu_choice_rec_aac_profile[i].label())); + menu_choice_rec_aac_profile_i18n_done = 1; + } + choice_rec_aac_profile->menu(menu_choice_rec_aac_profile); + } // Fl_Choice* choice_rec_aac_profile + { choice_rec_aac_afterburner = new Fl_Choice(210, 50, 165, 20, gettext("Afterburner")); + choice_rec_aac_afterburner->down_box(FL_BORDER_BOX); + choice_rec_aac_afterburner->callback((Fl_Callback*)cb_choice_rec_aac_afterburner); + choice_rec_aac_afterburner->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_aac_afterburner_i18n_done) { + int i=0; + for ( ; i<2; i++) + if (menu_choice_rec_aac_afterburner[i].label()) + menu_choice_rec_aac_afterburner[i].label(gettext(menu_choice_rec_aac_afterburner[i].label())); + menu_choice_rec_aac_afterburner_i18n_done = 1; + } + choice_rec_aac_afterburner->menu(menu_choice_rec_aac_afterburner); + } // Fl_Choice* choice_rec_aac_afterburner + { choice_rec_aac_bitrate_mode = new Fl_Choice(25, 110, 165, 20, gettext("Bitrate Mode")); + choice_rec_aac_bitrate_mode->down_box(FL_BORDER_BOX); + choice_rec_aac_bitrate_mode->callback((Fl_Callback*)cb_choice_rec_aac_bitrate_mode); + choice_rec_aac_bitrate_mode->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + if (!menu_choice_rec_aac_bitrate_mode_i18n_done) { + int i=0; + for ( ; i<2; i++) + if (menu_choice_rec_aac_bitrate_mode[i].label()) + menu_choice_rec_aac_bitrate_mode[i].label(gettext(menu_choice_rec_aac_bitrate_mode[i].label())); + menu_choice_rec_aac_bitrate_mode_i18n_done = 1; + } + choice_rec_aac_bitrate_mode->menu(menu_choice_rec_aac_bitrate_mode); + } // Fl_Choice* choice_rec_aac_bitrate_mode + tab_rec_aac->end(); + } // Fl_Group* tab_rec_aac + { tab_rec_flac = new Fl_Group(5, 20, 385, 330, gettext("FLAC")); + tab_rec_flac->hide(); + { Fl_Group* o = new Fl_Group(20, 50, 355, 50, gettext("Bit depth")); + o->box(FL_ENGRAVED_FRAME); + { radio_rec_flac_bit_depth_16 = new Fl_Round_Button(95, 65, 70, 20, gettext("16 bit")); + radio_rec_flac_bit_depth_16->type(102); + radio_rec_flac_bit_depth_16->down_box(FL_ROUND_DOWN_BOX); + radio_rec_flac_bit_depth_16->callback((Fl_Callback*)cb_radio_rec_flac_bit_depth_16); + } // Fl_Round_Button* radio_rec_flac_bit_depth_16 + { radio_rec_flac_bit_depth_24 = new Fl_Round_Button(236, 65, 79, 20, gettext("24 bit")); + radio_rec_flac_bit_depth_24->type(102); + radio_rec_flac_bit_depth_24->down_box(FL_ROUND_DOWN_BOX); + radio_rec_flac_bit_depth_24->callback((Fl_Callback*)cb_radio_rec_flac_bit_depth_24); + } // Fl_Round_Button* radio_rec_flac_bit_depth_24 + o->end(); + } // Fl_Group* o + tab_rec_flac->end(); + } // Fl_Group* tab_rec_flac + { tab_rec_wav = new Fl_Group(5, 20, 385, 330, gettext("WAV")); + tab_rec_wav->hide(); + { Fl_Group* o = new Fl_Group(20, 50, 355, 50, gettext("Bit depth")); + o->box(FL_ENGRAVED_FRAME); + { radio_rec_wav_bit_depth_16 = new Fl_Round_Button(80, 65, 70, 20, gettext("16 bit")); + radio_rec_wav_bit_depth_16->type(102); + radio_rec_wav_bit_depth_16->down_box(FL_ROUND_DOWN_BOX); + radio_rec_wav_bit_depth_16->callback((Fl_Callback*)cb_radio_rec_wav_bit_depth_16); + } // Fl_Round_Button* radio_rec_wav_bit_depth_16 + { radio_rec_wav_bit_depth_32 = new Fl_Round_Button(260, 65, 79, 20, gettext("32 bit")); + radio_rec_wav_bit_depth_32->type(102); + radio_rec_wav_bit_depth_32->down_box(FL_ROUND_DOWN_BOX); + radio_rec_wav_bit_depth_32->callback((Fl_Callback*)cb_radio_rec_wav_bit_depth_32); + } // Fl_Round_Button* radio_rec_wav_bit_depth_32 + { radio_rec_wav_bit_depth_24 = new Fl_Round_Button(170, 65, 70, 20, gettext("24 bit")); + radio_rec_wav_bit_depth_24->type(102); + radio_rec_wav_bit_depth_24->down_box(FL_ROUND_DOWN_BOX); + radio_rec_wav_bit_depth_24->callback((Fl_Callback*)cb_radio_rec_wav_bit_depth_24); + } // Fl_Round_Button* radio_rec_wav_bit_depth_24 + o->end(); + } // Fl_Group* o + tab_rec_wav->end(); + } // Fl_Group* tab_rec_wav + tabs_rec_codec_settings->end(); + } // Fl_Tabs* tabs_rec_codec_settings + { Fl_Button* o = new Fl_Button(150, 358, 88, 22, gettext("&Close")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Close2); + } // Fl_Button* o + window_rec_codec_settings->end(); + } // Fl_My_Double_Window* window_rec_codec_settings + { window_mixer = new Fl_My_Double_Window(430, 450, gettext("butt audio mixer")); + window_mixer->box(FL_FLAT_BOX); + window_mixer->color(FL_BACKGROUND_COLOR); + window_mixer->selection_color(FL_BACKGROUND_COLOR); + window_mixer->labeltype(FL_NO_LABEL); + window_mixer->labelfont(0); + window_mixer->labelsize(14); + window_mixer->labelcolor(FL_FOREGROUND_COLOR); + window_mixer->user_data((void*)(this)); + window_mixer->align(Fl_Align(FL_ALIGN_TOP)); + window_mixer->when(FL_WHEN_RELEASE); + { Fl_Button* o = new Fl_Button(340, 11, 80, 19, gettext("Reset")); + o->box(FL_ENGRAVED_BOX); + o->labelsize(12); + o->callback((Fl_Callback*)cb_Reset2); + } // Fl_Button* o + { Fl_Group* o = new Fl_Group(15, 32, 405, 397, gettext("Audio Mixer")); + o->box(FL_ENGRAVED_BOX); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + { text_mixer_primary_device_volume = new Fl_Text_Display(22, 63, 55, 10, gettext("+0.0 dB")); + text_mixer_primary_device_volume->box(FL_NO_BOX); + text_mixer_primary_device_volume->labelsize(11); + text_mixer_primary_device_volume->align(Fl_Align(FL_ALIGN_TOP_RIGHT)); + } // Fl_Text_Display* text_mixer_primary_device_volume + { slider_mixer_primary_device = new Fl_My_Value_Slider(43, 65, 17, 245, gettext("Primary\nDevice")); + slider_mixer_primary_device->type(4); + slider_mixer_primary_device->box(FL_NO_BOX); + slider_mixer_primary_device->color(FL_BACKGROUND_COLOR); + slider_mixer_primary_device->selection_color(FL_BACKGROUND_COLOR); + slider_mixer_primary_device->labeltype(FL_NORMAL_LABEL); + slider_mixer_primary_device->labelfont(0); + slider_mixer_primary_device->labelsize(11); + slider_mixer_primary_device->labelcolor(FL_FOREGROUND_COLOR); + slider_mixer_primary_device->minimum(18); + slider_mixer_primary_device->maximum(-18); + slider_mixer_primary_device->step(0.1); + slider_mixer_primary_device->slider_size(0.1); + slider_mixer_primary_device->callback((Fl_Callback*)cb_slider_mixer_primary_device, (void*)(CB_CALLED_BY_USER)); + slider_mixer_primary_device->align(Fl_Align(FL_ALIGN_BOTTOM)); + slider_mixer_primary_device->when(FL_WHEN_CHANGED); + slider_mixer_primary_device->default_value = 0.0; + } // Fl_My_Value_Slider* slider_mixer_primary_device + { button_mixer_mute_primary_device = new Fl_Light_Button(30, 340, 45, 20, gettext("Mute")); + button_mixer_mute_primary_device->tooltip(gettext("Mute")); + button_mixer_mute_primary_device->box(FL_THIN_UP_FRAME); + button_mixer_mute_primary_device->selection_color((Fl_Color)1); + button_mixer_mute_primary_device->labelsize(11); + button_mixer_mute_primary_device->callback((Fl_Callback*)cb_button_mixer_mute_primary_device); + } // Fl_Light_Button* button_mixer_mute_primary_device + { text_mixer_secondary_device_volume = new Fl_Text_Display(105, 63, 55, 10, gettext("+0.0 dB")); + text_mixer_secondary_device_volume->box(FL_NO_BOX); + text_mixer_secondary_device_volume->labelsize(11); + text_mixer_secondary_device_volume->align(Fl_Align(FL_ALIGN_TOP_RIGHT)); + } // Fl_Text_Display* text_mixer_secondary_device_volume + { slider_mixer_secondary_device = new Fl_My_Value_Slider(128, 65, 15, 245, gettext("Secondary\nDevice")); + slider_mixer_secondary_device->type(4); + slider_mixer_secondary_device->box(FL_NO_BOX); + slider_mixer_secondary_device->color(FL_BACKGROUND_COLOR); + slider_mixer_secondary_device->selection_color(FL_BACKGROUND_COLOR); + slider_mixer_secondary_device->labeltype(FL_NORMAL_LABEL); + slider_mixer_secondary_device->labelfont(0); + slider_mixer_secondary_device->labelsize(11); + slider_mixer_secondary_device->labelcolor(FL_FOREGROUND_COLOR); + slider_mixer_secondary_device->minimum(18); + slider_mixer_secondary_device->maximum(-18); + slider_mixer_secondary_device->step(0.1); + slider_mixer_secondary_device->slider_size(0.1); + slider_mixer_secondary_device->callback((Fl_Callback*)cb_slider_mixer_secondary_device, (void*)(CB_CALLED_BY_USER)); + slider_mixer_secondary_device->align(Fl_Align(FL_ALIGN_BOTTOM)); + slider_mixer_secondary_device->when(FL_WHEN_CHANGED); + slider_mixer_secondary_device->default_value = 0.0; + } // Fl_My_Value_Slider* slider_mixer_secondary_device + { button_mixer_mute_secondary_device = new Fl_Light_Button(115, 340, 45, 20, gettext("Mute")); + button_mixer_mute_secondary_device->tooltip(gettext("Mute")); + button_mixer_mute_secondary_device->box(FL_THIN_UP_FRAME); + button_mixer_mute_secondary_device->selection_color((Fl_Color)1); + button_mixer_mute_secondary_device->labelsize(11); + button_mixer_mute_secondary_device->callback((Fl_Callback*)cb_button_mixer_mute_secondary_device); + } // Fl_Light_Button* button_mixer_mute_secondary_device + { text_mixer_streaming_volume = new Fl_Text_Display(190, 63, 50, 10, gettext("+0.0 dB")); + text_mixer_streaming_volume->box(FL_NO_BOX); + text_mixer_streaming_volume->labelsize(11); + text_mixer_streaming_volume->align(Fl_Align(FL_ALIGN_TOP_RIGHT)); + } // Fl_Text_Display* text_mixer_streaming_volume + { slider_mixer_streaming_gain = new Fl_My_Value_Slider(208, 65, 15, 245, gettext("Streaming\nGain")); + slider_mixer_streaming_gain->type(4); + slider_mixer_streaming_gain->box(FL_NO_BOX); + slider_mixer_streaming_gain->color(FL_BACKGROUND_COLOR); + slider_mixer_streaming_gain->selection_color(FL_BACKGROUND_COLOR); + slider_mixer_streaming_gain->labeltype(FL_NORMAL_LABEL); + slider_mixer_streaming_gain->labelfont(0); + slider_mixer_streaming_gain->labelsize(11); + slider_mixer_streaming_gain->labelcolor(FL_FOREGROUND_COLOR); + slider_mixer_streaming_gain->minimum(18); + slider_mixer_streaming_gain->maximum(-18); + slider_mixer_streaming_gain->step(0.1); + slider_mixer_streaming_gain->slider_size(0.1); + slider_mixer_streaming_gain->callback((Fl_Callback*)cb_slider_mixer_streaming_gain, (void*)(CB_CALLED_BY_USER)); + slider_mixer_streaming_gain->align(Fl_Align(FL_ALIGN_BOTTOM)); + slider_mixer_streaming_gain->when(FL_WHEN_CHANGED); + slider_mixer_streaming_gain->default_value = 0.0; + } // Fl_My_Value_Slider* slider_mixer_streaming_gain + { text_mixer_recording_volume = new Fl_Text_Display(271, 63, 50, 10, gettext("+0.0 dB")); + text_mixer_recording_volume->box(FL_NO_BOX); + text_mixer_recording_volume->labelsize(11); + text_mixer_recording_volume->align(Fl_Align(FL_ALIGN_TOP_RIGHT)); + } // Fl_Text_Display* text_mixer_recording_volume + { slider_mixer_recording_gain = new Fl_My_Value_Slider(288, 65, 15, 245, gettext("Recording\nGain")); + slider_mixer_recording_gain->type(4); + slider_mixer_recording_gain->box(FL_NO_BOX); + slider_mixer_recording_gain->color(FL_BACKGROUND_COLOR); + slider_mixer_recording_gain->selection_color(FL_BACKGROUND_COLOR); + slider_mixer_recording_gain->labeltype(FL_NORMAL_LABEL); + slider_mixer_recording_gain->labelfont(0); + slider_mixer_recording_gain->labelsize(11); + slider_mixer_recording_gain->labelcolor(FL_FOREGROUND_COLOR); + slider_mixer_recording_gain->minimum(18); + slider_mixer_recording_gain->maximum(-18); + slider_mixer_recording_gain->step(0.1); + slider_mixer_recording_gain->slider_size(0.1); + slider_mixer_recording_gain->callback((Fl_Callback*)cb_slider_mixer_recording_gain, (void*)(CB_CALLED_BY_USER)); + slider_mixer_recording_gain->align(Fl_Align(FL_ALIGN_BOTTOM)); + slider_mixer_recording_gain->when(FL_WHEN_CHANGED); + slider_mixer_recording_gain->default_value = 0.0; + } // Fl_My_Value_Slider* slider_mixer_recording_gain + { text_mixer_master_volume = new Fl_Text_Display(352, 63, 50, 10, gettext("+0.0 dB")); + text_mixer_master_volume->box(FL_NO_BOX); + text_mixer_master_volume->labelsize(11); + text_mixer_master_volume->align(Fl_Align(FL_ALIGN_TOP_RIGHT)); + } // Fl_Text_Display* text_mixer_master_volume + { slider_mixer_master_gain = new Fl_My_Value_Slider(368, 65, 15, 245, gettext("Master\nGain")); + slider_mixer_master_gain->type(4); + slider_mixer_master_gain->box(FL_NO_BOX); + slider_mixer_master_gain->color(FL_BACKGROUND_COLOR); + slider_mixer_master_gain->selection_color(FL_BACKGROUND_COLOR); + slider_mixer_master_gain->labeltype(FL_NORMAL_LABEL); + slider_mixer_master_gain->labelfont(0); + slider_mixer_master_gain->labelsize(11); + slider_mixer_master_gain->labelcolor(FL_FOREGROUND_COLOR); + slider_mixer_master_gain->minimum(24); + slider_mixer_master_gain->maximum(-24); + slider_mixer_master_gain->step(0.1); + slider_mixer_master_gain->slider_size(0.1); + slider_mixer_master_gain->callback((Fl_Callback*)cb_slider_mixer_master_gain, (void*)(CB_CALLED_BY_USER)); + slider_mixer_master_gain->align(Fl_Align(FL_ALIGN_BOTTOM)); + slider_mixer_master_gain->when(FL_WHEN_CHANGED); + slider_mixer_master_gain->default_value = 0.0; + } // Fl_My_Value_Slider* slider_mixer_master_gain + { slider_mixer_cross_fader = new Fl_My_Value_Slider(30, 385, 375, 15, gettext("\nCross Fader")); + slider_mixer_cross_fader->type(5); + slider_mixer_cross_fader->box(FL_NO_BOX); + slider_mixer_cross_fader->color(FL_BACKGROUND_COLOR); + slider_mixer_cross_fader->selection_color(FL_BACKGROUND_COLOR); + slider_mixer_cross_fader->labeltype(FL_NORMAL_LABEL); + slider_mixer_cross_fader->labelfont(0); + slider_mixer_cross_fader->labelsize(11); + slider_mixer_cross_fader->labelcolor(FL_FOREGROUND_COLOR); + slider_mixer_cross_fader->minimum(-100); + slider_mixer_cross_fader->maximum(100); + slider_mixer_cross_fader->step(1); + slider_mixer_cross_fader->slider_size(0.1); + slider_mixer_cross_fader->callback((Fl_Callback*)cb_slider_mixer_cross_fader, (void*)(CB_CALLED_BY_USER)); + slider_mixer_cross_fader->align(Fl_Align(FL_ALIGN_BOTTOM)); + slider_mixer_cross_fader->when(FL_WHEN_CHANGED); + slider_mixer_cross_fader->default_value = 0.0; + slider_mixer_cross_fader->hide_tipwin = true; + } // Fl_My_Value_Slider* slider_mixer_cross_fader + { Fl_Box* o = new Fl_Box(25, 398, 85, 26, gettext("Primary\nDevice")); + o->labelsize(11); + o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); + } // Fl_Box* o + { Fl_Box* o = new Fl_Box(205, 388, 25, 20, gettext("|")); + o->labelsize(11); + o->align(Fl_Align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE)); + } // Fl_Box* o + { Fl_Box* o = new Fl_Box(310, 398, 95, 27, gettext("Secondary\nDevice")); + o->labelsize(11); + o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); + } // Fl_Box* o + o->end(); + } // Fl_Group* o + window_mixer->end(); + } // Fl_My_Double_Window* window_mixer + { window_missing_aac_lib = new Fl_My_Double_Window(390, 190, gettext("Alert")); + window_missing_aac_lib->box(FL_FLAT_BOX); + window_missing_aac_lib->color(FL_BACKGROUND_COLOR); + window_missing_aac_lib->selection_color(FL_BACKGROUND_COLOR); + window_missing_aac_lib->labeltype(FL_NO_LABEL); + window_missing_aac_lib->labelfont(0); + window_missing_aac_lib->labelsize(14); + window_missing_aac_lib->labelcolor(FL_FOREGROUND_COLOR); + window_missing_aac_lib->user_data((void*)(this)); + window_missing_aac_lib->align(Fl_Align(FL_ALIGN_TOP)); + window_missing_aac_lib->when(FL_WHEN_RELEASE); + { Fl_Button* o = new Fl_Button(20, 123, 350, 29, gettext("&Open the manual")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Open); + } // Fl_Button* o + { Fl_Box* o = new Fl_Box(20, 25, 355, 80, gettext("Could not find aac library.\n\nPlease follow the instructions in the manual\n\ +for adding aac support.")); + o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); + } // Fl_Box* o + { Fl_Button* o = new Fl_Button(20, 156, 350, 29, gettext("&Close")); + o->box(FL_ENGRAVED_BOX); + o->callback((Fl_Callback*)cb_Close3); + } // Fl_Button* o + window_missing_aac_lib->set_modal(); + window_missing_aac_lib->end(); + } // Fl_My_Double_Window* window_missing_aac_lib +} + +flgui::~flgui() { + return; +} diff --git a/src/FLTK/flgui.fl b/src/FLTK/flgui.fl new file mode 100644 index 0000000..c6d44be --- /dev/null +++ b/src/FLTK/flgui.fl @@ -0,0 +1,3264 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0309 +i18n_type 1 +i18n_include "../../gettext.h" +i18n_function gettext +header_name {.h} +code_name {.cpp} +class flgui {open +} { + decl {bool info_visible;} {public local + } + decl {Fl_Text_Buffer *info_buffer;} {public local + } + Function {flgui()} {open + } { + Fl_Window window_main { + callback {window_main_close_cb(true);} + xywh {859 484 430 395} type Double resizable + code0 {\#include "FL/Fl_My_Double_Window.H"} + code1 {\#include +\#include "config.h"} + code2 {\#include "flgui.h" +\#include "fl_timer_funcs.h"} + code3 {window_main->size_range(430, 155, 430); window_main->is_main_window = true;} + class Fl_My_Double_Window size_range {430 276 430 0} visible + } { + Fl_Box lcd { + callback {ILM216_cb();} + tooltip {press left mouse to toggle lcd info} xywh {10 10 410 95} box ENGRAVED_BOX color 32 selection_color 41 + code0 {\#include "Fl_ILM216.h"} + code1 {\#include "fl_callbacks.h"} + code3 {\#include "cfg.h"} + class Fl_ILM216 + } + Fl_Box label_volume { + label {Streaming volume} + xywh {154 119 135 16} labelsize 10 align 20 + } + Fl_Button button_mixer { + label Mixer + callback {button_mixer_cb();} + tooltip {show/hide mixer window} xywh {10 113 122 22} box ENGRAVED_BOX shortcut 0x40066 color 48 labelsize 11 + } + Fl_Button button_record { + label {@circle} + callback {button_record_cb(true);} + tooltip {start/stop recording} xywh {10 148 30 30} box ENGRAVED_BOX down_box ENGRAVED_BOX shortcut 0x40072 color 48 selection_color 40 labelfont 1 labelsize 12 labelcolor 1 + } + Fl_Button button_disconnect { + label {@square} + callback {button_disconnect_cb(true);} + tooltip {disconnect from server} xywh {62 148 30 30} box ENGRAVED_BOX down_box ENGRAVED_BOX shortcut 0x40064 color 48 selection_color 40 labelfont 1 labelsize 12 labelcolor 7 + } + Fl_Button button_connect { + label {@>} + callback {button_connect_cb();} + tooltip {connect to server} xywh {102 148 30 30} box ENGRAVED_BOX down_box ENGRAVED_BOX shortcut 0x40063 color 48 selection_color 40 labelfont 1 labelsize 21 labelcolor 7 + } + Fl_Tabs vu_tabs { + callback {vu_tabs_cb();} + xywh {140 110 196 74} box GTK_THIN_UP_BOX selection_color 47 labelsize 13 + } { + Fl_Group {} { + label Streaming open + xywh {150 128 177 47} labelsize 11 + } {} + Fl_Group {} { + label Recording open + xywh {150 130 185 50} labelsize 11 hide + } {} + } + Fl_Group vumeter { + xywh {156 135 174 43} box BORDER_BOX + code0 {\#include "Fl_vu_meter.h"} + class VUMeter + } {} + Fl_Box invisible_tab_box { + xywh {140 108 197 76} + code0 {\#include "FL/Fl_My_Invisible_Box.H"} + class Fl_My_Invisible_Box + } + Fl_Button button_cfg { + label Settings + callback {button_cfg_cb();} + tooltip {show/hide config window} xywh {340 135 80 22} box ENGRAVED_BOX shortcut 0x40066 color 48 labelsize 11 + } + Fl_Button button_info { + label {Show log} + callback {button_info_cb();} + tooltip {show/hide info window} xywh {340 163 80 15} box ENGRAVED_BOX shortcut 0x40076 color 48 labelsize 10 + } + Fl_Box label_n24dB { + label {-24 dB} + xywh {10 190 30 16} labelsize 10 + } + Fl_Slider slider_gain { + label Gain + user_data CB_CALLED_BY_USER + callback {slider_gain_cb(v);} + tooltip {Master Gain} xywh {50 191 335 15} type {Horz Knob} box NO_BOX labeltype NO_LABEL align 0 minimum -24 maximum 24 step 0.1 slider_size 0.1 + code0 {\#include "FL/Fl_My_Value_Slider.H"} + code1 {slider_gain->default_value = 0.0;} + class Fl_My_Value_Slider + } + Fl_Box label_p24dB { + label {+24 dB} + xywh {390 190 30 16} labelsize 10 + } + Fl_Button sponsor_logo { + image {../xpm/radio_co_badge.png} xywh {237 27 128 61} box NO_BOX + } + Fl_Box label_current_listeners { + label {Listeners: 0} + xywh {211 83 165 16} labelsize 18 labelcolor 7 align 24 + } + Fl_Text_Display info_output { + xywh {0 212 430 184} box EMBOSSED_BOX textfont 4 textsize 15 resizable + } + } + Fl_Window window_cfg { + label {butt settings} + callback {if(window_cfg->shown()) +{ + window_cfg->hide(); + Fl::remove_timeout(&cfg_win_pos_timer); +}} + xywh {1297 180 430 680} type Double + code0 {\#include "FL/Fl_My_Double_Window.H"} + code1 {\#include "fl_timer_funcs.h"} + class Fl_My_Double_Window size_range {430 640 430 680} visible + } { + Fl_Tabs Settings {open + xywh {-1 0 436 681} selection_color 45 + } { + Fl_Group {} { + label Main + xywh {0 20 434 660} when 6 + } { + Fl_Group {} { + label {Server Settings} open + xywh {50 55 328 155} box ENGRAVED_FRAME align 5 + } { + Fl_Choice choice_cfg_act_srv { + label Server + callback {choice_cfg_act_srv_cb();} + tooltip {Server to connect to} xywh {58 75 310 20} down_box BORDER_BOX align 5 + } {} + Fl_Button {} { + label ADD + callback {button_cfg_add_srv_cb();} + tooltip {Add server} xywh {58 100 80 20} box ENGRAVED_BOX + } + Fl_Button button_cfg_edit_srv { + label EDIT + callback {button_cfg_edit_srv_cb();} + tooltip {Edit selected server} xywh {173 100 80 20} box ENGRAVED_BOX + } + Fl_Button button_cfg_del_srv { + label DEL + callback {button_cfg_del_srv_cb();} + tooltip {Delete selected server} xywh {288 100 80 20} box ENGRAVED_BOX + } + Fl_Choice choice_cfg_act_icy { + label {Stream Infos} + callback {choice_cfg_act_icy_cb();} open + tooltip {Stream info that shall be used} xywh {58 155 310 20} down_box BORDER_BOX align 5 + } {} + Fl_Button {} { + label ADD + callback {button_cfg_add_icy_cb();} + tooltip {Add stream info} xywh {58 180 80 20} box ENGRAVED_BOX + } + Fl_Button button_cfg_edit_icy { + label EDIT + callback {button_cfg_edit_icy_cb();} + tooltip {Edit stream info} xywh {173 180 80 20} box ENGRAVED_BOX + } + Fl_Button button_cfg_del_icy { + label DEL + callback {button_cfg_del_icy_cb();} + tooltip {Delete stream info} xywh {288 180 80 20} box ENGRAVED_BOX + } + } + Fl_Group {} { + label {Log File} open + xywh {50 237 326 40} box ENGRAVED_FRAME align 5 + } { + Fl_Input input_log_filename { + callback {input_log_filename_cb();} + tooltip {Log file path} xywh {58 245 280 25} align 5 + } + Fl_Button {} { + callback {button_cfg_log_browse_cb();} + tooltip {Select log file} image {../xpm/folder.png} xywh {344 245 25 25} box ENGRAVED_BOX + } + } + Fl_Group {} { + label Configuration open + xywh {50 304 326 50} box ENGRAVED_FRAME align 5 + } { + Fl_Button button_cfg_import { + label {Import...} + callback {button_cfg_import_cb();} + tooltip {Import settings from config file} xywh {58 315 70 28} box ENGRAVED_BOX + } + Fl_Button {} { + label {&Save} + callback {cfg_write_file(NULL);} + tooltip {Save settings} xywh {166 315 95 28} box ENGRAVED_BOX + } + Fl_Button {} { + label {Export...} + callback {button_cfg_export_cb();} + tooltip {export settings} xywh {298 315 70 28} box ENGRAVED_BOX + } + } + Fl_Group group_agent { + label {Butt Agent} + xywh {50 385 326 75} box ENGRAVED_FRAME align 5 + } { + Fl_Check_Button check_start_agent { + label {Start agent at startup} + callback {check_start_agent_cb();} + tooltip {Start the butt agent when butt starts} xywh {56 400 157 15} down_box DOWN_BOX + } + Fl_Check_Button check_minimize_to_tray { + label {Minimize butt to tray} + callback {check_minimize_to_tray_cb();} + tooltip {Minimize butt to tray} xywh {56 430 150 15} down_box DOWN_BOX + } + Fl_Button {} { + label {Start Agent} + callback {button_start_agent_cb();} + tooltip {Start the butt agent now} xywh {261 391 105 28} box ENGRAVED_BOX + } + Fl_Button {} { + label {Stop Agent} + callback {button_stop_agent_cb();} + tooltip {Stop the butt agent} xywh {261 425 105 28} box ENGRAVED_BOX + } + } + Fl_Group {} { + label Updates open + xywh {50 485 326 50} box ENGRAVED_FRAME align 5 + } { + Fl_Check_Button check_update_at_startup { + label {Check at startup} + callback {check_update_at_startup_cb();} + tooltip {Check for updates at start} xywh {56 504 145 15} down_box DOWN_BOX + } + Fl_Button {} { + label {Check now} + callback {button_cfg_check_for_updates_cb();} + tooltip {Check if a new version is available} xywh {261 497 105 28} box ENGRAVED_BOX + } + } + Fl_Group {} { + label Help open + xywh {50 565 330 50} box ENGRAVED_FRAME align 5 + } { + Fl_Button {} { + label Manual + callback {char uri[128]; +snprintf(uri, sizeof(uri), "https://danielnoethen.de/butt/release/%s/butt-%s_manual.html", VERSION, VERSION); +fl_open_uri(uri);} + xywh {58 576 135 28} box ENGRAVED_BOX + code0 {\#include } + } + Fl_Button {} { + label { YouTube} + callback {char uri[128]; +snprintf(uri, sizeof(uri), "https://www.youtube.com/@butt.broadcaster"); +fl_open_uri(uri);} + image {../xpm/yt_icon.png} xywh {235 577 135 28} box ENGRAVED_BOX align 256 + code0 {\#include } + } + } + } + Fl_Group {} { + label Audio + xywh {0 20 434 660} hide + } { + Fl_Group {} { + label {Main Audio Settings} open + xywh {50 55 326 245} box ENGRAVED_FRAME align 5 + } { + Fl_Choice choice_cfg_channel { + label {Channel mode} + tooltip {Select input channel} xywh {58 84 150 21} box ENGRAVED_BOX down_box BORDER_BOX align 5 + } { + MenuItem {} { + label Stereo + callback {choice_cfg_channel_stereo_cb();} + xywh {60 60 40 25} + } + MenuItem {} { + label Mono + callback {choice_cfg_channel_mono_cb();} + xywh {50 50 40 25} + } + } + Fl_Choice choice_cfg_samplerate { + label Samplerate + callback {choice_cfg_samplerate_cb();} + tooltip {Select input sample rate} xywh {228 85 135 20} down_box BORDER_BOX align 5 + } {} + Fl_Group {} { + label {Remember Device by} + xywh {58 133 162 25} box ENGRAVED_FRAME align 5 + } { + Fl_Round_Button radio_cfg_ID { + label ID + callback {radio_cfg_ID_cb();} + xywh {67 138 40 14} type Radio down_box ROUND_DOWN_BOX + } + Fl_Round_Button radio_cfg_name { + label Name + callback {radio_cfg_name_cb();} + xywh {143 138 65 15} type Radio down_box ROUND_DOWN_BOX + } + } + Fl_Button button_cfg_rescan_devices { + label {Update devices} + callback {button_cfg_rescan_devices_cb();} + tooltip {Rescan audio devices} xywh {228 133 135 25} box ENGRAVED_BOX + } + Fl_Choice choice_cfg_dev { + label {Primary Audio Device} + callback {choice_cfg_dev_cb();} open + tooltip {Select your primary sound card device} xywh {58 190 170 20} down_box FLAT_BOX align 5 + } {} + Fl_Choice choice_cfg_left_channel { + label Left + callback {choice_cfg_left_channel_cb();} open + tooltip {Select left audio channel} xywh {248 190 50 20} down_box BORDER_BOX align 5 + } {} + Fl_Choice choice_cfg_right_channel { + label Right + callback {choice_cfg_right_channel_cb();} open + tooltip {Select right audio channel} xywh {313 190 50 20} down_box BORDER_BOX align 5 + } {} + Fl_Choice choice_cfg_dev2 { + label {Secondary Audio Device} + callback {choice_cfg_dev2_cb();} open + tooltip {Select your secondary sound card device} xywh {58 256 170 20} down_box FLAT_BOX align 5 + } {} + Fl_Choice choice_cfg_left_channel2 { + label Left + callback {choice_cfg_left_channel2_cb();} open + tooltip {Select left audio channel} xywh {248 256 50 20} down_box BORDER_BOX align 5 + } {} + Fl_Choice choice_cfg_right_channel2 { + label Right + callback {choice_cfg_right_channel2_cb();} open + tooltip {Select right audio channel} xywh {313 256 50 20} down_box BORDER_BOX align 5 + } {} + } + Fl_Group {} { + label Streaming + xywh {50 330 326 60} box ENGRAVED_FRAME align 5 + } { + Fl_Choice choice_cfg_codec { + label Codec open + tooltip {Select streaming codec} xywh {58 357 125 20} box ENGRAVED_BOX down_box BORDER_BOX align 5 + } { + MenuItem {} { + label MP3 + callback {choice_cfg_codec_mp3_cb();} + xywh {70 70 40 25} + } + MenuItem {} { + label {OGG/VORBIS} + callback {choice_cfg_codec_ogg_cb();} + xywh {60 60 40 25} + } + MenuItem {} { + label OPUS + callback {choice_cfg_codec_opus_cb();} + xywh {70 70 40 25} + } + MenuItem menu_item_cfg_aac { + label {AAC+} + callback {choice_cfg_codec_aac_cb();} + xywh {80 80 40 25} + } + MenuItem {} { + label FLAC + callback {choice_cfg_codec_flac_cb();} + xywh {80 80 40 25} + } + } + Fl_Choice choice_cfg_bitrate { + label Bitrate + callback {choice_cfg_bitrate_cb();} open + tooltip {Select streaming bitrate} xywh {200 357 115 20} box ENGRAVED_BOX down_box BORDER_BOX align 5 + } {} + Fl_Button {} { + callback {button_stream_codec_settings_cb();} + image {../xpm/settings.png} xywh {323 355 22 22} box NO_BOX + } + } + Fl_Group {} { + label Recording + xywh {50 415 326 60} box ENGRAVED_FRAME align 5 + } { + Fl_Choice choice_rec_codec { + label Codec + tooltip {Select recording codec} xywh {58 442 125 20} box ENGRAVED_BOX down_box BORDER_BOX align 5 + } { + MenuItem {} { + label MP3 + callback {choice_rec_codec_mp3_cb();} + xywh {80 80 40 25} + } + MenuItem {} { + label {OGG/VORBIS} + callback {choice_rec_codec_ogg_cb();} + xywh {70 70 40 25} + } + MenuItem {} { + label OPUS + callback {choice_rec_codec_opus_cb();} + xywh {15 15 31 20} + } + MenuItem menu_item_rec_aac { + label {AAC+} + callback {choice_rec_codec_aac_cb();} + xywh {90 90 40 25} + } + MenuItem {} { + label FLAC + callback {choice_rec_codec_flac_cb();} + xywh {25 25 31 20} + } + MenuItem {} { + label WAV + callback {choice_rec_codec_wav_cb();} + xywh {5 5 31 20} + } + } + Fl_Choice choice_rec_bitrate { + label Bitrate + callback {choice_rec_bitrate_cb();} open + tooltip {Select recording bitrate} xywh {200 442 115 20} down_box BORDER_BOX align 5 + } {} + Fl_Button {} { + callback {button_rec_codec_settings_cb();} + image {../xpm/settings.png} xywh {323 440 22 22} box NO_BOX + } + } + Fl_Button button_advanced { + label {Advanced...} + callback {static int show_advanced = 0; +if (!show_advanced) +{ + window_cfg->size(window_cfg->w(), 450); + show_advanced = 1; + fl_g->button_advanced->label("Standard..."); +} +else +{ + window_cfg->size(window_cfg->w(), 380); + show_advanced = 0; + fl_g->button_advanced->label("Advanced..."); + +}} + xywh {37 345 89 25} box ENGRAVED_BOX hide deactivate + } + Fl_Value_Input input_cfg_buffer { + label {Buffer (ms)} + callback {input_cfg_buffer_cb(1);} + xywh {37 405 75 20} align 5 when 8 maximum 0 value 50 hide deactivate + } + Fl_Choice choice_cfg_resample_mode { + label {Resample Quality} + callback {choice_cfg_resample_mode_cb();} + xywh {177 405 125 20} down_box BORDER_BOX align 5 hide deactivate + } { + MenuItem {} { + label SINC_BEST + xywh {0 0 31 20} + } + MenuItem {} { + label SINC_MEDIUM + xywh {10 10 31 20} + } + MenuItem {} { + label SINC_FASTEST + xywh {20 20 31 20} + } + MenuItem {} { + label ZERO_ORDER_HOLD + xywh {30 30 31 20} + } + MenuItem {} { + label LINEAR + xywh {40 40 31 20} + } + } + Fl_Group {} { + label {Signal detection levels} open + xywh {50 500 326 50} box ENGRAVED_FRAME align 5 + } { + Fl_Value_Input input_cfg_present_level { + label {Signal present} + callback {input_cfg_present_level_cb();} + xywh {58 524 70 19} align 5 minimum -90 maximum 0 value -50 + } + Fl_Box {} { + label dB + xywh {128 526 25 17} align 20 + } + Fl_Value_Input input_cfg_absent_level { + label {Signal absent} + callback {input_cfg_absent_level_cb();} + xywh {253 524 65 19} align 5 minimum -90 maximum 0 value -50 + } + Fl_Box {} { + label dB + xywh {318 525 25 17} align 20 + } + } + } + Fl_Group {} { + label Stream open + xywh {0 20 434 660} hide + } { + Fl_Group {} { + label {Update song name from file} open + xywh {50 47 329 65} box ENGRAVED_FRAME align 5 + } { + Fl_Input input_cfg_song_file { + callback {input_cfg_song_file_cb();} + tooltip {Filename that holds the current song name} xywh {55 56 283 26} align 9 + code0 {this->input_cfg_song_file->maximum_size(500);} + } + Fl_Button button_songfile_browse { + callback {button_cfg_browse_songfile_cb();} + tooltip {Select file that holds the current song name} image {../xpm/folder.png} xywh {343 57 25 25} box ENGRAVED_FRAME + } + Fl_Check_Button check_song_update_active { + label Activate + callback {check_song_update_active_cb();} + tooltip {Activate auto update song name from file} xywh {53 83 77 25} down_box DOWN_BOX + } + Fl_Check_Button check_read_last_line { + label {Read last line instead of first} + callback {check_read_last_line_cb();} + tooltip {Activate auto update song name from file} xywh {133 83 215 25} down_box DOWN_BOX + } + } + Fl_Group {} { + label {Update song name from application} open + xywh {50 137 329 65} box ENGRAVED_BOX align 5 + } { + Fl_Choice choice_cfg_app { + callback {choice_cfg_app_cb();} open + tooltip {Changes the song through an running application} xywh {55 148 203 20} down_box BORDER_BOX + } {} + Fl_Group {} {open + xywh {268 145 105 40} + } { + Fl_Round_Button radio_cfg_title_artist { + label {Title - Artist} + callback {radio_cfg_title_artist_cb();} + xywh {268 145 105 20} type Radio down_box ROUND_DOWN_BOX + } + Fl_Round_Button radio_cfg_artist_title { + label {Artist - Title} + callback {radio_cfg_artist_title_cb();} + xywh {268 170 105 15} type Radio down_box ROUND_DOWN_BOX + } + } + Fl_Check_Button check_cfg_use_app { + label Activate + callback {check_cfg_use_app_cb();} + xywh {53 167 85 33} down_box DOWN_BOX + } + } + Fl_Group {} { + label {Update song name manually} open + xywh {50 314 329 40} box ENGRAVED_FRAME align 5 + } { + Fl_Input input_cfg_song { + callback {input_cfg_song_cb();} + tooltip {Current song name} xywh {55 322 283 25} align 5 when 1 + code0 {this->input_cfg_song->maximum_size(500);} + } + Fl_Button button_cfg_song_go { + label OK + callback {button_cfg_song_go_cb();} + tooltip {Send current song name to the server} xywh {343 322 25 25} box ENGRAVED_BOX shortcut 0xff0d labelsize 12 + } + } + Fl_Group {} { + label {Update song name delay} open + xywh {50 373 329 32} box ENGRAVED_FRAME align 5 + } { + Fl_Choice choice_cfg_song_delay { + callback {choice_cfg_song_delay_cb();} open + tooltip {Introduces a delay until the song name is actually updated} xywh {55 379 153 20} down_box BORDER_BOX align 8 + } {} + } + Fl_Group {} { + label {Extend song name} open + xywh {50 426 330 75} box ENGRAVED_FRAME align 5 + } { + Fl_Input input_cfg_song_prefix { + label {Prefix:} + callback {input_cfg_song_prefix_cb();} + xywh {103 434 255 24} when 1 + code0 {this->input_cfg_song_prefix->maximum_size(500);} + } + Fl_Input input_cfg_song_suffix { + label {Suffix:} + callback {input_cfg_song_suffix_cb();} + xywh {103 469 255 24} when 1 + code0 {this->input_cfg_song_suffix->maximum_size(500);} + } + } + Fl_Group {} { + label Streaming open + xywh {50 525 329 152} box ENGRAVED_FRAME align 5 + } { + Fl_Check_Button check_stream_signal { + label {Start if signal is present for} + callback {check_stream_signal_cb();} + tooltip {Start streaming if the audio level exceeds the "Signal present" level set in the "Audio" tab} xywh {55 535 205 18} down_box DOWN_BOX + } + Fl_Value_Input input_cfg_signal { + callback {input_cfg_signal_cb();} + xywh {272 533 42 19} when 4 + } + Fl_Box {} { + label seconds + xywh {313 533 62 16} align 20 + } + Fl_Check_Button check_stream_silence { + label {Stop if signal is absent for} + callback {check_stream_silence_cb();} + tooltip {Stop streaming if the audio level falls below the "Signal absent level set in the "Audio" tab} xywh {55 557 205 18} down_box DOWN_BOX + } + Fl_Value_Input input_cfg_silence { + callback {input_cfg_silence_cb();} + xywh {272 557 42 19} when 4 + } + Fl_Box {} { + label seconds + xywh {313 557 62 16} align 20 + } + Fl_Check_Button check_cfg_connect { + label {Start streaming after launch} + callback {check_cfg_connect_cb();} + tooltip {Connect automatically to a server after launch} xywh {55 583 205 18} down_box DOWN_BOX + } + Fl_Check_Button check_cfg_force_reconnecting { + label {Force reconnecting} + callback {check_cfg_force_reconnecting_cb();} + tooltip {If enabled butt keeps reconnecting regardless of the error message} xywh {55 606 205 18} down_box DOWN_BOX + } + Fl_Box {} { + label {Reconnect delay:} + xywh {55 631 190 17} align 20 + } + Fl_Value_Input input_cfg_reconnect_delay { + callback {input_cfg_reconnect_delay_cb();} + xywh {58 651 42 19} + } + Fl_Box {} { + label seconds + xywh {104 652 62 16} align 20 + } + } + Fl_Group {} { + label {Update song name from URL} open + xywh {50 225 329 65} box ENGRAVED_FRAME align 5 + } { + Fl_Input input_cfg_song_url { + callback {input_cfg_song_url_cb();} + tooltip {URL to get song name from} xywh {55 233 318 25} align 5 + code0 {this->input_cfg_song_url->maximum_size(1024);} + } + Fl_Value_Input input_cfg_url_update_song_interval { + label {Update interval} + callback {input_cfg_url_update_song_interval_cb();} + tooltip {Update interval in seconds} xywh {340 263 30 19} when 4 minimum 1 maximum 1000 value 1 + } + Fl_Check_Button check_cfg_update_from_url { + label Activate + callback {check_cfg_update_from_url_cb();} + xywh {55 259 85 31} down_box DOWN_BOX + } + } + } + Fl_Group {} { + label Record open + xywh {0 20 434 660} hide + } { + Fl_Input input_rec_filename { + label {Record File Name:} + callback {input_rec_filename_cb();} + tooltip {Record file name} xywh {50 55 326 25} align 5 + code0 {this->input_rec_filename->maximum_size(500);} + } + Fl_Input input_rec_folder { + label {Record Directory:} + callback {input_rec_folder_cb();} + tooltip {Directory of recordings} xywh {50 106 298 25} align 5 + code0 {this->input_rec_folder->maximum_size(500);} + } + Fl_Button button_rec_browse { + callback {button_rec_browse_cb();} + tooltip {Select recording directory} image {../xpm/folder.png} xywh {350 106 25 25} box ENGRAVED_BOX + } + Fl_Group {} { + label {Split file} + xywh {50 164 326 57} box ENGRAVED_FRAME align 5 + } { + Fl_Value_Input input_rec_split_time { + label every + callback {input_rec_split_time_cb();} + xywh {97 171 40 19} + } + Fl_Box text_rec_split_time { + label minutes + xywh {143 171 50 16} + } + Fl_Check_Button check_sync_to_full_hour { + label {Sync to full hour} + callback {check_sync_to_full_hour_cb();} + tooltip {Sync to full hour} xywh {55 196 124 15} down_box DOWN_BOX + } + Fl_Button {} { + label {Split now} + callback {button_rec_split_now_cb();} + xywh {288 179 80 28} box ENGRAVED_BOX + } + } + Fl_Group {} { + label Recording open + xywh {50 250 326 173} box ENGRAVED_FRAME align 5 + } { + Fl_Check_Button check_cfg_auto_start_rec { + label {Start recording when connected} + callback {check_cfg_auto_start_rec_cb();} + tooltip {Start recording when connected} xywh {55 290 265 20} down_box DOWN_BOX + } + Fl_Check_Button check_cfg_auto_stop_rec { + label {Stop recording when disconnected} + callback {check_cfg_auto_stop_rec_cb();} + tooltip {Start recording when disconnected} xywh {55 314 265 20} down_box DOWN_BOX + } + Fl_Check_Button check_cfg_rec_after_launch { + label {Start recording after launch} + callback {check_cfg_rec_after_launch_cb();} + tooltip {Start recording after launch} xywh {55 339 265 20} down_box DOWN_BOX + } + Fl_Check_Button check_rec_signal { + label {Start if signal is present for} + callback {check_rec_signal_cb();} + tooltip {Start recording if the audio level exceeds the "Signal present" level set in the "Audio" tab} xywh {55 362 205 18} down_box DOWN_BOX + } + Fl_Value_Input input_rec_signal { + callback {input_rec_signal_cb();} + xywh {266 362 42 19} when 4 + } + Fl_Box {} { + label seconds + xywh {308 363 64 16} align 20 + } + Fl_Check_Button check_rec_silence { + label {Stop if signal is absent for} + callback {check_rec_silence_cb();} + tooltip {Stop recording if the audio level falls below the "Signal absent level set in the "Audio" tab} xywh {55 385 205 18} down_box DOWN_BOX + } + Fl_Value_Input input_rec_silence { + callback {input_rec_silence_cb();} + xywh {266 386 42 19} when 4 + } + Fl_Box {} { + label seconds + xywh {308 386 62 16} align 20 + } + Fl_Check_Button check_cfg_overwrite_existing_files { + label {Overwrite existing files} + callback {check_cfg_overwrite_existing_files_cb();} + xywh {55 266 300 20} down_box DOWN_BOX + } + } + } + Fl_Group {} { + label DSP + xywh {0 20 434 660} hide + } { + Fl_Button {} { + label Reset + callback {button_eq_reset_cb();} + xywh {320 33 80 19} box ENGRAVED_BOX labelsize 12 + } + Fl_Group {} { + label Equalizer + xywh {30 55 371 225} box ENGRAVED_FRAME align 5 + } { + Fl_Check_Button check_stream_eq { + label Stream + callback {check_stream_eq_cb();} + xywh {35 57 79 25} down_box DOWN_BOX + } + Fl_Check_Button check_rec_eq { + label Rec + callback {check_rec_eq_cb();} + xywh {115 57 60 25} down_box DOWN_BOX + } + Fl_Choice choice_eq_preset { + callback {choice_eq_preset_cb();} + tooltip {Equalizer Preset} xywh {250 62 140 18} down_box BORDER_BOX + } { + MenuItem {} { + label Manual + xywh {0 0 31 20} + } + MenuItem {} { + label Acoustic + xywh {10 10 31 20} + } + MenuItem {} { + label {Bass Booster} + xywh {20 20 31 20} + } + MenuItem {} { + label {Bass Reducer} + xywh {30 30 31 20} + } + MenuItem {} { + label Classical + xywh {40 40 31 20} + } + MenuItem {} { + label Dance + xywh {50 50 31 20} + } + MenuItem {} { + label Deep + xywh {60 60 31 20} + } + MenuItem {} { + label Electronic + xywh {70 70 31 20} + } + MenuItem {} { + label {Hip-Hop} + xywh {80 80 31 20} + } + MenuItem {} { + label Jazz + xywh {90 90 31 20} + } + MenuItem {} { + label Latin + xywh {100 100 31 20} + } + MenuItem {} { + label Loudness + xywh {110 110 31 20} + } + MenuItem {} { + label Lounge + xywh {120 120 31 20} + } + MenuItem {} { + label Piano + xywh {130 130 31 20} + } + MenuItem {} { + label RnB + xywh {140 140 31 20} + } + MenuItem {} { + label Rock + xywh {150 150 31 20} + } + MenuItem {} { + label Speech + xywh {160 160 31 20} + } + MenuItem {} { + label {Treble Booster} + xywh {170 170 31 20} + } + MenuItem {} { + label {Treble Reducer} + xywh {180 180 31 20} + } + MenuItem {} { + label {Vocal Booster} + xywh {190 190 31 20} + } + } + Fl_Text_Display equalizerGain1 { + label {+0.0} + xywh {31 105 51 10} box NO_BOX labelsize 11 + } + Fl_Slider equalizerSlider1 { + label 32Hz + callback {slider_equalizer1_cb(o->value());} + xywh {53 105 15 150} type {Vert Knob} box NO_BOX labelsize 11 minimum 15 maximum -15 step 0.1 slider_size 0.151515 + code0 {equalizerSlider1->default_value = 0.0;} + class Fl_My_Value_Slider + } + Fl_Text_Display equalizerGain2 { + label {+0.0} + xywh {74 105 35 10} box NO_BOX labelsize 11 + } + Fl_Slider equalizerSlider2 { + label 64Hz + callback {slider_equalizer2_cb(o->value());} + xywh {88 105 15 150} type {Vert Knob} box NO_BOX labelsize 11 minimum 15 maximum -15 step 0.1 slider_size 0.151515 + code0 {equalizerSlider2->default_value = 0.0;} + class Fl_My_Value_Slider + } + Fl_Text_Display equalizerGain3 { + label {+0.0} + xywh {109 105 35 10} box NO_BOX labelsize 11 + } + Fl_Slider equalizerSlider3 { + label 125Hz + callback {slider_equalizer3_cb(o->value());} + xywh {123 105 15 150} type {Vert Knob} box NO_BOX labelsize 11 minimum 15 maximum -15 step 0.1 slider_size 0.151515 + code0 {equalizerSlider3->default_value = 0.0;} + class Fl_My_Value_Slider + } + Fl_Text_Display equalizerGain4 { + label {+0.0} + xywh {144 105 35 10} box NO_BOX labelsize 11 + } + Fl_Slider equalizerSlider4 { + label 250Hz + callback {slider_equalizer4_cb(o->value());} + xywh {158 105 15 150} type {Vert Knob} box NO_BOX labelsize 11 minimum 15 maximum -15 step 0.1 slider_size 0.151515 + code0 {equalizerSlider4->default_value = 0.0;} + class Fl_My_Value_Slider + } + Fl_Text_Display equalizerGain5 { + label {+0.0} + xywh {179 105 35 10} box NO_BOX labelsize 11 + } + Fl_Slider equalizerSlider5 { + label 500Hz + callback {slider_equalizer5_cb(o->value());} + xywh {193 105 15 150} type {Vert Knob} box NO_BOX labelsize 11 minimum 15 maximum -15 step 0.1 slider_size 0.151515 + code0 {equalizerSlider5->default_value = 0.0;} + class Fl_My_Value_Slider + } + Fl_Text_Display equalizerGain6 { + label {+0.0} + xywh {214 105 35 10} box NO_BOX labelsize 11 + } + Fl_Slider equalizerSlider6 { + label 1kHz + callback {slider_equalizer6_cb(o->value());} + xywh {228 105 15 150} type {Vert Knob} box NO_BOX labelsize 11 minimum 15 maximum -15 step 0.1 slider_size 0.151515 + code0 {equalizerSlider6->default_value = 0.0;} + class Fl_My_Value_Slider + } + Fl_Text_Display equalizerGain7 { + label {+0.0} + xywh {249 105 35 10} box NO_BOX labelsize 11 + } + Fl_Slider equalizerSlider7 { + label 2kHz + callback {slider_equalizer7_cb(o->value());} + xywh {263 105 15 150} type {Vert Knob} box NO_BOX labelsize 11 minimum 15 maximum -15 step 0.1 slider_size 0.151515 + code0 {equalizerSlider7->default_value = 0.0;} + class Fl_My_Value_Slider + } + Fl_Text_Display equalizerGain8 { + label {+0.0} + xywh {284 105 35 10} box NO_BOX labelsize 11 + } + Fl_Slider equalizerSlider8 { + label 4kHz + callback {slider_equalizer8_cb(o->value());} + xywh {298 105 15 150} type {Vert Knob} box NO_BOX labelsize 11 minimum 15 maximum -15 step 0.1 slider_size 0.151515 + code0 {equalizerSlider8->default_value = 0.0;} + class Fl_My_Value_Slider + } + Fl_Text_Display equalizerGain9 { + label {+0.0} + xywh {319 105 35 10} box NO_BOX labelsize 11 + } + Fl_Slider equalizerSlider9 { + label 8kHz + callback {slider_equalizer9_cb(o->value());} + xywh {333 105 15 150} type {Vert Knob} box NO_BOX labelsize 11 minimum 15 maximum -15 step 0.1 slider_size 0.151515 + code0 {equalizerSlider9->default_value = 0.0;} + class Fl_My_Value_Slider + } + Fl_Text_Display equalizerGain10 { + label {+0.0} + xywh {354 105 35 10} box NO_BOX labelsize 11 + } + Fl_Slider equalizerSlider10 { + label 16kHz + callback {slider_equalizer10_cb(o->value());} + xywh {368 105 15 150} type {Vert Knob} box NO_BOX labelsize 11 minimum 15 maximum -15 step 0.1 slider_size 0.151515 + code0 {equalizerSlider10->default_value = 0.0;} + class Fl_My_Value_Slider + } + } + Fl_Button {} { + label Reset + callback {button_drc_reset_cb();} + xywh {320 301 80 19} box ENGRAVED_BOX labelsize 12 + } + Fl_Group {} { + label {Dynamic Range Compressor} + xywh {30 323 371 225} box ENGRAVED_FRAME align 5 + } { + Fl_Check_Button check_stream_drc { + label Stream + callback {check_stream_drc_cb();} + xywh {35 326 79 25} down_box DOWN_BOX + } + Fl_Check_Button check_rec_drc { + label Rec + callback {check_rec_drc_cb();} + xywh {110 325 60 25} down_box DOWN_BOX + } + Fl_Check_Button check_aggressive_mode { + label {Aggressive Mode} + callback {check_aggressive_mode_cb();} + xywh {259 328 130 20} down_box DOWN_BOX + } + Fl_Text_Display threshold { + label {+0.0} + xywh {54 378 35 10} box NO_BOX labelsize 11 + } + Fl_Slider thresholdSlider { + label Threshold + callback {slider_threshold_cb(o->value());} + xywh {68 378 15 150} type {Vert Knob} box NO_BOX labelsize 11 maximum -60 step 0.1 value -20 slider_size 0.151515 + code0 {thresholdSlider->default_value = -20.0;} + class Fl_My_Value_Slider + } + Fl_Text_Display ratio { + label {+0.0} + xywh {124 378 35 10} box NO_BOX labelsize 11 + } + Fl_Slider ratioSlider { + label Ratio + callback {slider_ratio_cb(o->value());} + xywh {138 378 15 150} type {Vert Knob} box NO_BOX labelsize 11 minimum 10 step 0.1 value 5 slider_size 0.151515 + code0 {ratioSlider->default_value = 5.0;} + class Fl_My_Value_Slider + } + Fl_Text_Display attack { + label {+0.00} + xywh {197 378 35 10} box NO_BOX labelsize 11 + } + Fl_Slider attackSlider { + label Attack + callback {slider_attack_cb(o->value());} + xywh {208 378 15 150} type {Vert Knob} box NO_BOX labelsize 11 minimum 1 maximum 0 step 0.001 value 0.01 slider_size 0.151515 + code0 {attackSlider->default_value = 0.01;} + class Fl_My_Value_Slider + } + Fl_Text_Display release { + label {+0.00} + xywh {267 378 35 10} box NO_BOX labelsize 11 + } + Fl_Slider releaseSlider { + label Release + callback {slider_release_cb(o->value());} + xywh {278 378 14 150} type {Vert Knob} box NO_BOX labelsize 11 minimum 10 maximum 0 step 0.01 value 1 slider_size 0.151515 + code0 {releaseSlider->default_value = 1.0;} + class Fl_My_Value_Slider + } + Fl_Text_Display makeup { + label {+0.0} + xywh {334 378 35 10} box NO_BOX labelsize 11 + } + Fl_Slider makeupSlider { + label MakeupGain + callback {slider_makeup_cb(o->value());} + xywh {348 378 15 150} type {Vert Knob} box NO_BOX labelsize 11 minimum 30 maximum 0 step 0.01 value 1 slider_size 0.151515 + class Fl_My_Value_Slider + } + Fl_Group LED_comp_threshold { + xywh {36 529 10 10} box BORDER_BOX + code0 {\#include "Fl_LED.h"} + class LED + } {} + } + } + Fl_Group {} { + label MIDI + xywh {1 20 434 660} hide + } { + Fl_Choice choice_midi_dev { + label {MIDI Device} + callback {choice_midi_dev_cb();} open + tooltip {Select your MIDI device} xywh {51 65 330 20} down_box FLAT_BOX align 5 + } {} + Fl_Button button_midi_rescan_devices { + label Rescan + callback {button_midi_rescan_devices_cb();} + tooltip {Rescan MIDI devices} xywh {51 90 120 25} box ENGRAVED_BOX + } + Fl_Group LED_midi_command { + label MIDI + tooltip {MIDI signal indicator} xywh {336 95 10 10} box BORDER_BOX align 8 + code0 {\#include "Fl_LED.h"} + class LED + } {} + Fl_Browser browser_midi_command { + label {MIDI Commands} + callback {browser_midi_command_cb();} + xywh {51 165 330 190} type Hold align 5 + } + Fl_Check_Button check_midi_command_enable { + label Enable + callback {check_midi_command_enable_cb();} + tooltip {Enable/Disable the selected MIDI command} xywh {51 364 145 33} down_box DOWN_BOX + } + Fl_Group group_midi_command_settings {open + xywh {51 392 330 141} box ENGRAVED_FRAME + } { + Fl_Choice choice_midi_channel { + label Channel + callback {choice_midi_channel_cb();} + tooltip {Select MIDI channel} xywh {61 419 80 25} box ENGRAVED_BOX down_box BORDER_BOX align 5 + } { + MenuItem {} { + label Any + xywh {65 65 40 25} + } + MenuItem {} { + label 1 + xywh {55 55 40 25} + } + MenuItem {} { + label 2 + xywh {65 65 40 25} + } + MenuItem {} { + label 3 + xywh {75 75 40 25} + } + MenuItem {} { + label 4 + xywh {85 85 40 25} + } + MenuItem {} { + label 5 + xywh {95 95 40 25} + } + MenuItem {} { + label 6 + xywh {105 105 40 25} + } + MenuItem {} { + label 7 + xywh {115 115 40 25} + } + MenuItem {} { + label 8 + xywh {125 125 40 25} + } + MenuItem {} { + label 9 + xywh {135 135 40 25} + } + MenuItem {} { + label 10 + xywh {145 145 40 25} + } + MenuItem {} { + label 11 + xywh {155 155 40 25} + } + MenuItem {} { + label 12 + xywh {165 165 40 25} + } + MenuItem {} { + label 13 + xywh {175 175 40 25} + } + MenuItem {} { + label 14 + xywh {185 185 40 25} + } + MenuItem {} { + label 15 + xywh {195 195 40 25} + } + MenuItem {} { + label 16 + xywh {205 205 40 25} + } + } + Fl_Value_Input input_midi_msg_num { + label CC + callback {input_midi_msg_num_cb();} + tooltip {Select CC number} xywh {156 418 45 25} align 5 maximum 127 + } + Fl_Button button_midi_learn { + label Learn + callback {button_midi_learn_cb();} + tooltip {Activate to auto detect the channel and CC number} xywh {215 417 151 25} type Toggle box ENGRAVED_BOX + } + Fl_Choice choice_midi_cc_mode { + label {CC Mode} + callback {choice_midi_cc_mode_cb();} open + tooltip {Select CC mode} xywh {61 470 143 25} box ENGRAVED_BOX down_box BORDER_BOX align 5 + } { + MenuItem {} { + label Absolute + xywh {75 75 40 25} + } + MenuItem {} { + label {Relative (Twos Complement)} + xywh {65 65 40 25} + } + MenuItem {} { + label {Relative (Binary Offset)} + xywh {75 75 40 25} + } + MenuItem {} { + label {Relative (Sign Magnitude)} + xywh {85 85 40 25} + } + } + Fl_Check_Button check_midi_soft_takeover { + label {Soft takeover} + callback {check_midi_soft_takeover_cb();} + tooltip {Prevents jumps when controlling a slider in absolute mode} xywh {60 494 145 33} down_box DOWN_BOX + } + } + } + Fl_Group {} { + label TLS + xywh {0 20 434 660} hide + } { + Fl_Group {} { + label {SSL/TLS} open + xywh {50 55 326 184} box ENGRAVED_FRAME align 5 + } { + Fl_Box {} { + label {If your server uses a certificate from +Let's Encrypt or another well known +CA, you can leave these fields blank.} + xywh {56 67 272 60} align 20 + } + Fl_Input input_tls_cert_file { + label {CA Certificate File:} + callback {input_tls_cert_file_cb();} + tooltip {Certificate file} xywh {58 149 275 25} align 5 + code0 {this->input_tls_cert_file->maximum_size(500);} + } + Fl_Button button_tls_browse_file { + callback {button_tls_browse_file_cb();} + tooltip {Select certificate file} image {../xpm/folder.png} xywh {338 149 25 25} box ENGRAVED_BOX + } + Fl_Input input_tls_cert_dir { + label {CA Certificate Directory:} + callback {input_tls_cert_dir_cb();} + tooltip {Certificate directory} xywh {58 200 275 25} align 5 + code0 {this->input_tls_cert_dir->maximum_size(500);} + } + Fl_Button button_tls_browse_dir { + callback {button_tls_browse_dir_cb();} + tooltip {Select certificate directory} image {../xpm/folder.png} xywh {338 200 25 25} box ENGRAVED_BOX + } + } + } + Fl_Group {} { + label GUI + xywh {0 20 434 660} hide + } { + Fl_Group {} { + label Language + xywh {45 58 129 42} box ENGRAVED_FRAME align 5 + } { + Fl_Choice choice_gui_language { + callback {choice_gui_language_cb();} + xywh {58 68 102 20} down_box BORDER_BOX + } { + MenuItem {} { + label System + xywh {0 0 31 20} + } + MenuItem {} { + label {العرب} + xywh {10 10 31 20} + } + MenuItem {} { + label Deutsch + xywh {0 0 31 20} + } + MenuItem {} { + label English + xywh {0 0 31 20} + } + MenuItem {} { + label {Español} + xywh {20 20 31 20} + } + MenuItem {} { + label {Français} + xywh {10 10 31 20} + } + MenuItem {} { + label Nederlands + xywh {0 0 31 20} + } + MenuItem {} { + label {Português Brasileiro} + xywh {10 10 31 20} + } + } + } + Fl_Group {} { + label {Display Color} + xywh {185 58 209 42} box ENGRAVED_FRAME align 5 + } { + Fl_Button button_gui_text_color { + label Text + callback {button_gui_text_color_cb();} + tooltip {Select text color} xywh {198 68 25 25} box SHADOW_BOX color 7 align 8 + } + Fl_Button button_gui_bg_color { + label Background + callback {button_gui_bg_color_cb();} + tooltip {Select background color} xywh {277 68 25 25} box SHADOW_BOX color 15 align 8 + } + } + Fl_Group {} { + label {VU meter} open + xywh {45 135 350 130} box ENGRAVED_FRAME align 5 + } { + Fl_Round_Button radio_gui_vu_gradient { + label {Gradient colors} + callback {radio_gui_vu_gradient_cb();} + xywh {56 150 144 15} type Radio down_box ROUND_DOWN_BOX + } + Fl_Round_Button radio_gui_vu_solid { + label {Solid colors} + callback {radio_gui_vu_solid_cb();} + xywh {56 175 139 15} type Radio down_box ROUND_DOWN_BOX + } + Fl_Check_Button check_gui_always_show_vu_tabs { + label {Always show tabs} + callback {check_gui_always_show_vu_tabs_cb();} + xywh {200 150 165 15} down_box DOWN_BOX + } + Fl_Button button_gui_vu_low_color { + callback {button_gui_vu_low_color_cb();} + tooltip {Select lower range color} xywh {55 200 40 25} box SHADOW_BOX color 61 align 8 + } + Fl_Button button_gui_vu_mid_color { + callback {button_gui_vu_mid_color_cb();} + tooltip {Select mid range color} xywh {100 200 40 25} box SHADOW_BOX color 94 align 8 + } + Fl_Button button_gui_vu_high_color { + callback {button_gui_vu_high_color_cb();} + tooltip {Select high range color} xywh {145 200 40 25} box SHADOW_BOX color 80 align 8 + } + Fl_Value_Output {} { + tooltip {Low range start value (dB)} xywh {55 236 40 19} value -54 + } + Fl_Value_Input input_gui_vu_mid_range_start { + callback {input_gui_vu_mid_range_start_cb();} + tooltip {Mid range start value (dB)} xywh {100 236 40 19} align 5 when 4 minimum -54 maximum 0 value -12 + } + Fl_Value_Input input_gui_vu_high_range_start { + callback {input_gui_vu_high_range_start_cb();} + tooltip {High range start value (dB)} xywh {145 236 40 19} align 5 when 4 minimum -54 maximum 0 value -6 + } + } + Fl_Group {} { + label Misc open + xywh {45 305 350 295} box ENGRAVED_FRAME align 5 + } { + Fl_Check_Button check_gui_attach { + label {Attach settings window to main window} + callback {check_gui_attach_cb();} + tooltip {Attach this window to the butt window} xywh {56 314 300 20} down_box DOWN_BOX + } + Fl_Check_Button check_gui_ontop { + label {Stay always on top} + callback {check_gui_ontop_cb();} + tooltip {Stay always on top} xywh {56 339 175 20} down_box DOWN_BOX + } + Fl_Check_Button check_gui_remember_pos { + label {Remember main window position} + callback {check_gui_remember_pos_cb();} + tooltip {Remember main window position} xywh {56 364 260 20} down_box DOWN_BOX + } + Fl_Check_Button check_gui_hide_log_window { + label {Hide log window after start up} + callback {check_gui_hide_log_window_cb();} + tooltip {Hide log window after start up} xywh {56 389 220 20} down_box DOWN_BOX + } + Fl_Check_Button check_gui_lcd_auto { + label {Change display mode every 5 seconds} + callback {check_gui_lcd_auto_cb()} + tooltip {Change display mode every 5 seconds} xywh {56 414 295 20} down_box DOWN_BOX + } + Fl_Check_Button check_gui_start_minimized { + label {Start minimized} + callback {check_gui_start_minimized_cb();} + tooltip {Minimize butt at startup} xywh {56 439 149 20} down_box DOWN_BOX + } + Fl_Check_Button check_gui_disable_gain_slider { + label {Disable gain control} + callback {check_gui_disable_gain_slider_cb();} + xywh {56 464 194 20} down_box DOWN_BOX + } + Fl_Group {} {open + xywh {56 489 324 50} box ENGRAVED_FRAME + } { + Fl_Check_Button check_gui_show_listeners { + label {Show listeners} + callback {check_gui_show_listeners_cb();} + tooltip {Show current listeners in the display (not always available)} xywh {61 493 194 23} down_box DOWN_BOX + } + Fl_Value_Input input_gui_listeners_update_rate { + label {Update rate:} + callback {input_gui_listeners_update_rate_cb();} + xywh {263 513 42 19} align 5 when 4 + } + Fl_Box {} { + label seconds + xywh {305 514 70 17} align 20 + } + } + Fl_Input input_gui_window_title { + label {Custom window title:} + callback {input_gui_window_title_cb();} + tooltip {Define a custom window title} xywh {55 566 325 25} align 5 when 1 + code0 {this->input_gui_window_title->maximum_size(500);} + } + } + } + Fl_Group {} { + label Donate + xywh {0 20 434 660} hide + } { + Fl_Group {} { + label Donation open + xywh {55 70 326 360} box ENGRAVED_FRAME align 5 + } { + Fl_Box {} { + label {Keeping this software up to date, adding +new features and answering support mails +takes a lot of time and effort. If you can +afford it, please consider supporting this +project. + +Thank you!} + xywh {67 75 308 150} align 20 + } + Fl_Button {} { + label {&Donate via PayPal} + callback {fl_open_uri("https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=LTRSQNTWN4L6L&source=url");} + xywh {67 225 300 28} box ENGRAVED_BOX + code0 {\#include } + } + Fl_Button {} { + label {Become a &patron} + callback {fl_open_uri("https://www.patreon.com/butt_broadcast");} + xywh {67 272 300 27} box ENGRAVED_BOX + code0 {\#include } + } + Fl_Button {} { + label {&Apple Pay, Google Pay, CC and more} + callback {fl_open_uri("https://donorbox.org/butt");} + xywh {67 317 300 28} box ENGRAVED_BOX + code0 {\#include } + } + Fl_Button {} { + label {&Bitcoin && Co} + callback {this->window_donate_crypto->position(this->window_cfg->x(), this->window_cfg->y()); +this->window_donate_crypto->show();} + xywh {67 361 300 28} box ENGRAVED_BOX + } + } + } + } + } + Fl_Window window_add_srv { + label {Add server} open + xywh {572 241 395 522} type Double modal visible + } { + Fl_Input input_add_srv_name { + label {Name:} + xywh {70 27 245 23} align 5 + code0 {this->input_add_srv_name->maximum_size(100);} + } + Fl_Input input_add_srv_addr { + label {Address:} + xywh {10 216 295 25} align 5 + code0 {this->input_add_srv_addr->maximum_size(100);} + } + Fl_Input input_add_srv_port { + label {Port:} + xywh {315 216 75 25} type Int align 5 + } + Fl_Input input_add_srv_pwd { + label {Password:} + xywh {10 261 295 25} type Secret align 5 + code0 {this->input_add_srv_pwd->maximum_size(100);} + } + Fl_Input input_add_srv_mount { + label {Icecast mountpoint:} + xywh {10 311 215 25} align 5 + code0 {this->input_add_srv_mount->maximum_size(100);} + } + Fl_Input input_add_srv_usr { + label {Icecast user:} + xywh {235 311 155 25} align 5 + code0 {this->input_add_srv_usr->maximum_size(100);} + } + Fl_Button button_cfg_show_pw { + label Show + callback {button_add_srv_show_pwd_cb();} + tooltip {show/hide password} xywh {315 261 75 25} box ENGRAVED_BOX + } + Fl_Group {} { + label Type + xywh {10 96 125 97} box ENGRAVED_BOX align 5 + } { + Fl_Round_Button radio_add_srv_shoutcast { + label Shoutcast + callback {radio_add_srv_shoutcast_cb();} + xywh {15 105 88 15} type Radio down_box ROUND_DOWN_BOX + } + Fl_Round_Button radio_add_srv_icecast { + label Icecast + callback {radio_add_srv_icecast_cb();} + xywh {15 127 80 12} type Radio down_box ROUND_DOWN_BOX + } + Fl_Round_Button radio_add_srv_webrtc { + label WebRTC + callback {radio_add_srv_webrtc_cb();} + xywh {15 149 80 12} type Radio down_box ROUND_DOWN_BOX + } + Fl_Round_Button radio_add_srv_radioco { + label {Radio.co} + callback {radio_add_srv_radioco_cb();} + xywh {15 171 80 12} type Radio down_box ROUND_DOWN_BOX + } + } + Fl_Button {} { + label {&Cancel} + callback {button_add_srv_cancel_cb();} + xywh {10 478 85 25} box ENGRAVED_BOX + } + Fl_Button button_add_srv_add { + label {&ADD} + callback {button_add_srv_add_cb();} + xywh {305 478 85 25} box ENGRAVED_BOX + } + Fl_Button button_add_srv_save { + label {&Save} + callback {button_add_srv_save_cb();} + xywh {305 478 85 25} box ENGRAVED_BOX + } + Fl_Group frame_add_srv_tls { + label {SSL/TLS} + xywh {140 96 250 97} box ENGRAVED_BOX align 5 + } { + Fl_Check_Button check_add_srv_tls { + label {Use SSL/TLS} + xywh {148 100 190 20} down_box DOWN_BOX + } + Fl_Button button_add_srv_revoke_cert { + label {Revoke certificate trust} + callback {button_add_srv_revoke_cert_cb();} + xywh {150 157 225 25} box ENGRAVED_BOX + } + } + Fl_Check_Browser browser_add_srv_station_list { + label {Radio.co Stations} + xywh {140 216 250 83} align 5 + } + Fl_Button button_add_srv_get_stations { + label {Get Stations} + callback {button_add_srv_get_stations_cb();} + xywh {10 205 120 25} box ENGRAVED_BOX + } + Fl_Button button_add_srv_select_all { + label {Select all} + callback {button_add_srv_select_all_cb();} + xywh {140 301 120 20} box ENGRAVED_BOX + } + Fl_Button button_add_srv_deselect_all { + label {Deselect all} + callback {button_add_srv_deselect_all_cb();} + xywh {265 301 125 20} box ENGRAVED_BOX + } + Fl_Check_Button check_add_srv_protocol { + label {Use legacy Icecast protocol} + tooltip {Activate this if you want to use the older SOURCE protocol instead of the newer PUT protocol} xywh {8 345 297 15} down_box DOWN_BOX + } + Fl_Input input_webrtc_icesrv_url { + label {ICE server (optional):} + xywh {10 215 380 25} align 5 + } + Fl_Input input_webrtc_whip_url { + label {WebRTC (WHIP) URL:} + xywh {10 260 380 25} align 5 + } + Fl_Input input_webrtc_auth_token { + label {Bearer token (optional):} + xywh {10 305 380 25} align 5 + } + Fl_Input input_add_srv_listener_url { + label {Custom listener URL (optional):} + xywh {10 393 380 25} align 5 + code0 {this->input_add_srv_listener_url->maximum_size(100);} + } + Fl_Input input_add_srv_listener_mount { + label {Custom listener mountpoint (optional):} selected + xywh {10 441 380 25} align 5 + code0 {this->input_add_srv_listener_mount->maximum_size(100);} + } + } + Fl_Window window_add_icy { + label {Add stream info} + xywh {1158 448 305 380} type Double hide modal + } { + Fl_Input input_add_icy_name { + label {Name:} + tooltip {The name of your new ICY-entrie} xywh {10 35 285 25} align 5 + code0 {this->input_add_icy_name->maximum_size(100);} + } + Fl_Input input_add_icy_desc { + label {Description:} + xywh {10 145 170 25} align 5 + code0 {this->input_add_icy_desc->maximum_size(100);} + } + Fl_Input input_add_icy_genre { + label {Genre:} + xywh {185 145 110 25} align 5 + code0 {this->input_add_icy_genre->maximum_size(100);} + } + Fl_Input input_add_icy_url { + label {URL:} + xywh {10 190 170 25} align 5 + code0 {this->input_add_icy_url->maximum_size(100);} + } + Fl_Input input_add_icy_icq { + label {ICQ:} + xywh {185 190 110 25} align 5 + code0 {this->input_add_icy_icq->maximum_size(100);} + } + Fl_Input input_add_icy_irc { + label {IRC:} + xywh {10 235 170 25} align 5 + code0 {this->input_add_icy_irc->maximum_size(100);} + } + Fl_Input input_add_icy_aim { + label {AIM:} + xywh {185 235 110 25} align 5 + code0 {this->input_add_icy_aim->maximum_size(100);} + } + Fl_Check_Button check_add_icy_pub { + label {Make server public} + xywh {10 270 235 20} down_box DOWN_BOX + } + Fl_Check_Button check_expand_variables { + label {Expand variables} + tooltip {Activate to expand date variables in name and description} xywh {10 295 235 20} down_box DOWN_BOX + } + Fl_Button {} { + label {&Cancel} + callback {button_add_icy_cancel_cb();} + xywh {10 340 74 25} box ENGRAVED_BOX + } + Fl_Button button_add_icy_add { + label {&ADD} + callback {button_add_icy_add_cb();} + xywh {224 340 74 25} box ENGRAVED_BOX + } + Fl_Button button_add_icy_save { + label {&Save} + callback {button_add_icy_save_cb();} + xywh {224 340 74 25} box ENGRAVED_BOX + } + } + code {Fl::scheme("standard"); +window_main->label(PACKAGE_STRING); + +info_buffer = new Fl_Text_Buffer(); +info_output->buffer(info_buffer); + +//window_cfg->size(window_cfg->w(), 380); + +// show info output... +info_visible = 1; + +info_output->show();} {} + Fl_Window window_donate_crypto { + label {Donate Cryptocurrency} + xywh {590 548 460 255} type Double hide + class Fl_My_Double_Window + } { + Fl_Output output_bitcoin_addr { + label Bitcoin + xywh {20 40 320 22} box FLAT_BOX align 5 + code0 {output_bitcoin_addr->value("bc1q4uq7h464rsu2cudrmuuqmc4tcr98d0edrhe5au");} + } + Fl_Button {} { + label Copy + callback {int len = this->output_bitcoin_addr->size(); +this->output_bitcoin_addr->position(0, len); +this->output_bitcoin_addr->copy(1); + +fl_message(_("Bitcoin address has been copied to clipboard."));} + xywh {350 40 88 22} box ENGRAVED_BOX + code0 {\#include } + } + Fl_Output output_litecoin_addr { + label Litecoin + xywh {20 100 320 22} box FLAT_BOX align 5 + code0 {output_litecoin_addr->value("Ld9gntf8fsYpmVcbstFkzz5R3sNPC3AhTx");} + } + Fl_Button {} { + label Copy + callback {int len = this->output_litecoin_addr->size(); +this->output_litecoin_addr->position(0, len); +this->output_litecoin_addr->copy(1); + +fl_message(_("Litecoin address has been copied to clipboard."));} + xywh {350 100 88 22} box ENGRAVED_BOX + code0 {\#include } + } + Fl_Output output_monero_addr { + label Monero + xywh {20 160 320 22} box FLAT_BOX align 5 + code0 {output_monero_addr->value("85u8DacasxPNvKzY5kEiprBnbydDqg26yGAVEw7mdwccNFsrXMWCE4VQnV2JVfh5BTRheNnpDJqYjbqPrVRLEPAKP3dsYgc");} + } + Fl_Button {} { + label Copy + callback {int len = this->output_monero_addr->size(); +this->output_monero_addr->position(0, len); +this->output_monero_addr->copy(1); + +fl_message(_("Monero address has been copied to clipboard."));} + xywh {350 160 88 22} box ENGRAVED_BOX + code0 {\#include } + } + Fl_Button {} { + label {&Close} + callback {this->window_donate_crypto->hide();} + xywh {20 217 88 22} box ENGRAVED_BOX + } + } + Fl_Window window_stream_codec_settings { + label {Streaming Codec Settings} + xywh {70 97 395 385} type Double hide + class Fl_My_Double_Window + } { + Fl_Tabs tabs_stream_codec_settings {open + xywh {5 0 385 350} + } { + Fl_Group tab_stream_mp3 { + label MP3 open + xywh {5 20 385 330} + } { + Fl_Choice choice_stream_mp3_enc_quality { + label {Encoding Quality} + callback {choice_stream_mp3_enc_quality_cb();} + xywh {25 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {0 (best)} + xywh {0 0 36 21} + } + MenuItem {} { + label 1 + xywh {10 10 36 21} + } + MenuItem {} { + label 2 + xywh {20 20 36 21} + } + MenuItem {} { + label {3 (default)} + xywh {30 30 36 21} + } + MenuItem {} { + label 4 + xywh {40 40 36 21} + } + MenuItem {} { + label 5 + xywh {50 50 36 21} + } + MenuItem {} { + label 6 + xywh {60 60 36 21} + } + MenuItem {} { + label 7 + xywh {70 70 36 21} + } + MenuItem {} { + label 8 + xywh {80 80 36 21} + } + MenuItem {} { + label {9 (worst)} + xywh {80 80 36 21} + } + } + Fl_Choice choice_stream_mp3_stereo_mode { + label {Stereo Mode} + callback {choice_stream_mp3_stereo_mode_cb();} + xywh {210 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {Auto (default)} + xywh {10 10 36 21} + } + MenuItem {} { + label Stereo + xywh {30 30 36 21} + } + MenuItem {} { + label {Joint Stereo} + xywh {20 20 36 21} + } + } + Fl_Choice choice_stream_mp3_bitrate_mode { + label {Bitrate Mode} + callback {choice_stream_mp3_bitrate_mode_cb();} + xywh {25 110 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {CBR (default)} + xywh {20 20 36 21} + } + MenuItem {} { + label VBR + xywh {30 30 36 21} + } + MenuItem {} { + label ABR + xywh {40 40 36 21} + } + } + Fl_Group {} { + label VBR open + xywh {19 167 125 162} box ENGRAVED_FRAME align 5 + } { + Fl_Choice choice_stream_mp3_vbr_quality { + label Quality + callback {choice_stream_mp3_vbr_quality_cb();} open + xywh {27 191 110 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {0 (best)} + xywh {10 10 36 21} + } + MenuItem {} { + label 1 + xywh {20 20 36 21} + } + MenuItem {} { + label 2 + xywh {30 30 36 21} + } + MenuItem {} { + label 3 + xywh {40 40 36 21} + } + MenuItem {} { + label {4 (default)} + xywh {50 50 36 21} + } + MenuItem {} { + label 5 + xywh {60 60 36 21} + } + MenuItem {} { + label 6 + xywh {70 70 36 21} + } + MenuItem {} { + label 7 + xywh {80 80 36 21} + } + MenuItem {} { + label 8 + xywh {90 90 36 21} + } + MenuItem {} { + label {9 (worst)} + xywh {90 90 36 21} + } + } + Fl_Choice choice_stream_mp3_vbr_min_bitrate { + label {Min. Bitrate} + callback {choice_stream_mp3_vbr_min_bitrate_cb();} open + xywh {27 236 110 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label 8k + xywh {60 60 40 25} + } + MenuItem {} { + label 16k + xywh {50 50 40 25} + } + MenuItem {} { + label 24k + xywh {60 60 40 25} + } + MenuItem {} { + label {32k (default)} + xywh {40 40 40 25} + } + MenuItem {} { + label 40k + xywh {50 50 40 25} + } + MenuItem {} { + label 48k + xywh {60 60 40 25} + } + MenuItem {} { + label 56k + xywh {70 70 40 25} + } + MenuItem {} { + label 64k + xywh {80 80 40 25} + } + MenuItem {} { + label 80k + xywh {90 90 40 25} + } + MenuItem {} { + label 96k + xywh {100 100 40 25} + } + MenuItem {} { + label 112k + xywh {40 40 40 25} + } + MenuItem {} { + label 128k + xywh {110 110 40 25} + } + MenuItem {} { + label 160k + xywh {120 120 40 25} + } + MenuItem {} { + label 192k + xywh {130 130 40 25} + } + MenuItem {} { + label 224k + xywh {140 140 40 25} + } + MenuItem {} { + label 256k + xywh {150 150 40 25} + } + MenuItem {} { + label 320k + xywh {160 160 40 25} + } + } + Fl_Choice choice_stream_mp3_vbr_max_bitrate { + label {Max. Bitrate} + callback {choice_stream_mp3_vbr_max_bitrate_cb();} open + xywh {27 301 110 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label 8k + xywh {70 70 40 25} + } + MenuItem {} { + label 16k + xywh {60 60 40 25} + } + MenuItem {} { + label 24k + xywh {70 70 40 25} + } + MenuItem {} { + label 32k + xywh {50 50 40 25} + } + MenuItem {} { + label 40k + xywh {60 60 40 25} + } + MenuItem {} { + label 48k + xywh {70 70 40 25} + } + MenuItem {} { + label 56k + xywh {80 80 40 25} + } + MenuItem {} { + label 64k + xywh {90 90 40 25} + } + MenuItem {} { + label 80k + xywh {100 100 40 25} + } + MenuItem {} { + label 96k + xywh {110 110 40 25} + } + MenuItem {} { + label 112k + xywh {50 50 40 25} + } + MenuItem {} { + label 128k + xywh {120 120 40 25} + } + MenuItem {} { + label 160k + xywh {130 130 40 25} + } + MenuItem {} { + label 192k + xywh {140 140 40 25} + } + MenuItem {} { + label 224k + xywh {150 150 40 25} + } + MenuItem {} { + label 256k + xywh {160 160 40 25} + } + MenuItem {} { + label {320k (default)} + xywh {170 170 40 25} + } + } + Fl_Check_Button check_stream_mp3_force_min_bitrate { + label Force + callback {check_stream_mp3_force_min_bitrate_cb();} + tooltip {Strictly enforce mininum Bitrate (-F option of the lame encoder)} xywh {25 259 117 15} down_box DOWN_BOX + } + } + Fl_Group {} { + label {Lowpass (kHz)} open + xywh {155 167 105 162} box ENGRAVED_FRAME align 5 + } { + Fl_Value_Input input_stream_mp3_lowpass_freq { + label Frequency + callback {input_stream_mp3_lowpass_freq_cb();} + xywh {180 190 70 20} align 5 when 4 deactivate + } + Fl_Value_Input input_stream_mp3_lowpass_width { + label Width + callback {input_stream_mp3_lowpass_width_cb();} + xywh {180 235 70 20} align 5 when 4 deactivate + } + Fl_Check_Button check_stream_mp3_activate_lowpass_freq { + callback {check_stream_mp3_activate_lowpass_freq_cb();} + xywh {159 193 20 15} down_box DOWN_BOX + } + Fl_Check_Button check_stream_mp3_activate_lowpass_width { + callback {check_stream_mp3_activate_lowpass_width_cb();} + xywh {159 238 20 15} down_box DOWN_BOX + } + } + Fl_Group {} { + label {Highpass (kHz)} open + xywh {270 167 105 162} box ENGRAVED_FRAME align 5 + } { + Fl_Value_Input input_stream_mp3_highpass_freq { + label Frequency + callback {input_stream_mp3_highpass_freq_cb();} + xywh {295 189 70 20} align 5 when 4 deactivate + } + Fl_Value_Input input_stream_mp3_highpass_width { + label Width + callback {input_stream_mp3_highpass_width_cb();} + xywh {295 234 70 20} align 5 when 4 deactivate + } + Fl_Check_Button check_stream_mp3_activate_highpass_freq { + callback {check_stream_mp3_activate_highpass_freq_cb();} + xywh {274 192 20 15} down_box DOWN_BOX + } + Fl_Check_Button check_stream_mp3_activate_highpass_width { + callback {check_stream_mp3_activate_highpass_width_cb();} + xywh {274 237 20 15} down_box DOWN_BOX + } + } + Fl_Choice choice_stream_mp3_resampling_freq { + label Resampling + callback {choice_stream_mp3_resampling_freq_cb();} open + tooltip {Resample to the selected sample rate} xywh {210 110 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {Disabled (default)} + xywh {80 80 40 25} + } + MenuItem {} { + label {8000 Hz} + xywh {80 80 40 25} + } + MenuItem {} { + label {11025 Hz} + xywh {70 70 40 25} + } + MenuItem {} { + label {12000 Hz} + xywh {80 80 40 25} + } + MenuItem {} { + label {16000 Hz} + xywh {60 60 40 25} + } + MenuItem {} { + label {22050 Hz} + xywh {70 70 40 25} + } + MenuItem {} { + label {24000 Hz} + xywh {80 80 40 25} + } + MenuItem {} { + label {32000 Hz} + xywh {90 90 40 25} + } + MenuItem {} { + label {44100 Hz} + xywh {100 100 40 25} + } + MenuItem {} { + label {48000 Hz} + xywh {110 110 40 25} + } + } + } + Fl_Group tab_stream_ogg { + label OGG + xywh {5 20 385 330} hide + } { + Fl_Choice choice_stream_vorbis_bitrate_mode { + label {Bitrate Mode} + callback {choice_stream_vorbis_bitrate_mode_cb();} + xywh {25 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {CBR (default)} + xywh {40 40 36 21} + } + MenuItem {} { + label VBR + xywh {50 50 36 21} + } + MenuItem {} { + label ABR + xywh {60 60 36 21} + } + } + Fl_Choice choice_stream_vorbis_vbr_quality { + label {VBR Quality} + callback {choice_stream_vorbis_vbr_quality_cb();} + xywh {210 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {1.0 (best, default)} + xywh {110 110 36 21} + } + MenuItem {} { + label {0.9} + xywh {120 120 36 21} + } + MenuItem {} { + label {0.8} + xywh {110 110 36 21} + } + MenuItem {} { + label {0.7} + xywh {100 100 36 21} + } + MenuItem {} { + label {0.6} + xywh {90 90 36 21} + } + MenuItem {} { + label {0.5} + xywh {80 80 36 21} + } + MenuItem {} { + label {0.4} + xywh {70 70 36 21} + } + MenuItem {} { + label {0.3} + xywh {60 60 36 21} + } + MenuItem {} { + label {0.2} + xywh {50 50 36 21} + } + MenuItem {} { + label {0.1} + xywh {40 40 36 21} + } + MenuItem {} { + label {0.0 (worst)} + xywh {30 30 36 21} + } + } + Fl_Choice choice_stream_vorbis_vbr_min_bitrate { + label {VBR min. Bitrate} + callback {choice_stream_vorbis_vbr_min_bitrate_cb();} open + xywh {25 110 165 20} down_box BORDER_BOX align 5 + } {} + Fl_Choice choice_stream_vorbis_vbr_max_bitrate { + label {VBR max. Bitrate} + callback {choice_stream_vorbis_vbr_max_bitrate_cb();} open + xywh {210 110 165 20} down_box BORDER_BOX align 5 + } {} + } + Fl_Group tab_stream_opus { + label OPUS + xywh {5 20 385 330} hide + } { + Fl_Choice choice_stream_opus_quality { + label Quality + callback {choice_stream_opus_quality_cb();} + xywh {25 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {10 (best, default)} + xywh {100 100 36 21} + } + MenuItem {} { + label 9 + xywh {90 90 36 21} + } + MenuItem {} { + label 8 + xywh {90 90 36 21} + } + MenuItem {} { + label 7 + xywh {80 80 36 21} + } + MenuItem {} { + label 6 + xywh {70 70 36 21} + } + MenuItem {} { + label 5 + xywh {60 60 36 21} + } + MenuItem {} { + label 4 + xywh {50 50 36 21} + } + MenuItem {} { + label 3 + xywh {40 40 36 21} + } + MenuItem {} { + label 2 + xywh {30 30 36 21} + } + MenuItem {} { + label 1 + xywh {20 20 36 21} + } + MenuItem {} { + label {0 (worst)} + xywh {10 10 36 21} + } + } + Fl_Choice choice_stream_opus_audio_type { + label {Optimize for} + callback {choice_stream_opus_audio_type_cb();} + xywh {210 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {Music (default)} + xywh {20 20 36 21} + } + MenuItem {} { + label Speech + xywh {30 30 36 21} + } + } + Fl_Choice choice_stream_opus_bitrate_mode { + label {Bitrate Mode} + callback {choice_stream_opus_bitrate_mode_cb();} + xywh {25 110 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label CBR + xywh {50 50 36 21} + } + MenuItem {} { + label {VBR (default)} + xywh {60 60 36 21} + } + } + Fl_Choice choice_stream_opus_bandwidth { + label {Max. Bandwidth} + callback {choice_stream_opus_bandwidth_cb();} open + xywh {210 110 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {20kHz (best,default)} + xywh {110 110 36 21} + } + MenuItem {} { + label 12kHz + xywh {100 100 36 21} + } + MenuItem {} { + label 8kHz + xywh {90 90 36 21} + } + MenuItem {} { + label 6kHz + xywh {80 80 36 21} + } + MenuItem {} { + label {4kHz (worst)} + xywh {70 70 36 21} + } + } + } + Fl_Group tab_stream_aac { + label AAC + xywh {5 20 385 330} hide + } { + Fl_Choice choice_stream_aac_profile { + label Profile + callback {choice_stream_aac_profile_cb();} + xywh {25 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {Auto (default)} + xywh {20 20 36 21} + } + MenuItem {} { + label {AAC-LC} + xywh {50 50 36 21} + } + MenuItem {} { + label {HE-AACv1 (AAC+)} + xywh {100 100 36 21} + } + MenuItem {} { + label {HE-AACv2 (eAAC+)} + xywh {110 110 36 21} + } + } + Fl_Choice choice_stream_aac_afterburner { + label Afterburner + callback {choice_stream_aac_afterburner_cb();} + xywh {210 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {On (default)} + xywh {110 110 36 21} + } + MenuItem {} { + label Off + xywh {120 120 36 21} + } + } + Fl_Choice choice_stream_aac_bitrate_mode { + label {Bitrate Mode} + callback {choice_stream_aac_bitrate_mode_cb();} + xywh {25 110 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {CBR (default)} + xywh {30 30 36 21} + } + MenuItem {} { + label VBR + xywh {40 40 36 21} + } + } + } + Fl_Group tab_stream_flac { + label FLAC + xywh {5 20 385 330} hide + } { + Fl_Group {} { + label {Bit depth} open + xywh {20 50 355 50} box ENGRAVED_FRAME + } { + Fl_Round_Button radio_stream_flac_bit_depth_16 { + label {16 bit} + callback {radio_stream_flac_bit_depth_16_cb();} + xywh {95 65 70 20} type Radio down_box ROUND_DOWN_BOX + } + Fl_Round_Button radio_stream_flac_bit_depth_24 { + label {24 bit} + callback {radio_stream_flac_bit_depth_24_cb();} + xywh {236 65 79 20} type Radio down_box ROUND_DOWN_BOX + } + } + } + } + Fl_Button {} { + label {&Close} + callback {this->window_stream_codec_settings->hide();} + xywh {150 358 88 22} box ENGRAVED_BOX + } + } + Fl_Window window_rec_codec_settings { + label {Recording Codec Settings} + xywh {516 103 395 385} type Double hide + class Fl_My_Double_Window + } { + Fl_Tabs tabs_rec_codec_settings {open + xywh {5 0 385 350} + } { + Fl_Group tab_rec_mp3 { + label MP3 open + xywh {5 20 385 330} + } { + Fl_Choice choice_rec_mp3_enc_quality { + label {Encoding Quality} + callback {choice_rec_mp3_enc_quality_cb();} + xywh {25 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {0 (best)} + xywh {0 0 36 21} + } + MenuItem {} { + label 1 + xywh {10 10 36 21} + } + MenuItem {} { + label 2 + xywh {20 20 36 21} + } + MenuItem {} { + label {3 (default)} + xywh {30 30 36 21} + } + MenuItem {} { + label 4 + xywh {40 40 36 21} + } + MenuItem {} { + label 5 + xywh {50 50 36 21} + } + MenuItem {} { + label 6 + xywh {60 60 36 21} + } + MenuItem {} { + label 7 + xywh {70 70 36 21} + } + MenuItem {} { + label 8 + xywh {80 80 36 21} + } + MenuItem {} { + label {9 (worst)} + xywh {80 80 36 21} + } + } + Fl_Choice choice_rec_mp3_stereo_mode { + label {Stereo Mode} + callback {choice_rec_mp3_stereo_mode_cb();} + xywh {210 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {Auto (default)} + xywh {10 10 36 21} + } + MenuItem {} { + label Stereo + xywh {30 30 36 21} + } + MenuItem {} { + label {Joint Stereo} + xywh {20 20 36 21} + } + } + Fl_Choice choice_rec_mp3_bitrate_mode { + label {Bitrate Mode} + callback {choice_rec_mp3_bitrate_mode_cb();} + xywh {25 110 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {CBR (default)} + xywh {20 20 36 21} + } + MenuItem {} { + label VBR + xywh {30 30 36 21} + } + MenuItem {} { + label ABR + xywh {40 40 36 21} + } + } + Fl_Group {} { + label VBR open + xywh {19 167 125 162} box ENGRAVED_FRAME align 5 + } { + Fl_Choice choice_rec_mp3_vbr_quality { + label Quality + callback {choice_rec_mp3_vbr_quality_cb();} open + xywh {27 191 110 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {0 (best)} + xywh {10 10 36 21} + } + MenuItem {} { + label 1 + xywh {20 20 36 21} + } + MenuItem {} { + label 2 + xywh {30 30 36 21} + } + MenuItem {} { + label 3 + xywh {40 40 36 21} + } + MenuItem {} { + label {4 (default)} + xywh {50 50 36 21} + } + MenuItem {} { + label 5 + xywh {60 60 36 21} + } + MenuItem {} { + label 6 + xywh {70 70 36 21} + } + MenuItem {} { + label 7 + xywh {80 80 36 21} + } + MenuItem {} { + label 8 + xywh {90 90 36 21} + } + MenuItem {} { + label {9 (worst)} + xywh {90 90 36 21} + } + } + Fl_Choice choice_rec_mp3_vbr_min_bitrate { + label {Min. Bitrate} + callback {choice_rec_mp3_vbr_min_bitrate_cb();} open + xywh {27 236 110 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label 8k + xywh {60 60 40 25} + } + MenuItem {} { + label 16k + xywh {50 50 40 25} + } + MenuItem {} { + label 24k + xywh {60 60 40 25} + } + MenuItem {} { + label {32k (default)} + xywh {40 40 40 25} + } + MenuItem {} { + label 40k + xywh {50 50 40 25} + } + MenuItem {} { + label 48k + xywh {60 60 40 25} + } + MenuItem {} { + label 56k + xywh {70 70 40 25} + } + MenuItem {} { + label 64k + xywh {80 80 40 25} + } + MenuItem {} { + label 80k + xywh {90 90 40 25} + } + MenuItem {} { + label 96k + xywh {100 100 40 25} + } + MenuItem {} { + label 112k + xywh {40 40 40 25} + } + MenuItem {} { + label 128k + xywh {110 110 40 25} + } + MenuItem {} { + label 160k + xywh {120 120 40 25} + } + MenuItem {} { + label 192k + xywh {130 130 40 25} + } + MenuItem {} { + label 224k + xywh {140 140 40 25} + } + MenuItem {} { + label 256k + xywh {150 150 40 25} + } + MenuItem {} { + label 320k + xywh {160 160 40 25} + } + } + Fl_Choice choice_rec_mp3_vbr_max_bitrate { + label {Max. Bitrate} + callback {choice_rec_mp3_vbr_max_bitrate_cb();} open + xywh {27 301 110 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label 8k + xywh {70 70 40 25} + } + MenuItem {} { + label 16k + xywh {60 60 40 25} + } + MenuItem {} { + label 24k + xywh {70 70 40 25} + } + MenuItem {} { + label 32k + xywh {50 50 40 25} + } + MenuItem {} { + label 40k + xywh {60 60 40 25} + } + MenuItem {} { + label 48k + xywh {70 70 40 25} + } + MenuItem {} { + label 56k + xywh {80 80 40 25} + } + MenuItem {} { + label 64k + xywh {90 90 40 25} + } + MenuItem {} { + label 80k + xywh {100 100 40 25} + } + MenuItem {} { + label 96k + xywh {110 110 40 25} + } + MenuItem {} { + label 112k + xywh {50 50 40 25} + } + MenuItem {} { + label 128k + xywh {120 120 40 25} + } + MenuItem {} { + label 160k + xywh {130 130 40 25} + } + MenuItem {} { + label 192k + xywh {140 140 40 25} + } + MenuItem {} { + label 224k + xywh {150 150 40 25} + } + MenuItem {} { + label 256k + xywh {160 160 40 25} + } + MenuItem {} { + label {320k (default)} + xywh {170 170 40 25} + } + } + Fl_Check_Button check_rec_mp3_force_min_bitrate { + label Force + callback {check_rec_mp3_force_min_bitrate_cb();} + tooltip {Strictly enforce mininum Bitrate (-F option of the lame encoder)} xywh {25 259 117 19} down_box DOWN_BOX + } + } + Fl_Choice choice_rec_mp3_resampling_freq { + label Resampling + callback {choice_rec_mp3_resampling_freq_cb();} open + tooltip {Resample to the selected sample rate} xywh {210 110 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {Disabled (default)} + xywh {90 90 40 25} + } + MenuItem {} { + label {8000 Hz} + xywh {90 90 40 25} + } + MenuItem {} { + label {11025 Hz} + xywh {80 80 40 25} + } + MenuItem {} { + label {12000 Hz} + xywh {90 90 40 25} + } + MenuItem {} { + label {16000 Hz} + xywh {70 70 40 25} + } + MenuItem {} { + label {22050 Hz} + xywh {80 80 40 25} + } + MenuItem {} { + label {24000 Hz} + xywh {90 90 40 25} + } + MenuItem {} { + label {32000 Hz} + xywh {100 100 40 25} + } + MenuItem {} { + label {44100 Hz} + xywh {110 110 40 25} + } + MenuItem {} { + label {48000 Hz} + xywh {120 120 40 25} + } + } + Fl_Group {} { + label {Lowpass (kHz)} open + xywh {155 167 105 162} box ENGRAVED_FRAME align 5 + } { + Fl_Value_Input input_rec_mp3_lowpass_freq { + label Frequency + callback {input_rec_mp3_lowpass_freq_cb();} + xywh {180 190 70 20} align 5 when 4 deactivate + } + Fl_Value_Input input_rec_mp3_lowpass_width { + label Width + callback {input_rec_mp3_lowpass_width_cb();} + xywh {180 235 70 20} align 5 when 4 deactivate + } + Fl_Check_Button check_rec_mp3_activate_lowpass_freq { + callback {check_rec_mp3_activate_lowpass_freq_cb();} + xywh {159 193 20 15} down_box DOWN_BOX + } + Fl_Check_Button check_rec_mp3_activate_lowpass_width { + callback {check_rec_mp3_activate_lowpass_width_cb();} + xywh {159 238 20 15} down_box DOWN_BOX + } + } + Fl_Group {} { + label {Highpass (kHz)} open + xywh {270 167 105 162} box ENGRAVED_FRAME align 5 + } { + Fl_Value_Input input_rec_mp3_highpass_freq { + label Frequency + callback {input_rec_mp3_highpass_freq_cb();} + xywh {295 189 70 20} align 5 when 4 deactivate + } + Fl_Value_Input input_rec_mp3_highpass_width { + label Width + callback {input_rec_mp3_highpass_width_cb();} + xywh {295 234 70 20} align 5 when 4 deactivate + } + Fl_Check_Button check_rec_mp3_activate_highpass_freq { + callback {check_rec_mp3_activate_highpass_freq_cb();} + xywh {274 192 20 15} down_box DOWN_BOX + } + Fl_Check_Button check_rec_mp3_activate_highpass_width { + callback {check_rec_mp3_activate_highpass_width_cb();} + xywh {274 237 20 15} down_box DOWN_BOX + } + } + } + Fl_Group tab_rec_ogg { + label OGG + xywh {5 20 385 330} hide + } { + Fl_Choice choice_rec_vorbis_bitrate_mode { + label {Bitrate Mode} + callback {choice_rec_vorbis_bitrate_mode_cb();} + xywh {25 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {CBR (default)} + xywh {40 40 36 21} + } + MenuItem {} { + label VBR + xywh {50 50 36 21} + } + MenuItem {} { + label ABR + xywh {60 60 36 21} + } + } + Fl_Choice choice_rec_vorbis_vbr_quality { + label {VBR Quality} + callback {choice_rec_vorbis_vbr_quality_cb();} + xywh {210 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {1.0 (best, default)} + xywh {110 110 36 21} + } + MenuItem {} { + label {0.9} + xywh {120 120 36 21} + } + MenuItem {} { + label {0.8} + xywh {110 110 36 21} + } + MenuItem {} { + label {0.7} + xywh {100 100 36 21} + } + MenuItem {} { + label {0.6} + xywh {90 90 36 21} + } + MenuItem {} { + label {0.5} + xywh {80 80 36 21} + } + MenuItem {} { + label {0.4} + xywh {70 70 36 21} + } + MenuItem {} { + label {0.3} + xywh {60 60 36 21} + } + MenuItem {} { + label {0.2} + xywh {50 50 36 21} + } + MenuItem {} { + label {0.1} + xywh {40 40 36 21} + } + MenuItem {} { + label {0.0 (worst)} + xywh {30 30 36 21} + } + } + Fl_Choice choice_rec_vorbis_vbr_min_bitrate { + label {VBR min. Bitrate} + callback {choice_rec_vorbis_vbr_min_bitrate_cb();} open + xywh {25 110 165 20} down_box BORDER_BOX align 5 + } {} + Fl_Choice choice_rec_vorbis_vbr_max_bitrate { + label {VBR max. Bitrate} + callback {choice_rec_vorbis_vbr_max_bitrate_cb();} open + xywh {210 110 165 20} down_box BORDER_BOX align 5 + } {} + } + Fl_Group tab_rec_opus { + label OPUS + xywh {5 20 385 330} hide + } { + Fl_Choice choice_rec_opus_audio_type { + label {Optimize for} + callback {choice_rec_opus_audio_type_cb();} open + xywh {210 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {Music (default)} + xywh {20 20 36 21} + } + MenuItem {} { + label Speech + xywh {30 30 36 21} + } + } + Fl_Choice choice_rec_opus_bitrate_mode { + label {Bitrate Mode} + callback {choice_rec_opus_bitrate_mode_cb();} open + xywh {25 110 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label CBR + xywh {50 50 36 21} + } + MenuItem {} { + label {VBR (default)} + xywh {60 60 36 21} + } + } + Fl_Choice choice_rec_opus_quality { + label Quality + callback {choice_rec_opus_quality_cb();} open + xywh {25 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {10 (best, default)} + xywh {100 100 36 21} + } + MenuItem {} { + label 9 + xywh {90 90 36 21} + } + MenuItem {} { + label 8 + xywh {90 90 36 21} + } + MenuItem {} { + label 7 + xywh {80 80 36 21} + } + MenuItem {} { + label 6 + xywh {70 70 36 21} + } + MenuItem {} { + label 5 + xywh {60 60 36 21} + } + MenuItem {} { + label 4 + xywh {50 50 36 21} + } + MenuItem {} { + label 3 + xywh {40 40 36 21} + } + MenuItem {} { + label 2 + xywh {30 30 36 21} + } + MenuItem {} { + label 1 + xywh {20 20 36 21} + } + MenuItem {} { + label {0 (worst)} + xywh {10 10 36 21} + } + } + Fl_Choice choice_rec_opus_bandwidth { + label {Max. Bandwidth} + callback {choice_rec_opus_bandwidth_cb();} open + xywh {210 110 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {20kHz (best,default)} + xywh {110 110 36 21} + } + MenuItem {} { + label 12kHz + xywh {100 100 36 21} + } + MenuItem {} { + label 8kHz + xywh {90 90 36 21} + } + MenuItem {} { + label 6kHz + xywh {80 80 36 21} + } + MenuItem {} { + label {4kHz (worst)} + xywh {70 70 36 21} + } + } + } + Fl_Group tab_rec_aac { + label AAC + xywh {5 20 385 330} hide + } { + Fl_Choice choice_rec_aac_profile { + label Profile + callback {choice_rec_aac_profile_cb();} open + xywh {25 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {Auto (default)} + xywh {20 20 36 21} + } + MenuItem {} { + label {AAC-LC} + xywh {50 50 36 21} + } + MenuItem {} { + label {HE-AACv1 (AAC+)} + xywh {100 100 36 21} + } + MenuItem {} { + label {HE-AACv2 (eAAC+)} + xywh {110 110 36 21} + } + } + Fl_Choice choice_rec_aac_afterburner { + label Afterburner + callback {choice_rec_aac_afterburner_cb();} open + xywh {210 50 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {On (default)} + xywh {110 110 36 21} + } + MenuItem {} { + label Off + xywh {120 120 36 21} + } + } + Fl_Choice choice_rec_aac_bitrate_mode { + label {Bitrate Mode} + callback {choice_rec_aac_bitrate_mode_cb();} open + xywh {25 110 165 20} down_box BORDER_BOX align 5 + } { + MenuItem {} { + label {CBR (default)} + xywh {30 30 36 21} + } + MenuItem {} { + label VBR + xywh {40 40 36 21} + } + } + } + Fl_Group tab_rec_flac { + label FLAC + xywh {5 20 385 330} hide + } { + Fl_Group {} { + label {Bit depth} open + xywh {20 50 355 50} box ENGRAVED_FRAME + } { + Fl_Round_Button radio_rec_flac_bit_depth_16 { + label {16 bit} + callback {radio_rec_flac_bit_depth_16_cb();} + xywh {95 65 70 20} type Radio down_box ROUND_DOWN_BOX + } + Fl_Round_Button radio_rec_flac_bit_depth_24 { + label {24 bit} + callback {radio_rec_flac_bit_depth_24_cb();} + xywh {236 65 79 20} type Radio down_box ROUND_DOWN_BOX + } + } + } + Fl_Group tab_rec_wav { + label WAV + xywh {5 20 385 330} hide + } { + Fl_Group {} { + label {Bit depth} open + xywh {20 50 355 50} box ENGRAVED_FRAME + } { + Fl_Round_Button radio_rec_wav_bit_depth_16 { + label {16 bit} + callback {radio_rec_wav_bit_depth_16_cb();} + xywh {80 65 70 20} type Radio down_box ROUND_DOWN_BOX + } + Fl_Round_Button radio_rec_wav_bit_depth_32 { + label {32 bit} + callback {radio_rec_wav_bit_depth_32_cb();} + xywh {260 65 79 20} type Radio down_box ROUND_DOWN_BOX + } + Fl_Round_Button radio_rec_wav_bit_depth_24 { + label {24 bit} + callback {radio_rec_wav_bit_depth_24_cb();} + xywh {170 65 70 20} type Radio down_box ROUND_DOWN_BOX + } + } + } + } + Fl_Button {} { + label {&Close} + callback {this->window_rec_codec_settings->hide();} + xywh {150 358 88 22} box ENGRAVED_BOX + } + } + Fl_Window window_mixer { + label {butt audio mixer} + xywh {228 590 430 450} type Double hide + class Fl_My_Double_Window + } { + Fl_Button {} { + label Reset + callback {button_mixer_reset_cb();} + xywh {340 11 80 19} box ENGRAVED_BOX labelsize 12 + } + Fl_Group {} { + label {Audio Mixer} open + xywh {15 32 405 397} box ENGRAVED_BOX align 5 + } { + Fl_Text_Display text_mixer_primary_device_volume { + label {+0.0 dB} + xywh {22 63 55 10} box NO_BOX labelsize 11 align 9 + } + Fl_Slider slider_mixer_primary_device { + label {Primary +Device} + user_data CB_CALLED_BY_USER + callback {slider_mixer_primary_device_cb(o->value(),v);} + xywh {43 65 17 245} type {Vert Knob} box NO_BOX labelsize 11 minimum 18 maximum -18 step 0.1 slider_size 0.1 + code0 {slider_mixer_primary_device->default_value = 0.0;} + class Fl_My_Value_Slider + } + Fl_Light_Button button_mixer_mute_primary_device { + label Mute + callback {button_mixer_mute_primary_device_cb()} + tooltip Mute xywh {30 340 45 20} box THIN_UP_FRAME selection_color 1 labelsize 11 + } + Fl_Text_Display text_mixer_secondary_device_volume { + label {+0.0 dB} + xywh {105 63 55 10} box NO_BOX labelsize 11 align 9 + } + Fl_Slider slider_mixer_secondary_device { + label {Secondary +Device} + user_data CB_CALLED_BY_USER + callback {slider_mixer_secondary_device_cb(o->value(),v);} + xywh {128 65 15 245} type {Vert Knob} box NO_BOX labelsize 11 minimum 18 maximum -18 step 0.1 slider_size 0.1 + code0 {slider_mixer_secondary_device->default_value = 0.0;} + class Fl_My_Value_Slider + } + Fl_Light_Button button_mixer_mute_secondary_device { + label Mute + callback {button_mixer_mute_secondary_device_cb()} + tooltip Mute xywh {115 340 45 20} box THIN_UP_FRAME selection_color 1 labelsize 11 + } + Fl_Text_Display text_mixer_streaming_volume { + label {+0.0 dB} + xywh {190 63 50 10} box NO_BOX labelsize 11 align 9 + } + Fl_Slider slider_mixer_streaming_gain { + label {Streaming +Gain} + user_data CB_CALLED_BY_USER + callback {slider_mixer_streaming_gain_cb(o->value(),v);} + xywh {208 65 15 245} type {Vert Knob} box NO_BOX labelsize 11 minimum 18 maximum -18 step 0.1 slider_size 0.1 + code0 {slider_mixer_streaming_gain->default_value = 0.0;} + class Fl_My_Value_Slider + } + Fl_Text_Display text_mixer_recording_volume { + label {+0.0 dB} + xywh {271 63 50 10} box NO_BOX labelsize 11 align 9 + } + Fl_Slider slider_mixer_recording_gain { + label {Recording +Gain} + user_data CB_CALLED_BY_USER + callback {slider_mixer_recording_gain_cb(o->value(),v);} + xywh {288 65 15 245} type {Vert Knob} box NO_BOX labelsize 11 minimum 18 maximum -18 step 0.1 slider_size 0.1 + code0 {slider_mixer_recording_gain->default_value = 0.0;} + class Fl_My_Value_Slider + } + Fl_Text_Display text_mixer_master_volume { + label {+0.0 dB} + xywh {352 63 50 10} box NO_BOX labelsize 11 align 9 + } + Fl_Slider slider_mixer_master_gain { + label {Master +Gain} + user_data CB_CALLED_BY_USER + callback {slider_mixer_master_gain_cb(o->value(),v);} + xywh {368 65 15 245} type {Vert Knob} box NO_BOX labelsize 11 minimum 24 maximum -24 step 0.1 slider_size 0.1 + code0 {slider_mixer_master_gain->default_value = 0.0;} + class Fl_My_Value_Slider + } + Fl_Slider slider_mixer_cross_fader { + label { +Cross Fader} + user_data CB_CALLED_BY_USER + callback {slider_mixer_cross_fader_cb(o->value(),v);} + xywh {30 385 375 15} type {Horz Knob} box NO_BOX labelsize 11 minimum -100 maximum 100 step 1 slider_size 0.1 + code0 {slider_mixer_cross_fader->default_value = 0.0;} + code1 {slider_mixer_cross_fader->hide_tipwin = true;} + class Fl_My_Value_Slider + } + Fl_Box {} { + label {Primary +Device} + xywh {25 398 85 26} labelsize 11 align 20 + } + Fl_Box {} { + label {|} + xywh {205 388 25 20} labelsize 11 align 16 + } + Fl_Box {} { + label {Secondary +Device} + xywh {310 398 95 27} labelsize 11 align 24 + } + } + } + Fl_Window window_missing_aac_lib { + label Alert + xywh {630 565 390 190} type Double hide + class Fl_My_Double_Window modal + } { + Fl_Button {} { + label {&Open the manual} + callback {char uri[128]; +snprintf(uri, sizeof(uri), "https://danielnoethen.de/butt/release/%s/butt-%s_manual.html", VERSION, VERSION); +fl_open_uri(uri); +this->window_missing_aac_lib->hide();} + xywh {20 123 350 29} box ENGRAVED_BOX + code0 {\#include } + } + Fl_Box {} { + label {Could not find aac library. + +Please follow the instructions in the manual +for adding aac support.} + xywh {20 25 355 80} align 20 + } + Fl_Button {} { + label {&Close} + callback {this->window_missing_aac_lib->hide();} + xywh {20 156 350 29} box ENGRAVED_BOX + code0 {\#include } + } + } + } + Function {~flgui()} {open + } { + code {return;} {} + } +} diff --git a/src/FLTK/flgui.h b/src/FLTK/flgui.h new file mode 100644 index 0000000..732d4fa --- /dev/null +++ b/src/FLTK/flgui.h @@ -0,0 +1,1380 @@ +// generated by Fast Light User Interface Designer (fluid) version 1.0309 + +#ifndef flgui_h +#define flgui_h +#include +#include "FL/Fl_My_Double_Window.H" +#include +#include "config.h" +#include "flgui.h" +#include "fl_timer_funcs.h" +#include "Fl_ILM216.h" +#include "fl_callbacks.h" +#include "cfg.h" +#include +#include +#include +#include +#include "Fl_vu_meter.h" +#include "FL/Fl_My_Invisible_Box.H" +#include "FL/Fl_My_Value_Slider.H" +#include +#include "fl_timer_funcs.h" +#include +#include +#include +#include +#include +#include +#include "Fl_LED.h" +#include +#include +#include +#include +#include +#include +#include +#include + +class flgui { +public: + bool info_visible; + Fl_Text_Buffer *info_buffer; + flgui(); + Fl_My_Double_Window *window_main; +private: + inline void cb_window_main_i(Fl_My_Double_Window*, void*); + static void cb_window_main(Fl_My_Double_Window*, void*); +public: + Fl_ILM216 *lcd; +private: + inline void cb_lcd_i(Fl_ILM216*, void*); + static void cb_lcd(Fl_ILM216*, void*); +public: + Fl_Box *label_volume; + Fl_Button *button_mixer; +private: + inline void cb_button_mixer_i(Fl_Button*, void*); + static void cb_button_mixer(Fl_Button*, void*); +public: + Fl_Button *button_record; +private: + inline void cb_button_record_i(Fl_Button*, void*); + static void cb_button_record(Fl_Button*, void*); +public: + Fl_Button *button_disconnect; +private: + inline void cb_button_disconnect_i(Fl_Button*, void*); + static void cb_button_disconnect(Fl_Button*, void*); +public: + Fl_Button *button_connect; +private: + inline void cb_button_connect_i(Fl_Button*, void*); + static void cb_button_connect(Fl_Button*, void*); +public: + Fl_Tabs *vu_tabs; +private: + inline void cb_vu_tabs_i(Fl_Tabs*, void*); + static void cb_vu_tabs(Fl_Tabs*, void*); +public: + VUMeter *vumeter; + Fl_My_Invisible_Box *invisible_tab_box; + Fl_Button *button_cfg; +private: + inline void cb_button_cfg_i(Fl_Button*, void*); + static void cb_button_cfg(Fl_Button*, void*); +public: + Fl_Button *button_info; +private: + inline void cb_button_info_i(Fl_Button*, void*); + static void cb_button_info(Fl_Button*, void*); +public: + Fl_Box *label_n24dB; + Fl_My_Value_Slider *slider_gain; +private: + inline void cb_slider_gain_i(Fl_My_Value_Slider*, void*); + static void cb_slider_gain(Fl_My_Value_Slider*, void*); +public: + Fl_Box *label_p24dB; + Fl_Button *sponsor_logo; + Fl_Box *label_current_listeners; + Fl_Text_Display *info_output; + Fl_My_Double_Window *window_cfg; +private: + inline void cb_window_cfg_i(Fl_My_Double_Window*, void*); + static void cb_window_cfg(Fl_My_Double_Window*, void*); +public: + Fl_Tabs *Settings; + Fl_Choice *choice_cfg_act_srv; +private: + inline void cb_choice_cfg_act_srv_i(Fl_Choice*, void*); + static void cb_choice_cfg_act_srv(Fl_Choice*, void*); + inline void cb_ADD_i(Fl_Button*, void*); + static void cb_ADD(Fl_Button*, void*); +public: + Fl_Button *button_cfg_edit_srv; +private: + inline void cb_button_cfg_edit_srv_i(Fl_Button*, void*); + static void cb_button_cfg_edit_srv(Fl_Button*, void*); +public: + Fl_Button *button_cfg_del_srv; +private: + inline void cb_button_cfg_del_srv_i(Fl_Button*, void*); + static void cb_button_cfg_del_srv(Fl_Button*, void*); +public: + Fl_Choice *choice_cfg_act_icy; +private: + inline void cb_choice_cfg_act_icy_i(Fl_Choice*, void*); + static void cb_choice_cfg_act_icy(Fl_Choice*, void*); + inline void cb_ADD1_i(Fl_Button*, void*); + static void cb_ADD1(Fl_Button*, void*); +public: + Fl_Button *button_cfg_edit_icy; +private: + inline void cb_button_cfg_edit_icy_i(Fl_Button*, void*); + static void cb_button_cfg_edit_icy(Fl_Button*, void*); +public: + Fl_Button *button_cfg_del_icy; +private: + inline void cb_button_cfg_del_icy_i(Fl_Button*, void*); + static void cb_button_cfg_del_icy(Fl_Button*, void*); +public: + Fl_Input *input_log_filename; +private: + inline void cb_input_log_filename_i(Fl_Input*, void*); + static void cb_input_log_filename(Fl_Input*, void*); + inline void cb__i(Fl_Button*, void*); + static void cb_(Fl_Button*, void*); +public: + Fl_Button *button_cfg_import; +private: + inline void cb_button_cfg_import_i(Fl_Button*, void*); + static void cb_button_cfg_import(Fl_Button*, void*); + inline void cb_Save_i(Fl_Button*, void*); + static void cb_Save(Fl_Button*, void*); + inline void cb_Export_i(Fl_Button*, void*); + static void cb_Export(Fl_Button*, void*); +public: + Fl_Group *group_agent; + Fl_Check_Button *check_start_agent; +private: + inline void cb_check_start_agent_i(Fl_Check_Button*, void*); + static void cb_check_start_agent(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_minimize_to_tray; +private: + inline void cb_check_minimize_to_tray_i(Fl_Check_Button*, void*); + static void cb_check_minimize_to_tray(Fl_Check_Button*, void*); + inline void cb_Start_i(Fl_Button*, void*); + static void cb_Start(Fl_Button*, void*); + inline void cb_Stop_i(Fl_Button*, void*); + static void cb_Stop(Fl_Button*, void*); +public: + Fl_Check_Button *check_update_at_startup; +private: + inline void cb_check_update_at_startup_i(Fl_Check_Button*, void*); + static void cb_check_update_at_startup(Fl_Check_Button*, void*); + inline void cb_Check_i(Fl_Button*, void*); + static void cb_Check(Fl_Button*, void*); + inline void cb_Manual_i(Fl_Button*, void*); + static void cb_Manual(Fl_Button*, void*); + inline void cb_YouTube_i(Fl_Button*, void*); + static void cb_YouTube(Fl_Button*, void*); +public: + Fl_Choice *choice_cfg_channel; + static unsigned char menu_choice_cfg_channel_i18n_done; + static Fl_Menu_Item menu_choice_cfg_channel[]; +private: + inline void cb_Stereo_i(Fl_Menu_*, void*); + static void cb_Stereo(Fl_Menu_*, void*); + inline void cb_Mono_i(Fl_Menu_*, void*); + static void cb_Mono(Fl_Menu_*, void*); +public: + Fl_Choice *choice_cfg_samplerate; +private: + inline void cb_choice_cfg_samplerate_i(Fl_Choice*, void*); + static void cb_choice_cfg_samplerate(Fl_Choice*, void*); +public: + Fl_Round_Button *radio_cfg_ID; +private: + inline void cb_radio_cfg_ID_i(Fl_Round_Button*, void*); + static void cb_radio_cfg_ID(Fl_Round_Button*, void*); +public: + Fl_Round_Button *radio_cfg_name; +private: + inline void cb_radio_cfg_name_i(Fl_Round_Button*, void*); + static void cb_radio_cfg_name(Fl_Round_Button*, void*); +public: + Fl_Button *button_cfg_rescan_devices; +private: + inline void cb_button_cfg_rescan_devices_i(Fl_Button*, void*); + static void cb_button_cfg_rescan_devices(Fl_Button*, void*); +public: + Fl_Choice *choice_cfg_dev; +private: + inline void cb_choice_cfg_dev_i(Fl_Choice*, void*); + static void cb_choice_cfg_dev(Fl_Choice*, void*); +public: + Fl_Choice *choice_cfg_left_channel; +private: + inline void cb_choice_cfg_left_channel_i(Fl_Choice*, void*); + static void cb_choice_cfg_left_channel(Fl_Choice*, void*); +public: + Fl_Choice *choice_cfg_right_channel; +private: + inline void cb_choice_cfg_right_channel_i(Fl_Choice*, void*); + static void cb_choice_cfg_right_channel(Fl_Choice*, void*); +public: + Fl_Choice *choice_cfg_dev2; +private: + inline void cb_choice_cfg_dev2_i(Fl_Choice*, void*); + static void cb_choice_cfg_dev2(Fl_Choice*, void*); +public: + Fl_Choice *choice_cfg_left_channel2; +private: + inline void cb_choice_cfg_left_channel2_i(Fl_Choice*, void*); + static void cb_choice_cfg_left_channel2(Fl_Choice*, void*); +public: + Fl_Choice *choice_cfg_right_channel2; +private: + inline void cb_choice_cfg_right_channel2_i(Fl_Choice*, void*); + static void cb_choice_cfg_right_channel2(Fl_Choice*, void*); +public: + Fl_Choice *choice_cfg_codec; + static unsigned char menu_choice_cfg_codec_i18n_done; + static Fl_Menu_Item menu_choice_cfg_codec[]; +private: + inline void cb_MP3_i(Fl_Menu_*, void*); + static void cb_MP3(Fl_Menu_*, void*); + inline void cb_OGG_i(Fl_Menu_*, void*); + static void cb_OGG(Fl_Menu_*, void*); + inline void cb_OPUS_i(Fl_Menu_*, void*); + static void cb_OPUS(Fl_Menu_*, void*); +public: + static Fl_Menu_Item *menu_item_cfg_aac; +private: + inline void cb_menu_item_cfg_aac_i(Fl_Menu_*, void*); + static void cb_menu_item_cfg_aac(Fl_Menu_*, void*); + inline void cb_FLAC_i(Fl_Menu_*, void*); + static void cb_FLAC(Fl_Menu_*, void*); +public: + Fl_Choice *choice_cfg_bitrate; +private: + inline void cb_choice_cfg_bitrate_i(Fl_Choice*, void*); + static void cb_choice_cfg_bitrate(Fl_Choice*, void*); + inline void cb_1_i(Fl_Button*, void*); + static void cb_1(Fl_Button*, void*); +public: + Fl_Choice *choice_rec_codec; + static unsigned char menu_choice_rec_codec_i18n_done; + static Fl_Menu_Item menu_choice_rec_codec[]; +private: + inline void cb_MP31_i(Fl_Menu_*, void*); + static void cb_MP31(Fl_Menu_*, void*); + inline void cb_OGG1_i(Fl_Menu_*, void*); + static void cb_OGG1(Fl_Menu_*, void*); + inline void cb_OPUS1_i(Fl_Menu_*, void*); + static void cb_OPUS1(Fl_Menu_*, void*); +public: + static Fl_Menu_Item *menu_item_rec_aac; +private: + inline void cb_menu_item_rec_aac_i(Fl_Menu_*, void*); + static void cb_menu_item_rec_aac(Fl_Menu_*, void*); + inline void cb_FLAC1_i(Fl_Menu_*, void*); + static void cb_FLAC1(Fl_Menu_*, void*); + inline void cb_WAV_i(Fl_Menu_*, void*); + static void cb_WAV(Fl_Menu_*, void*); +public: + Fl_Choice *choice_rec_bitrate; +private: + inline void cb_choice_rec_bitrate_i(Fl_Choice*, void*); + static void cb_choice_rec_bitrate(Fl_Choice*, void*); + inline void cb_2_i(Fl_Button*, void*); + static void cb_2(Fl_Button*, void*); +public: + Fl_Button *button_advanced; +private: + inline void cb_button_advanced_i(Fl_Button*, void*); + static void cb_button_advanced(Fl_Button*, void*); +public: + Fl_Value_Input *input_cfg_buffer; +private: + inline void cb_input_cfg_buffer_i(Fl_Value_Input*, void*); + static void cb_input_cfg_buffer(Fl_Value_Input*, void*); +public: + Fl_Choice *choice_cfg_resample_mode; +private: + inline void cb_choice_cfg_resample_mode_i(Fl_Choice*, void*); + static void cb_choice_cfg_resample_mode(Fl_Choice*, void*); + static unsigned char menu_choice_cfg_resample_mode_i18n_done; + static Fl_Menu_Item menu_choice_cfg_resample_mode[]; +public: + Fl_Value_Input *input_cfg_present_level; +private: + inline void cb_input_cfg_present_level_i(Fl_Value_Input*, void*); + static void cb_input_cfg_present_level(Fl_Value_Input*, void*); +public: + Fl_Value_Input *input_cfg_absent_level; +private: + inline void cb_input_cfg_absent_level_i(Fl_Value_Input*, void*); + static void cb_input_cfg_absent_level(Fl_Value_Input*, void*); +public: + Fl_Input *input_cfg_song_file; +private: + inline void cb_input_cfg_song_file_i(Fl_Input*, void*); + static void cb_input_cfg_song_file(Fl_Input*, void*); +public: + Fl_Button *button_songfile_browse; +private: + inline void cb_button_songfile_browse_i(Fl_Button*, void*); + static void cb_button_songfile_browse(Fl_Button*, void*); +public: + Fl_Check_Button *check_song_update_active; +private: + inline void cb_check_song_update_active_i(Fl_Check_Button*, void*); + static void cb_check_song_update_active(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_read_last_line; +private: + inline void cb_check_read_last_line_i(Fl_Check_Button*, void*); + static void cb_check_read_last_line(Fl_Check_Button*, void*); +public: + Fl_Choice *choice_cfg_app; +private: + inline void cb_choice_cfg_app_i(Fl_Choice*, void*); + static void cb_choice_cfg_app(Fl_Choice*, void*); +public: + Fl_Round_Button *radio_cfg_title_artist; +private: + inline void cb_radio_cfg_title_artist_i(Fl_Round_Button*, void*); + static void cb_radio_cfg_title_artist(Fl_Round_Button*, void*); +public: + Fl_Round_Button *radio_cfg_artist_title; +private: + inline void cb_radio_cfg_artist_title_i(Fl_Round_Button*, void*); + static void cb_radio_cfg_artist_title(Fl_Round_Button*, void*); +public: + Fl_Check_Button *check_cfg_use_app; +private: + inline void cb_check_cfg_use_app_i(Fl_Check_Button*, void*); + static void cb_check_cfg_use_app(Fl_Check_Button*, void*); +public: + Fl_Input *input_cfg_song; +private: + inline void cb_input_cfg_song_i(Fl_Input*, void*); + static void cb_input_cfg_song(Fl_Input*, void*); +public: + Fl_Button *button_cfg_song_go; +private: + inline void cb_button_cfg_song_go_i(Fl_Button*, void*); + static void cb_button_cfg_song_go(Fl_Button*, void*); +public: + Fl_Choice *choice_cfg_song_delay; +private: + inline void cb_choice_cfg_song_delay_i(Fl_Choice*, void*); + static void cb_choice_cfg_song_delay(Fl_Choice*, void*); +public: + Fl_Input *input_cfg_song_prefix; +private: + inline void cb_input_cfg_song_prefix_i(Fl_Input*, void*); + static void cb_input_cfg_song_prefix(Fl_Input*, void*); +public: + Fl_Input *input_cfg_song_suffix; +private: + inline void cb_input_cfg_song_suffix_i(Fl_Input*, void*); + static void cb_input_cfg_song_suffix(Fl_Input*, void*); +public: + Fl_Check_Button *check_stream_signal; +private: + inline void cb_check_stream_signal_i(Fl_Check_Button*, void*); + static void cb_check_stream_signal(Fl_Check_Button*, void*); +public: + Fl_Value_Input *input_cfg_signal; +private: + inline void cb_input_cfg_signal_i(Fl_Value_Input*, void*); + static void cb_input_cfg_signal(Fl_Value_Input*, void*); +public: + Fl_Check_Button *check_stream_silence; +private: + inline void cb_check_stream_silence_i(Fl_Check_Button*, void*); + static void cb_check_stream_silence(Fl_Check_Button*, void*); +public: + Fl_Value_Input *input_cfg_silence; +private: + inline void cb_input_cfg_silence_i(Fl_Value_Input*, void*); + static void cb_input_cfg_silence(Fl_Value_Input*, void*); +public: + Fl_Check_Button *check_cfg_connect; +private: + inline void cb_check_cfg_connect_i(Fl_Check_Button*, void*); + static void cb_check_cfg_connect(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_cfg_force_reconnecting; +private: + inline void cb_check_cfg_force_reconnecting_i(Fl_Check_Button*, void*); + static void cb_check_cfg_force_reconnecting(Fl_Check_Button*, void*); +public: + Fl_Value_Input *input_cfg_reconnect_delay; +private: + inline void cb_input_cfg_reconnect_delay_i(Fl_Value_Input*, void*); + static void cb_input_cfg_reconnect_delay(Fl_Value_Input*, void*); +public: + Fl_Input *input_cfg_song_url; +private: + inline void cb_input_cfg_song_url_i(Fl_Input*, void*); + static void cb_input_cfg_song_url(Fl_Input*, void*); +public: + Fl_Value_Input *input_cfg_url_update_song_interval; +private: + inline void cb_input_cfg_url_update_song_interval_i(Fl_Value_Input*, void*); + static void cb_input_cfg_url_update_song_interval(Fl_Value_Input*, void*); +public: + Fl_Check_Button *check_cfg_update_from_url; +private: + inline void cb_check_cfg_update_from_url_i(Fl_Check_Button*, void*); + static void cb_check_cfg_update_from_url(Fl_Check_Button*, void*); +public: + Fl_Input *input_rec_filename; +private: + inline void cb_input_rec_filename_i(Fl_Input*, void*); + static void cb_input_rec_filename(Fl_Input*, void*); +public: + Fl_Input *input_rec_folder; +private: + inline void cb_input_rec_folder_i(Fl_Input*, void*); + static void cb_input_rec_folder(Fl_Input*, void*); +public: + Fl_Button *button_rec_browse; +private: + inline void cb_button_rec_browse_i(Fl_Button*, void*); + static void cb_button_rec_browse(Fl_Button*, void*); +public: + Fl_Value_Input *input_rec_split_time; +private: + inline void cb_input_rec_split_time_i(Fl_Value_Input*, void*); + static void cb_input_rec_split_time(Fl_Value_Input*, void*); +public: + Fl_Box *text_rec_split_time; + Fl_Check_Button *check_sync_to_full_hour; +private: + inline void cb_check_sync_to_full_hour_i(Fl_Check_Button*, void*); + static void cb_check_sync_to_full_hour(Fl_Check_Button*, void*); + inline void cb_Split_i(Fl_Button*, void*); + static void cb_Split(Fl_Button*, void*); +public: + Fl_Check_Button *check_cfg_auto_start_rec; +private: + inline void cb_check_cfg_auto_start_rec_i(Fl_Check_Button*, void*); + static void cb_check_cfg_auto_start_rec(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_cfg_auto_stop_rec; +private: + inline void cb_check_cfg_auto_stop_rec_i(Fl_Check_Button*, void*); + static void cb_check_cfg_auto_stop_rec(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_cfg_rec_after_launch; +private: + inline void cb_check_cfg_rec_after_launch_i(Fl_Check_Button*, void*); + static void cb_check_cfg_rec_after_launch(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_rec_signal; +private: + inline void cb_check_rec_signal_i(Fl_Check_Button*, void*); + static void cb_check_rec_signal(Fl_Check_Button*, void*); +public: + Fl_Value_Input *input_rec_signal; +private: + inline void cb_input_rec_signal_i(Fl_Value_Input*, void*); + static void cb_input_rec_signal(Fl_Value_Input*, void*); +public: + Fl_Check_Button *check_rec_silence; +private: + inline void cb_check_rec_silence_i(Fl_Check_Button*, void*); + static void cb_check_rec_silence(Fl_Check_Button*, void*); +public: + Fl_Value_Input *input_rec_silence; +private: + inline void cb_input_rec_silence_i(Fl_Value_Input*, void*); + static void cb_input_rec_silence(Fl_Value_Input*, void*); +public: + Fl_Check_Button *check_cfg_overwrite_existing_files; +private: + inline void cb_check_cfg_overwrite_existing_files_i(Fl_Check_Button*, void*); + static void cb_check_cfg_overwrite_existing_files(Fl_Check_Button*, void*); + inline void cb_Reset_i(Fl_Button*, void*); + static void cb_Reset(Fl_Button*, void*); +public: + Fl_Check_Button *check_stream_eq; +private: + inline void cb_check_stream_eq_i(Fl_Check_Button*, void*); + static void cb_check_stream_eq(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_rec_eq; +private: + inline void cb_check_rec_eq_i(Fl_Check_Button*, void*); + static void cb_check_rec_eq(Fl_Check_Button*, void*); +public: + Fl_Choice *choice_eq_preset; +private: + inline void cb_choice_eq_preset_i(Fl_Choice*, void*); + static void cb_choice_eq_preset(Fl_Choice*, void*); + static unsigned char menu_choice_eq_preset_i18n_done; + static Fl_Menu_Item menu_choice_eq_preset[]; +public: + Fl_Text_Display *equalizerGain1; + Fl_My_Value_Slider *equalizerSlider1; +private: + inline void cb_equalizerSlider1_i(Fl_My_Value_Slider*, void*); + static void cb_equalizerSlider1(Fl_My_Value_Slider*, void*); +public: + Fl_Text_Display *equalizerGain2; + Fl_My_Value_Slider *equalizerSlider2; +private: + inline void cb_equalizerSlider2_i(Fl_My_Value_Slider*, void*); + static void cb_equalizerSlider2(Fl_My_Value_Slider*, void*); +public: + Fl_Text_Display *equalizerGain3; + Fl_My_Value_Slider *equalizerSlider3; +private: + inline void cb_equalizerSlider3_i(Fl_My_Value_Slider*, void*); + static void cb_equalizerSlider3(Fl_My_Value_Slider*, void*); +public: + Fl_Text_Display *equalizerGain4; + Fl_My_Value_Slider *equalizerSlider4; +private: + inline void cb_equalizerSlider4_i(Fl_My_Value_Slider*, void*); + static void cb_equalizerSlider4(Fl_My_Value_Slider*, void*); +public: + Fl_Text_Display *equalizerGain5; + Fl_My_Value_Slider *equalizerSlider5; +private: + inline void cb_equalizerSlider5_i(Fl_My_Value_Slider*, void*); + static void cb_equalizerSlider5(Fl_My_Value_Slider*, void*); +public: + Fl_Text_Display *equalizerGain6; + Fl_My_Value_Slider *equalizerSlider6; +private: + inline void cb_equalizerSlider6_i(Fl_My_Value_Slider*, void*); + static void cb_equalizerSlider6(Fl_My_Value_Slider*, void*); +public: + Fl_Text_Display *equalizerGain7; + Fl_My_Value_Slider *equalizerSlider7; +private: + inline void cb_equalizerSlider7_i(Fl_My_Value_Slider*, void*); + static void cb_equalizerSlider7(Fl_My_Value_Slider*, void*); +public: + Fl_Text_Display *equalizerGain8; + Fl_My_Value_Slider *equalizerSlider8; +private: + inline void cb_equalizerSlider8_i(Fl_My_Value_Slider*, void*); + static void cb_equalizerSlider8(Fl_My_Value_Slider*, void*); +public: + Fl_Text_Display *equalizerGain9; + Fl_My_Value_Slider *equalizerSlider9; +private: + inline void cb_equalizerSlider9_i(Fl_My_Value_Slider*, void*); + static void cb_equalizerSlider9(Fl_My_Value_Slider*, void*); +public: + Fl_Text_Display *equalizerGain10; + Fl_My_Value_Slider *equalizerSlider10; +private: + inline void cb_equalizerSlider10_i(Fl_My_Value_Slider*, void*); + static void cb_equalizerSlider10(Fl_My_Value_Slider*, void*); + inline void cb_Reset1_i(Fl_Button*, void*); + static void cb_Reset1(Fl_Button*, void*); +public: + Fl_Check_Button *check_stream_drc; +private: + inline void cb_check_stream_drc_i(Fl_Check_Button*, void*); + static void cb_check_stream_drc(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_rec_drc; +private: + inline void cb_check_rec_drc_i(Fl_Check_Button*, void*); + static void cb_check_rec_drc(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_aggressive_mode; +private: + inline void cb_check_aggressive_mode_i(Fl_Check_Button*, void*); + static void cb_check_aggressive_mode(Fl_Check_Button*, void*); +public: + Fl_Text_Display *threshold; + Fl_My_Value_Slider *thresholdSlider; +private: + inline void cb_thresholdSlider_i(Fl_My_Value_Slider*, void*); + static void cb_thresholdSlider(Fl_My_Value_Slider*, void*); +public: + Fl_Text_Display *ratio; + Fl_My_Value_Slider *ratioSlider; +private: + inline void cb_ratioSlider_i(Fl_My_Value_Slider*, void*); + static void cb_ratioSlider(Fl_My_Value_Slider*, void*); +public: + Fl_Text_Display *attack; + Fl_My_Value_Slider *attackSlider; +private: + inline void cb_attackSlider_i(Fl_My_Value_Slider*, void*); + static void cb_attackSlider(Fl_My_Value_Slider*, void*); +public: + Fl_Text_Display *release; + Fl_My_Value_Slider *releaseSlider; +private: + inline void cb_releaseSlider_i(Fl_My_Value_Slider*, void*); + static void cb_releaseSlider(Fl_My_Value_Slider*, void*); +public: + Fl_Text_Display *makeup; + Fl_My_Value_Slider *makeupSlider; +private: + inline void cb_makeupSlider_i(Fl_My_Value_Slider*, void*); + static void cb_makeupSlider(Fl_My_Value_Slider*, void*); +public: + LED *LED_comp_threshold; + Fl_Choice *choice_midi_dev; +private: + inline void cb_choice_midi_dev_i(Fl_Choice*, void*); + static void cb_choice_midi_dev(Fl_Choice*, void*); +public: + Fl_Button *button_midi_rescan_devices; +private: + inline void cb_button_midi_rescan_devices_i(Fl_Button*, void*); + static void cb_button_midi_rescan_devices(Fl_Button*, void*); +public: + LED *LED_midi_command; + Fl_Browser *browser_midi_command; +private: + inline void cb_browser_midi_command_i(Fl_Browser*, void*); + static void cb_browser_midi_command(Fl_Browser*, void*); +public: + Fl_Check_Button *check_midi_command_enable; +private: + inline void cb_check_midi_command_enable_i(Fl_Check_Button*, void*); + static void cb_check_midi_command_enable(Fl_Check_Button*, void*); +public: + Fl_Group *group_midi_command_settings; + Fl_Choice *choice_midi_channel; +private: + inline void cb_choice_midi_channel_i(Fl_Choice*, void*); + static void cb_choice_midi_channel(Fl_Choice*, void*); + static unsigned char menu_choice_midi_channel_i18n_done; + static Fl_Menu_Item menu_choice_midi_channel[]; +public: + Fl_Value_Input *input_midi_msg_num; +private: + inline void cb_input_midi_msg_num_i(Fl_Value_Input*, void*); + static void cb_input_midi_msg_num(Fl_Value_Input*, void*); +public: + Fl_Button *button_midi_learn; +private: + inline void cb_button_midi_learn_i(Fl_Button*, void*); + static void cb_button_midi_learn(Fl_Button*, void*); +public: + Fl_Choice *choice_midi_cc_mode; +private: + inline void cb_choice_midi_cc_mode_i(Fl_Choice*, void*); + static void cb_choice_midi_cc_mode(Fl_Choice*, void*); + static unsigned char menu_choice_midi_cc_mode_i18n_done; + static Fl_Menu_Item menu_choice_midi_cc_mode[]; +public: + Fl_Check_Button *check_midi_soft_takeover; +private: + inline void cb_check_midi_soft_takeover_i(Fl_Check_Button*, void*); + static void cb_check_midi_soft_takeover(Fl_Check_Button*, void*); +public: + Fl_Input *input_tls_cert_file; +private: + inline void cb_input_tls_cert_file_i(Fl_Input*, void*); + static void cb_input_tls_cert_file(Fl_Input*, void*); +public: + Fl_Button *button_tls_browse_file; +private: + inline void cb_button_tls_browse_file_i(Fl_Button*, void*); + static void cb_button_tls_browse_file(Fl_Button*, void*); +public: + Fl_Input *input_tls_cert_dir; +private: + inline void cb_input_tls_cert_dir_i(Fl_Input*, void*); + static void cb_input_tls_cert_dir(Fl_Input*, void*); +public: + Fl_Button *button_tls_browse_dir; +private: + inline void cb_button_tls_browse_dir_i(Fl_Button*, void*); + static void cb_button_tls_browse_dir(Fl_Button*, void*); +public: + Fl_Choice *choice_gui_language; +private: + inline void cb_choice_gui_language_i(Fl_Choice*, void*); + static void cb_choice_gui_language(Fl_Choice*, void*); + static unsigned char menu_choice_gui_language_i18n_done; + static Fl_Menu_Item menu_choice_gui_language[]; +public: + Fl_Button *button_gui_text_color; +private: + inline void cb_button_gui_text_color_i(Fl_Button*, void*); + static void cb_button_gui_text_color(Fl_Button*, void*); +public: + Fl_Button *button_gui_bg_color; +private: + inline void cb_button_gui_bg_color_i(Fl_Button*, void*); + static void cb_button_gui_bg_color(Fl_Button*, void*); +public: + Fl_Round_Button *radio_gui_vu_gradient; +private: + inline void cb_radio_gui_vu_gradient_i(Fl_Round_Button*, void*); + static void cb_radio_gui_vu_gradient(Fl_Round_Button*, void*); +public: + Fl_Round_Button *radio_gui_vu_solid; +private: + inline void cb_radio_gui_vu_solid_i(Fl_Round_Button*, void*); + static void cb_radio_gui_vu_solid(Fl_Round_Button*, void*); +public: + Fl_Check_Button *check_gui_always_show_vu_tabs; +private: + inline void cb_check_gui_always_show_vu_tabs_i(Fl_Check_Button*, void*); + static void cb_check_gui_always_show_vu_tabs(Fl_Check_Button*, void*); +public: + Fl_Button *button_gui_vu_low_color; +private: + inline void cb_button_gui_vu_low_color_i(Fl_Button*, void*); + static void cb_button_gui_vu_low_color(Fl_Button*, void*); +public: + Fl_Button *button_gui_vu_mid_color; +private: + inline void cb_button_gui_vu_mid_color_i(Fl_Button*, void*); + static void cb_button_gui_vu_mid_color(Fl_Button*, void*); +public: + Fl_Button *button_gui_vu_high_color; +private: + inline void cb_button_gui_vu_high_color_i(Fl_Button*, void*); + static void cb_button_gui_vu_high_color(Fl_Button*, void*); +public: + Fl_Value_Input *input_gui_vu_mid_range_start; +private: + inline void cb_input_gui_vu_mid_range_start_i(Fl_Value_Input*, void*); + static void cb_input_gui_vu_mid_range_start(Fl_Value_Input*, void*); +public: + Fl_Value_Input *input_gui_vu_high_range_start; +private: + inline void cb_input_gui_vu_high_range_start_i(Fl_Value_Input*, void*); + static void cb_input_gui_vu_high_range_start(Fl_Value_Input*, void*); +public: + Fl_Check_Button *check_gui_attach; +private: + inline void cb_check_gui_attach_i(Fl_Check_Button*, void*); + static void cb_check_gui_attach(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_gui_ontop; +private: + inline void cb_check_gui_ontop_i(Fl_Check_Button*, void*); + static void cb_check_gui_ontop(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_gui_remember_pos; +private: + inline void cb_check_gui_remember_pos_i(Fl_Check_Button*, void*); + static void cb_check_gui_remember_pos(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_gui_hide_log_window; +private: + inline void cb_check_gui_hide_log_window_i(Fl_Check_Button*, void*); + static void cb_check_gui_hide_log_window(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_gui_lcd_auto; +private: + inline void cb_check_gui_lcd_auto_i(Fl_Check_Button*, void*); + static void cb_check_gui_lcd_auto(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_gui_start_minimized; +private: + inline void cb_check_gui_start_minimized_i(Fl_Check_Button*, void*); + static void cb_check_gui_start_minimized(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_gui_disable_gain_slider; +private: + inline void cb_check_gui_disable_gain_slider_i(Fl_Check_Button*, void*); + static void cb_check_gui_disable_gain_slider(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_gui_show_listeners; +private: + inline void cb_check_gui_show_listeners_i(Fl_Check_Button*, void*); + static void cb_check_gui_show_listeners(Fl_Check_Button*, void*); +public: + Fl_Value_Input *input_gui_listeners_update_rate; +private: + inline void cb_input_gui_listeners_update_rate_i(Fl_Value_Input*, void*); + static void cb_input_gui_listeners_update_rate(Fl_Value_Input*, void*); +public: + Fl_Input *input_gui_window_title; +private: + inline void cb_input_gui_window_title_i(Fl_Input*, void*); + static void cb_input_gui_window_title(Fl_Input*, void*); + inline void cb_Donate_i(Fl_Button*, void*); + static void cb_Donate(Fl_Button*, void*); + inline void cb_Become_i(Fl_Button*, void*); + static void cb_Become(Fl_Button*, void*); + inline void cb_Apple_i(Fl_Button*, void*); + static void cb_Apple(Fl_Button*, void*); + inline void cb_Bitcoin_i(Fl_Button*, void*); + static void cb_Bitcoin(Fl_Button*, void*); +public: + Fl_Double_Window *window_add_srv; + Fl_Input *input_add_srv_name; + Fl_Input *input_add_srv_addr; + Fl_Int_Input *input_add_srv_port; + Fl_Input *input_add_srv_pwd; + Fl_Input *input_add_srv_mount; + Fl_Input *input_add_srv_usr; + Fl_Button *button_cfg_show_pw; +private: + inline void cb_button_cfg_show_pw_i(Fl_Button*, void*); + static void cb_button_cfg_show_pw(Fl_Button*, void*); +public: + Fl_Round_Button *radio_add_srv_shoutcast; +private: + inline void cb_radio_add_srv_shoutcast_i(Fl_Round_Button*, void*); + static void cb_radio_add_srv_shoutcast(Fl_Round_Button*, void*); +public: + Fl_Round_Button *radio_add_srv_icecast; +private: + inline void cb_radio_add_srv_icecast_i(Fl_Round_Button*, void*); + static void cb_radio_add_srv_icecast(Fl_Round_Button*, void*); +public: + Fl_Round_Button *radio_add_srv_webrtc; +private: + inline void cb_radio_add_srv_webrtc_i(Fl_Round_Button*, void*); + static void cb_radio_add_srv_webrtc(Fl_Round_Button*, void*); +public: + Fl_Round_Button *radio_add_srv_radioco; +private: + inline void cb_radio_add_srv_radioco_i(Fl_Round_Button*, void*); + static void cb_radio_add_srv_radioco(Fl_Round_Button*, void*); + inline void cb_Cancel_i(Fl_Button*, void*); + static void cb_Cancel(Fl_Button*, void*); +public: + Fl_Button *button_add_srv_add; +private: + inline void cb_button_add_srv_add_i(Fl_Button*, void*); + static void cb_button_add_srv_add(Fl_Button*, void*); +public: + Fl_Button *button_add_srv_save; +private: + inline void cb_button_add_srv_save_i(Fl_Button*, void*); + static void cb_button_add_srv_save(Fl_Button*, void*); +public: + Fl_Group *frame_add_srv_tls; + Fl_Check_Button *check_add_srv_tls; + Fl_Button *button_add_srv_revoke_cert; +private: + inline void cb_button_add_srv_revoke_cert_i(Fl_Button*, void*); + static void cb_button_add_srv_revoke_cert(Fl_Button*, void*); +public: + Fl_Check_Browser *browser_add_srv_station_list; + Fl_Button *button_add_srv_get_stations; +private: + inline void cb_button_add_srv_get_stations_i(Fl_Button*, void*); + static void cb_button_add_srv_get_stations(Fl_Button*, void*); +public: + Fl_Button *button_add_srv_select_all; +private: + inline void cb_button_add_srv_select_all_i(Fl_Button*, void*); + static void cb_button_add_srv_select_all(Fl_Button*, void*); +public: + Fl_Button *button_add_srv_deselect_all; +private: + inline void cb_button_add_srv_deselect_all_i(Fl_Button*, void*); + static void cb_button_add_srv_deselect_all(Fl_Button*, void*); +public: + Fl_Check_Button *check_add_srv_protocol; + Fl_Input *input_webrtc_icesrv_url; + Fl_Input *input_webrtc_whip_url; + Fl_Input *input_webrtc_auth_token; + Fl_Input *input_add_srv_listener_url; + Fl_Input *input_add_srv_listener_mount; + Fl_Double_Window *window_add_icy; + Fl_Input *input_add_icy_name; + Fl_Input *input_add_icy_desc; + Fl_Input *input_add_icy_genre; + Fl_Input *input_add_icy_url; + Fl_Input *input_add_icy_icq; + Fl_Input *input_add_icy_irc; + Fl_Input *input_add_icy_aim; + Fl_Check_Button *check_add_icy_pub; + Fl_Check_Button *check_expand_variables; +private: + inline void cb_Cancel1_i(Fl_Button*, void*); + static void cb_Cancel1(Fl_Button*, void*); +public: + Fl_Button *button_add_icy_add; +private: + inline void cb_button_add_icy_add_i(Fl_Button*, void*); + static void cb_button_add_icy_add(Fl_Button*, void*); +public: + Fl_Button *button_add_icy_save; +private: + inline void cb_button_add_icy_save_i(Fl_Button*, void*); + static void cb_button_add_icy_save(Fl_Button*, void*); +public: + Fl_My_Double_Window *window_donate_crypto; + Fl_Output *output_bitcoin_addr; +private: + inline void cb_Copy_i(Fl_Button*, void*); + static void cb_Copy(Fl_Button*, void*); +public: + Fl_Output *output_litecoin_addr; +private: + inline void cb_Copy1_i(Fl_Button*, void*); + static void cb_Copy1(Fl_Button*, void*); +public: + Fl_Output *output_monero_addr; +private: + inline void cb_Copy2_i(Fl_Button*, void*); + static void cb_Copy2(Fl_Button*, void*); + inline void cb_Close_i(Fl_Button*, void*); + static void cb_Close(Fl_Button*, void*); +public: + Fl_My_Double_Window *window_stream_codec_settings; + Fl_Tabs *tabs_stream_codec_settings; + Fl_Group *tab_stream_mp3; + Fl_Choice *choice_stream_mp3_enc_quality; +private: + inline void cb_choice_stream_mp3_enc_quality_i(Fl_Choice*, void*); + static void cb_choice_stream_mp3_enc_quality(Fl_Choice*, void*); + static unsigned char menu_choice_stream_mp3_enc_quality_i18n_done; + static Fl_Menu_Item menu_choice_stream_mp3_enc_quality[]; +public: + Fl_Choice *choice_stream_mp3_stereo_mode; +private: + inline void cb_choice_stream_mp3_stereo_mode_i(Fl_Choice*, void*); + static void cb_choice_stream_mp3_stereo_mode(Fl_Choice*, void*); + static unsigned char menu_choice_stream_mp3_stereo_mode_i18n_done; + static Fl_Menu_Item menu_choice_stream_mp3_stereo_mode[]; +public: + Fl_Choice *choice_stream_mp3_bitrate_mode; +private: + inline void cb_choice_stream_mp3_bitrate_mode_i(Fl_Choice*, void*); + static void cb_choice_stream_mp3_bitrate_mode(Fl_Choice*, void*); + static unsigned char menu_choice_stream_mp3_bitrate_mode_i18n_done; + static Fl_Menu_Item menu_choice_stream_mp3_bitrate_mode[]; +public: + Fl_Choice *choice_stream_mp3_vbr_quality; +private: + inline void cb_choice_stream_mp3_vbr_quality_i(Fl_Choice*, void*); + static void cb_choice_stream_mp3_vbr_quality(Fl_Choice*, void*); + static unsigned char menu_choice_stream_mp3_vbr_quality_i18n_done; + static Fl_Menu_Item menu_choice_stream_mp3_vbr_quality[]; +public: + Fl_Choice *choice_stream_mp3_vbr_min_bitrate; +private: + inline void cb_choice_stream_mp3_vbr_min_bitrate_i(Fl_Choice*, void*); + static void cb_choice_stream_mp3_vbr_min_bitrate(Fl_Choice*, void*); + static unsigned char menu_choice_stream_mp3_vbr_min_bitrate_i18n_done; + static Fl_Menu_Item menu_choice_stream_mp3_vbr_min_bitrate[]; +public: + Fl_Choice *choice_stream_mp3_vbr_max_bitrate; +private: + inline void cb_choice_stream_mp3_vbr_max_bitrate_i(Fl_Choice*, void*); + static void cb_choice_stream_mp3_vbr_max_bitrate(Fl_Choice*, void*); + static unsigned char menu_choice_stream_mp3_vbr_max_bitrate_i18n_done; + static Fl_Menu_Item menu_choice_stream_mp3_vbr_max_bitrate[]; +public: + Fl_Check_Button *check_stream_mp3_force_min_bitrate; +private: + inline void cb_check_stream_mp3_force_min_bitrate_i(Fl_Check_Button*, void*); + static void cb_check_stream_mp3_force_min_bitrate(Fl_Check_Button*, void*); +public: + Fl_Value_Input *input_stream_mp3_lowpass_freq; +private: + inline void cb_input_stream_mp3_lowpass_freq_i(Fl_Value_Input*, void*); + static void cb_input_stream_mp3_lowpass_freq(Fl_Value_Input*, void*); +public: + Fl_Value_Input *input_stream_mp3_lowpass_width; +private: + inline void cb_input_stream_mp3_lowpass_width_i(Fl_Value_Input*, void*); + static void cb_input_stream_mp3_lowpass_width(Fl_Value_Input*, void*); +public: + Fl_Check_Button *check_stream_mp3_activate_lowpass_freq; +private: + inline void cb_check_stream_mp3_activate_lowpass_freq_i(Fl_Check_Button*, void*); + static void cb_check_stream_mp3_activate_lowpass_freq(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_stream_mp3_activate_lowpass_width; +private: + inline void cb_check_stream_mp3_activate_lowpass_width_i(Fl_Check_Button*, void*); + static void cb_check_stream_mp3_activate_lowpass_width(Fl_Check_Button*, void*); +public: + Fl_Value_Input *input_stream_mp3_highpass_freq; +private: + inline void cb_input_stream_mp3_highpass_freq_i(Fl_Value_Input*, void*); + static void cb_input_stream_mp3_highpass_freq(Fl_Value_Input*, void*); +public: + Fl_Value_Input *input_stream_mp3_highpass_width; +private: + inline void cb_input_stream_mp3_highpass_width_i(Fl_Value_Input*, void*); + static void cb_input_stream_mp3_highpass_width(Fl_Value_Input*, void*); +public: + Fl_Check_Button *check_stream_mp3_activate_highpass_freq; +private: + inline void cb_check_stream_mp3_activate_highpass_freq_i(Fl_Check_Button*, void*); + static void cb_check_stream_mp3_activate_highpass_freq(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_stream_mp3_activate_highpass_width; +private: + inline void cb_check_stream_mp3_activate_highpass_width_i(Fl_Check_Button*, void*); + static void cb_check_stream_mp3_activate_highpass_width(Fl_Check_Button*, void*); +public: + Fl_Choice *choice_stream_mp3_resampling_freq; +private: + inline void cb_choice_stream_mp3_resampling_freq_i(Fl_Choice*, void*); + static void cb_choice_stream_mp3_resampling_freq(Fl_Choice*, void*); + static unsigned char menu_choice_stream_mp3_resampling_freq_i18n_done; + static Fl_Menu_Item menu_choice_stream_mp3_resampling_freq[]; +public: + Fl_Group *tab_stream_ogg; + Fl_Choice *choice_stream_vorbis_bitrate_mode; +private: + inline void cb_choice_stream_vorbis_bitrate_mode_i(Fl_Choice*, void*); + static void cb_choice_stream_vorbis_bitrate_mode(Fl_Choice*, void*); + static unsigned char menu_choice_stream_vorbis_bitrate_mode_i18n_done; + static Fl_Menu_Item menu_choice_stream_vorbis_bitrate_mode[]; +public: + Fl_Choice *choice_stream_vorbis_vbr_quality; +private: + inline void cb_choice_stream_vorbis_vbr_quality_i(Fl_Choice*, void*); + static void cb_choice_stream_vorbis_vbr_quality(Fl_Choice*, void*); + static unsigned char menu_choice_stream_vorbis_vbr_quality_i18n_done; + static Fl_Menu_Item menu_choice_stream_vorbis_vbr_quality[]; +public: + Fl_Choice *choice_stream_vorbis_vbr_min_bitrate; +private: + inline void cb_choice_stream_vorbis_vbr_min_bitrate_i(Fl_Choice*, void*); + static void cb_choice_stream_vorbis_vbr_min_bitrate(Fl_Choice*, void*); +public: + Fl_Choice *choice_stream_vorbis_vbr_max_bitrate; +private: + inline void cb_choice_stream_vorbis_vbr_max_bitrate_i(Fl_Choice*, void*); + static void cb_choice_stream_vorbis_vbr_max_bitrate(Fl_Choice*, void*); +public: + Fl_Group *tab_stream_opus; + Fl_Choice *choice_stream_opus_quality; +private: + inline void cb_choice_stream_opus_quality_i(Fl_Choice*, void*); + static void cb_choice_stream_opus_quality(Fl_Choice*, void*); + static unsigned char menu_choice_stream_opus_quality_i18n_done; + static Fl_Menu_Item menu_choice_stream_opus_quality[]; +public: + Fl_Choice *choice_stream_opus_audio_type; +private: + inline void cb_choice_stream_opus_audio_type_i(Fl_Choice*, void*); + static void cb_choice_stream_opus_audio_type(Fl_Choice*, void*); + static unsigned char menu_choice_stream_opus_audio_type_i18n_done; + static Fl_Menu_Item menu_choice_stream_opus_audio_type[]; +public: + Fl_Choice *choice_stream_opus_bitrate_mode; +private: + inline void cb_choice_stream_opus_bitrate_mode_i(Fl_Choice*, void*); + static void cb_choice_stream_opus_bitrate_mode(Fl_Choice*, void*); + static unsigned char menu_choice_stream_opus_bitrate_mode_i18n_done; + static Fl_Menu_Item menu_choice_stream_opus_bitrate_mode[]; +public: + Fl_Choice *choice_stream_opus_bandwidth; +private: + inline void cb_choice_stream_opus_bandwidth_i(Fl_Choice*, void*); + static void cb_choice_stream_opus_bandwidth(Fl_Choice*, void*); + static unsigned char menu_choice_stream_opus_bandwidth_i18n_done; + static Fl_Menu_Item menu_choice_stream_opus_bandwidth[]; +public: + Fl_Group *tab_stream_aac; + Fl_Choice *choice_stream_aac_profile; +private: + inline void cb_choice_stream_aac_profile_i(Fl_Choice*, void*); + static void cb_choice_stream_aac_profile(Fl_Choice*, void*); + static unsigned char menu_choice_stream_aac_profile_i18n_done; + static Fl_Menu_Item menu_choice_stream_aac_profile[]; +public: + Fl_Choice *choice_stream_aac_afterburner; +private: + inline void cb_choice_stream_aac_afterburner_i(Fl_Choice*, void*); + static void cb_choice_stream_aac_afterburner(Fl_Choice*, void*); + static unsigned char menu_choice_stream_aac_afterburner_i18n_done; + static Fl_Menu_Item menu_choice_stream_aac_afterburner[]; +public: + Fl_Choice *choice_stream_aac_bitrate_mode; +private: + inline void cb_choice_stream_aac_bitrate_mode_i(Fl_Choice*, void*); + static void cb_choice_stream_aac_bitrate_mode(Fl_Choice*, void*); + static unsigned char menu_choice_stream_aac_bitrate_mode_i18n_done; + static Fl_Menu_Item menu_choice_stream_aac_bitrate_mode[]; +public: + Fl_Group *tab_stream_flac; + Fl_Round_Button *radio_stream_flac_bit_depth_16; +private: + inline void cb_radio_stream_flac_bit_depth_16_i(Fl_Round_Button*, void*); + static void cb_radio_stream_flac_bit_depth_16(Fl_Round_Button*, void*); +public: + Fl_Round_Button *radio_stream_flac_bit_depth_24; +private: + inline void cb_radio_stream_flac_bit_depth_24_i(Fl_Round_Button*, void*); + static void cb_radio_stream_flac_bit_depth_24(Fl_Round_Button*, void*); + inline void cb_Close1_i(Fl_Button*, void*); + static void cb_Close1(Fl_Button*, void*); +public: + Fl_My_Double_Window *window_rec_codec_settings; + Fl_Tabs *tabs_rec_codec_settings; + Fl_Group *tab_rec_mp3; + Fl_Choice *choice_rec_mp3_enc_quality; +private: + inline void cb_choice_rec_mp3_enc_quality_i(Fl_Choice*, void*); + static void cb_choice_rec_mp3_enc_quality(Fl_Choice*, void*); + static unsigned char menu_choice_rec_mp3_enc_quality_i18n_done; + static Fl_Menu_Item menu_choice_rec_mp3_enc_quality[]; +public: + Fl_Choice *choice_rec_mp3_stereo_mode; +private: + inline void cb_choice_rec_mp3_stereo_mode_i(Fl_Choice*, void*); + static void cb_choice_rec_mp3_stereo_mode(Fl_Choice*, void*); + static unsigned char menu_choice_rec_mp3_stereo_mode_i18n_done; + static Fl_Menu_Item menu_choice_rec_mp3_stereo_mode[]; +public: + Fl_Choice *choice_rec_mp3_bitrate_mode; +private: + inline void cb_choice_rec_mp3_bitrate_mode_i(Fl_Choice*, void*); + static void cb_choice_rec_mp3_bitrate_mode(Fl_Choice*, void*); + static unsigned char menu_choice_rec_mp3_bitrate_mode_i18n_done; + static Fl_Menu_Item menu_choice_rec_mp3_bitrate_mode[]; +public: + Fl_Choice *choice_rec_mp3_vbr_quality; +private: + inline void cb_choice_rec_mp3_vbr_quality_i(Fl_Choice*, void*); + static void cb_choice_rec_mp3_vbr_quality(Fl_Choice*, void*); + static unsigned char menu_choice_rec_mp3_vbr_quality_i18n_done; + static Fl_Menu_Item menu_choice_rec_mp3_vbr_quality[]; +public: + Fl_Choice *choice_rec_mp3_vbr_min_bitrate; +private: + inline void cb_choice_rec_mp3_vbr_min_bitrate_i(Fl_Choice*, void*); + static void cb_choice_rec_mp3_vbr_min_bitrate(Fl_Choice*, void*); + static unsigned char menu_choice_rec_mp3_vbr_min_bitrate_i18n_done; + static Fl_Menu_Item menu_choice_rec_mp3_vbr_min_bitrate[]; +public: + Fl_Choice *choice_rec_mp3_vbr_max_bitrate; +private: + inline void cb_choice_rec_mp3_vbr_max_bitrate_i(Fl_Choice*, void*); + static void cb_choice_rec_mp3_vbr_max_bitrate(Fl_Choice*, void*); + static unsigned char menu_choice_rec_mp3_vbr_max_bitrate_i18n_done; + static Fl_Menu_Item menu_choice_rec_mp3_vbr_max_bitrate[]; +public: + Fl_Check_Button *check_rec_mp3_force_min_bitrate; +private: + inline void cb_check_rec_mp3_force_min_bitrate_i(Fl_Check_Button*, void*); + static void cb_check_rec_mp3_force_min_bitrate(Fl_Check_Button*, void*); +public: + Fl_Choice *choice_rec_mp3_resampling_freq; +private: + inline void cb_choice_rec_mp3_resampling_freq_i(Fl_Choice*, void*); + static void cb_choice_rec_mp3_resampling_freq(Fl_Choice*, void*); + static unsigned char menu_choice_rec_mp3_resampling_freq_i18n_done; + static Fl_Menu_Item menu_choice_rec_mp3_resampling_freq[]; +public: + Fl_Value_Input *input_rec_mp3_lowpass_freq; +private: + inline void cb_input_rec_mp3_lowpass_freq_i(Fl_Value_Input*, void*); + static void cb_input_rec_mp3_lowpass_freq(Fl_Value_Input*, void*); +public: + Fl_Value_Input *input_rec_mp3_lowpass_width; +private: + inline void cb_input_rec_mp3_lowpass_width_i(Fl_Value_Input*, void*); + static void cb_input_rec_mp3_lowpass_width(Fl_Value_Input*, void*); +public: + Fl_Check_Button *check_rec_mp3_activate_lowpass_freq; +private: + inline void cb_check_rec_mp3_activate_lowpass_freq_i(Fl_Check_Button*, void*); + static void cb_check_rec_mp3_activate_lowpass_freq(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_rec_mp3_activate_lowpass_width; +private: + inline void cb_check_rec_mp3_activate_lowpass_width_i(Fl_Check_Button*, void*); + static void cb_check_rec_mp3_activate_lowpass_width(Fl_Check_Button*, void*); +public: + Fl_Value_Input *input_rec_mp3_highpass_freq; +private: + inline void cb_input_rec_mp3_highpass_freq_i(Fl_Value_Input*, void*); + static void cb_input_rec_mp3_highpass_freq(Fl_Value_Input*, void*); +public: + Fl_Value_Input *input_rec_mp3_highpass_width; +private: + inline void cb_input_rec_mp3_highpass_width_i(Fl_Value_Input*, void*); + static void cb_input_rec_mp3_highpass_width(Fl_Value_Input*, void*); +public: + Fl_Check_Button *check_rec_mp3_activate_highpass_freq; +private: + inline void cb_check_rec_mp3_activate_highpass_freq_i(Fl_Check_Button*, void*); + static void cb_check_rec_mp3_activate_highpass_freq(Fl_Check_Button*, void*); +public: + Fl_Check_Button *check_rec_mp3_activate_highpass_width; +private: + inline void cb_check_rec_mp3_activate_highpass_width_i(Fl_Check_Button*, void*); + static void cb_check_rec_mp3_activate_highpass_width(Fl_Check_Button*, void*); +public: + Fl_Group *tab_rec_ogg; + Fl_Choice *choice_rec_vorbis_bitrate_mode; +private: + inline void cb_choice_rec_vorbis_bitrate_mode_i(Fl_Choice*, void*); + static void cb_choice_rec_vorbis_bitrate_mode(Fl_Choice*, void*); + static unsigned char menu_choice_rec_vorbis_bitrate_mode_i18n_done; + static Fl_Menu_Item menu_choice_rec_vorbis_bitrate_mode[]; +public: + Fl_Choice *choice_rec_vorbis_vbr_quality; +private: + inline void cb_choice_rec_vorbis_vbr_quality_i(Fl_Choice*, void*); + static void cb_choice_rec_vorbis_vbr_quality(Fl_Choice*, void*); + static unsigned char menu_choice_rec_vorbis_vbr_quality_i18n_done; + static Fl_Menu_Item menu_choice_rec_vorbis_vbr_quality[]; +public: + Fl_Choice *choice_rec_vorbis_vbr_min_bitrate; +private: + inline void cb_choice_rec_vorbis_vbr_min_bitrate_i(Fl_Choice*, void*); + static void cb_choice_rec_vorbis_vbr_min_bitrate(Fl_Choice*, void*); +public: + Fl_Choice *choice_rec_vorbis_vbr_max_bitrate; +private: + inline void cb_choice_rec_vorbis_vbr_max_bitrate_i(Fl_Choice*, void*); + static void cb_choice_rec_vorbis_vbr_max_bitrate(Fl_Choice*, void*); +public: + Fl_Group *tab_rec_opus; + Fl_Choice *choice_rec_opus_audio_type; +private: + inline void cb_choice_rec_opus_audio_type_i(Fl_Choice*, void*); + static void cb_choice_rec_opus_audio_type(Fl_Choice*, void*); + static unsigned char menu_choice_rec_opus_audio_type_i18n_done; + static Fl_Menu_Item menu_choice_rec_opus_audio_type[]; +public: + Fl_Choice *choice_rec_opus_bitrate_mode; +private: + inline void cb_choice_rec_opus_bitrate_mode_i(Fl_Choice*, void*); + static void cb_choice_rec_opus_bitrate_mode(Fl_Choice*, void*); + static unsigned char menu_choice_rec_opus_bitrate_mode_i18n_done; + static Fl_Menu_Item menu_choice_rec_opus_bitrate_mode[]; +public: + Fl_Choice *choice_rec_opus_quality; +private: + inline void cb_choice_rec_opus_quality_i(Fl_Choice*, void*); + static void cb_choice_rec_opus_quality(Fl_Choice*, void*); + static unsigned char menu_choice_rec_opus_quality_i18n_done; + static Fl_Menu_Item menu_choice_rec_opus_quality[]; +public: + Fl_Choice *choice_rec_opus_bandwidth; +private: + inline void cb_choice_rec_opus_bandwidth_i(Fl_Choice*, void*); + static void cb_choice_rec_opus_bandwidth(Fl_Choice*, void*); + static unsigned char menu_choice_rec_opus_bandwidth_i18n_done; + static Fl_Menu_Item menu_choice_rec_opus_bandwidth[]; +public: + Fl_Group *tab_rec_aac; + Fl_Choice *choice_rec_aac_profile; +private: + inline void cb_choice_rec_aac_profile_i(Fl_Choice*, void*); + static void cb_choice_rec_aac_profile(Fl_Choice*, void*); + static unsigned char menu_choice_rec_aac_profile_i18n_done; + static Fl_Menu_Item menu_choice_rec_aac_profile[]; +public: + Fl_Choice *choice_rec_aac_afterburner; +private: + inline void cb_choice_rec_aac_afterburner_i(Fl_Choice*, void*); + static void cb_choice_rec_aac_afterburner(Fl_Choice*, void*); + static unsigned char menu_choice_rec_aac_afterburner_i18n_done; + static Fl_Menu_Item menu_choice_rec_aac_afterburner[]; +public: + Fl_Choice *choice_rec_aac_bitrate_mode; +private: + inline void cb_choice_rec_aac_bitrate_mode_i(Fl_Choice*, void*); + static void cb_choice_rec_aac_bitrate_mode(Fl_Choice*, void*); + static unsigned char menu_choice_rec_aac_bitrate_mode_i18n_done; + static Fl_Menu_Item menu_choice_rec_aac_bitrate_mode[]; +public: + Fl_Group *tab_rec_flac; + Fl_Round_Button *radio_rec_flac_bit_depth_16; +private: + inline void cb_radio_rec_flac_bit_depth_16_i(Fl_Round_Button*, void*); + static void cb_radio_rec_flac_bit_depth_16(Fl_Round_Button*, void*); +public: + Fl_Round_Button *radio_rec_flac_bit_depth_24; +private: + inline void cb_radio_rec_flac_bit_depth_24_i(Fl_Round_Button*, void*); + static void cb_radio_rec_flac_bit_depth_24(Fl_Round_Button*, void*); +public: + Fl_Group *tab_rec_wav; + Fl_Round_Button *radio_rec_wav_bit_depth_16; +private: + inline void cb_radio_rec_wav_bit_depth_16_i(Fl_Round_Button*, void*); + static void cb_radio_rec_wav_bit_depth_16(Fl_Round_Button*, void*); +public: + Fl_Round_Button *radio_rec_wav_bit_depth_32; +private: + inline void cb_radio_rec_wav_bit_depth_32_i(Fl_Round_Button*, void*); + static void cb_radio_rec_wav_bit_depth_32(Fl_Round_Button*, void*); +public: + Fl_Round_Button *radio_rec_wav_bit_depth_24; +private: + inline void cb_radio_rec_wav_bit_depth_24_i(Fl_Round_Button*, void*); + static void cb_radio_rec_wav_bit_depth_24(Fl_Round_Button*, void*); + inline void cb_Close2_i(Fl_Button*, void*); + static void cb_Close2(Fl_Button*, void*); +public: + Fl_My_Double_Window *window_mixer; +private: + inline void cb_Reset2_i(Fl_Button*, void*); + static void cb_Reset2(Fl_Button*, void*); +public: + Fl_Text_Display *text_mixer_primary_device_volume; + Fl_My_Value_Slider *slider_mixer_primary_device; +private: + inline void cb_slider_mixer_primary_device_i(Fl_My_Value_Slider*, void*); + static void cb_slider_mixer_primary_device(Fl_My_Value_Slider*, void*); +public: + Fl_Light_Button *button_mixer_mute_primary_device; +private: + inline void cb_button_mixer_mute_primary_device_i(Fl_Light_Button*, void*); + static void cb_button_mixer_mute_primary_device(Fl_Light_Button*, void*); +public: + Fl_Text_Display *text_mixer_secondary_device_volume; + Fl_My_Value_Slider *slider_mixer_secondary_device; +private: + inline void cb_slider_mixer_secondary_device_i(Fl_My_Value_Slider*, void*); + static void cb_slider_mixer_secondary_device(Fl_My_Value_Slider*, void*); +public: + Fl_Light_Button *button_mixer_mute_secondary_device; +private: + inline void cb_button_mixer_mute_secondary_device_i(Fl_Light_Button*, void*); + static void cb_button_mixer_mute_secondary_device(Fl_Light_Button*, void*); +public: + Fl_Text_Display *text_mixer_streaming_volume; + Fl_My_Value_Slider *slider_mixer_streaming_gain; +private: + inline void cb_slider_mixer_streaming_gain_i(Fl_My_Value_Slider*, void*); + static void cb_slider_mixer_streaming_gain(Fl_My_Value_Slider*, void*); +public: + Fl_Text_Display *text_mixer_recording_volume; + Fl_My_Value_Slider *slider_mixer_recording_gain; +private: + inline void cb_slider_mixer_recording_gain_i(Fl_My_Value_Slider*, void*); + static void cb_slider_mixer_recording_gain(Fl_My_Value_Slider*, void*); +public: + Fl_Text_Display *text_mixer_master_volume; + Fl_My_Value_Slider *slider_mixer_master_gain; +private: + inline void cb_slider_mixer_master_gain_i(Fl_My_Value_Slider*, void*); + static void cb_slider_mixer_master_gain(Fl_My_Value_Slider*, void*); +public: + Fl_My_Value_Slider *slider_mixer_cross_fader; +private: + inline void cb_slider_mixer_cross_fader_i(Fl_My_Value_Slider*, void*); + static void cb_slider_mixer_cross_fader(Fl_My_Value_Slider*, void*); +public: + Fl_My_Double_Window *window_missing_aac_lib; +private: + inline void cb_Open_i(Fl_Button*, void*); + static void cb_Open(Fl_Button*, void*); + inline void cb_Close3_i(Fl_Button*, void*); + static void cb_Close3(Fl_Button*, void*); +public: + ~flgui(); +}; +#endif diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..e853d85 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,66 @@ +# what flags you want to pass to the C compiler & linker + +AM_CPPFLAGS = -IFLTK +AM_CPPFLAGS += -DLOCALEDIR='"$(localedir)"' +AM_CPPFLAGS += -D_="gettext" + +# +# # this lists the binaries to produce, the (non-PHONY, binary) targets in +# # the previous manual Makefile + +bin_PROGRAMS = + +if !CLIENT_ONLY +bin_PROGRAMS += butt +butt_SOURCES = butt.cpp butt.h cfg.cpp cfg.h icecast.cpp icecast.h lame_encode.cpp tls.cpp tls.h \ + lame_encode.h parseconfig.cpp parseconfig.h port_midi.cpp port_midi.h port_audio.cpp \ + port_audio.h ringbuffer.cpp ringbuffer.h shoutcast.cpp shoutcast.h \ + sockfuncs.cpp sockfuncs.h strfuncs.cpp strfuncs.h timer.cpp timer.h \ + util.cpp util.h vorbis_encode.cpp vorbis_encode.h vu_meter.cpp vu_meter.h webrtc.cpp webrtc.h \ + wav_header.cpp wav_header.h opus_encode.cpp opus_encode.h flac_encode.cpp flac_encode.h \ + dsp.cpp dsp.hpp Biquad.cpp Biquad.h command.cpp command.h update.cpp update.h logos.h \ + tray_agent.cpp tray_agent.h sha256.cpp sha256.h cJSON.cpp cJSON.h url.cpp url.h atom.h uri_encode.cpp uri_encode.h \ + FLTK/Fl_ILM216.cpp FLTK/Fl_ILM216.h FLTK/fl_callbacks.cpp \ + FLTK/fl_callbacks.h FLTK/fl_funcs.cpp FLTK/fl_funcs.h FLTK/flgui.cpp FLTK/flgui.h \ + FLTK/FL/Fl_My_Double_Window.H FLTK/FL/Fl_My_Value_Slider.H \ + FLTK/Fl_My_Native_File_Chooser.cxx FLTK/FL/Fl_My_Native_File_Chooser.H FLTK/Fl_vu_meter.cpp FLTK/Fl_vu_meter.h \ + FLTK/fl_timer_funcs.cpp FLTK/fl_timer_funcs.h aac_encode.cpp aac_encode.h \ + FLTK/Fl_LED.cpp FLTK/Fl_LED.h FLTK/FL/Fl_My_Invisible_Box.H +if WITH_RADIOCO +nodist_butt_SOURCES = radioco.cpp radioco.h oauth.cpp oauth.h +endif + +if WINDOWS +butt_SOURCES += resource.rc currentTrack.h currentTrack.cpp +butt_LDADD = -lintl + +# used only under MinGW to compile the resource.rc file (manifest and program icon) +# +.rc.o: + windres $^ -o $@ +%.o : %.rc + windres $^ -o $@ +endif + +if OSX +butt_SOURCES += CurrentTrackOSX.h CurrentTrackOSX.m AskForMicPermission.h AskForMicPermission.m +endif + +if LINUX +butt_SOURCES += currentTrack.h currentTrackLinux.cpp +endif + +if FREEBSD +butt_SOURCES += currentTrack.h currentTrackLinux.cpp +endif + +endif #!CLIENT_ONLY + + +# To build only the client on windows run ./configure --without-butt --disable-nls +if WITH_CLIENT +bin_PROGRAMS += butt-client +butt_client_SOURCES = butt.cpp command.cpp sockfuncs.cpp +butt_client_CPPFLAGS = -DBUILD_CLIENT $(AM_CPPFLAGS) +endif + diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..edbd8ec --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,1041 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# what flags you want to pass to the C compiler & linker + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +bin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) +@CLIENT_ONLY_FALSE@am__append_1 = butt +@CLIENT_ONLY_FALSE@@WINDOWS_TRUE@am__append_2 = resource.rc currentTrack.h currentTrack.cpp +@CLIENT_ONLY_FALSE@@OSX_TRUE@am__append_3 = CurrentTrackOSX.h CurrentTrackOSX.m AskForMicPermission.h AskForMicPermission.m +@CLIENT_ONLY_FALSE@@LINUX_TRUE@am__append_4 = currentTrack.h currentTrackLinux.cpp +@CLIENT_ONLY_FALSE@@FREEBSD_TRUE@am__append_5 = currentTrack.h currentTrackLinux.cpp + +# To build only the client on windows run ./configure --without-butt --disable-nls +@WITH_CLIENT_TRUE@am__append_6 = butt-client +subdir = src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@CLIENT_ONLY_FALSE@am__EXEEXT_1 = butt$(EXEEXT) +@WITH_CLIENT_TRUE@am__EXEEXT_2 = butt-client$(EXEEXT) +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am__butt_SOURCES_DIST = butt.cpp butt.h cfg.cpp cfg.h icecast.cpp \ + icecast.h lame_encode.cpp tls.cpp tls.h lame_encode.h \ + parseconfig.cpp parseconfig.h port_midi.cpp port_midi.h \ + port_audio.cpp port_audio.h ringbuffer.cpp ringbuffer.h \ + shoutcast.cpp shoutcast.h sockfuncs.cpp sockfuncs.h \ + strfuncs.cpp strfuncs.h timer.cpp timer.h util.cpp util.h \ + vorbis_encode.cpp vorbis_encode.h vu_meter.cpp vu_meter.h \ + webrtc.cpp webrtc.h wav_header.cpp wav_header.h \ + opus_encode.cpp opus_encode.h flac_encode.cpp flac_encode.h \ + dsp.cpp dsp.hpp Biquad.cpp Biquad.h command.cpp command.h \ + update.cpp update.h logos.h tray_agent.cpp tray_agent.h \ + sha256.cpp sha256.h cJSON.cpp cJSON.h url.cpp url.h atom.h \ + uri_encode.cpp uri_encode.h FLTK/Fl_ILM216.cpp \ + FLTK/Fl_ILM216.h FLTK/fl_callbacks.cpp FLTK/fl_callbacks.h \ + FLTK/fl_funcs.cpp FLTK/fl_funcs.h FLTK/flgui.cpp FLTK/flgui.h \ + FLTK/FL/Fl_My_Double_Window.H FLTK/FL/Fl_My_Value_Slider.H \ + FLTK/Fl_My_Native_File_Chooser.cxx \ + FLTK/FL/Fl_My_Native_File_Chooser.H FLTK/Fl_vu_meter.cpp \ + FLTK/Fl_vu_meter.h FLTK/fl_timer_funcs.cpp \ + FLTK/fl_timer_funcs.h aac_encode.cpp aac_encode.h \ + FLTK/Fl_LED.cpp FLTK/Fl_LED.h FLTK/FL/Fl_My_Invisible_Box.H \ + resource.rc currentTrack.h currentTrack.cpp CurrentTrackOSX.h \ + CurrentTrackOSX.m AskForMicPermission.h AskForMicPermission.m \ + currentTrackLinux.cpp +am__dirstamp = $(am__leading_dot)dirstamp +@CLIENT_ONLY_FALSE@@WINDOWS_TRUE@am__objects_1 = resource.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@@WINDOWS_TRUE@ currentTrack.$(OBJEXT) +@CLIENT_ONLY_FALSE@@OSX_TRUE@am__objects_2 = \ +@CLIENT_ONLY_FALSE@@OSX_TRUE@ CurrentTrackOSX.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@@OSX_TRUE@ AskForMicPermission.$(OBJEXT) +@CLIENT_ONLY_FALSE@@LINUX_TRUE@am__objects_3 = \ +@CLIENT_ONLY_FALSE@@LINUX_TRUE@ currentTrackLinux.$(OBJEXT) +@CLIENT_ONLY_FALSE@@FREEBSD_TRUE@am__objects_4 = \ +@CLIENT_ONLY_FALSE@@FREEBSD_TRUE@ currentTrackLinux.$(OBJEXT) +@CLIENT_ONLY_FALSE@am_butt_OBJECTS = butt.$(OBJEXT) cfg.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ icecast.$(OBJEXT) lame_encode.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ tls.$(OBJEXT) parseconfig.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ port_midi.$(OBJEXT) port_audio.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ ringbuffer.$(OBJEXT) shoutcast.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ sockfuncs.$(OBJEXT) strfuncs.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ timer.$(OBJEXT) util.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ vorbis_encode.$(OBJEXT) vu_meter.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ webrtc.$(OBJEXT) wav_header.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ opus_encode.$(OBJEXT) flac_encode.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ dsp.$(OBJEXT) Biquad.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ command.$(OBJEXT) update.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ tray_agent.$(OBJEXT) sha256.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ cJSON.$(OBJEXT) url.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ uri_encode.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ FLTK/Fl_ILM216.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ FLTK/fl_callbacks.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ FLTK/fl_funcs.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ FLTK/flgui.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ FLTK/Fl_My_Native_File_Chooser.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ FLTK/Fl_vu_meter.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ FLTK/fl_timer_funcs.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ aac_encode.$(OBJEXT) FLTK/Fl_LED.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@ $(am__objects_1) $(am__objects_2) \ +@CLIENT_ONLY_FALSE@ $(am__objects_3) $(am__objects_4) +@CLIENT_ONLY_FALSE@@WITH_RADIOCO_TRUE@nodist_butt_OBJECTS = \ +@CLIENT_ONLY_FALSE@@WITH_RADIOCO_TRUE@ radioco.$(OBJEXT) \ +@CLIENT_ONLY_FALSE@@WITH_RADIOCO_TRUE@ oauth.$(OBJEXT) +butt_OBJECTS = $(am_butt_OBJECTS) $(nodist_butt_OBJECTS) +butt_DEPENDENCIES = +am__butt_client_SOURCES_DIST = butt.cpp command.cpp sockfuncs.cpp +@WITH_CLIENT_TRUE@am_butt_client_OBJECTS = butt_client-butt.$(OBJEXT) \ +@WITH_CLIENT_TRUE@ butt_client-command.$(OBJEXT) \ +@WITH_CLIENT_TRUE@ butt_client-sockfuncs.$(OBJEXT) +butt_client_OBJECTS = $(am_butt_client_OBJECTS) +butt_client_LDADD = $(LDADD) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/AskForMicPermission.Po \ + ./$(DEPDIR)/Biquad.Po ./$(DEPDIR)/CurrentTrackOSX.Po \ + ./$(DEPDIR)/aac_encode.Po ./$(DEPDIR)/butt.Po \ + ./$(DEPDIR)/butt_client-butt.Po \ + ./$(DEPDIR)/butt_client-command.Po \ + ./$(DEPDIR)/butt_client-sockfuncs.Po ./$(DEPDIR)/cJSON.Po \ + ./$(DEPDIR)/cfg.Po ./$(DEPDIR)/command.Po \ + ./$(DEPDIR)/currentTrack.Po ./$(DEPDIR)/currentTrackLinux.Po \ + ./$(DEPDIR)/dsp.Po ./$(DEPDIR)/flac_encode.Po \ + ./$(DEPDIR)/icecast.Po ./$(DEPDIR)/lame_encode.Po \ + ./$(DEPDIR)/oauth.Po ./$(DEPDIR)/opus_encode.Po \ + ./$(DEPDIR)/parseconfig.Po ./$(DEPDIR)/port_audio.Po \ + ./$(DEPDIR)/port_midi.Po ./$(DEPDIR)/radioco.Po \ + ./$(DEPDIR)/ringbuffer.Po ./$(DEPDIR)/sha256.Po \ + ./$(DEPDIR)/shoutcast.Po ./$(DEPDIR)/sockfuncs.Po \ + ./$(DEPDIR)/strfuncs.Po ./$(DEPDIR)/timer.Po \ + ./$(DEPDIR)/tls.Po ./$(DEPDIR)/tray_agent.Po \ + ./$(DEPDIR)/update.Po ./$(DEPDIR)/uri_encode.Po \ + ./$(DEPDIR)/url.Po ./$(DEPDIR)/util.Po \ + ./$(DEPDIR)/vorbis_encode.Po ./$(DEPDIR)/vu_meter.Po \ + ./$(DEPDIR)/wav_header.Po ./$(DEPDIR)/webrtc.Po \ + FLTK/$(DEPDIR)/Fl_ILM216.Po FLTK/$(DEPDIR)/Fl_LED.Po \ + FLTK/$(DEPDIR)/Fl_My_Native_File_Chooser.Po \ + FLTK/$(DEPDIR)/Fl_vu_meter.Po FLTK/$(DEPDIR)/fl_callbacks.Po \ + FLTK/$(DEPDIR)/fl_funcs.Po FLTK/$(DEPDIR)/fl_timer_funcs.Po \ + FLTK/$(DEPDIR)/flgui.Po +am__mv = mv -f +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +OBJCCOMPILE = $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_OBJCFLAGS) $(OBJCFLAGS) +AM_V_OBJC = $(am__v_OBJC_@AM_V@) +am__v_OBJC_ = $(am__v_OBJC_@AM_DEFAULT_V@) +am__v_OBJC_0 = @echo " OBJC " $@; +am__v_OBJC_1 = +OBJCLD = $(OBJC) +OBJCLINK = $(OBJCLD) $(AM_OBJCFLAGS) $(OBJCFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_OBJCLD = $(am__v_OBJCLD_@AM_V@) +am__v_OBJCLD_ = $(am__v_OBJCLD_@AM_DEFAULT_V@) +am__v_OBJCLD_0 = @echo " OBJCLD " $@; +am__v_OBJCLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(butt_SOURCES) $(nodist_butt_SOURCES) \ + $(butt_client_SOURCES) +DIST_SOURCES = $(am__butt_SOURCES_DIST) \ + $(am__butt_client_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_LIBS = @DBUS_LIBS@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FLTKCONFIG = @FLTKCONFIG@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSUB = @POSUB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = -IFLTK -DLOCALEDIR='"$(localedir)"' -D_="gettext" +@CLIENT_ONLY_FALSE@butt_SOURCES = butt.cpp butt.h cfg.cpp cfg.h \ +@CLIENT_ONLY_FALSE@ icecast.cpp icecast.h lame_encode.cpp \ +@CLIENT_ONLY_FALSE@ tls.cpp tls.h lame_encode.h parseconfig.cpp \ +@CLIENT_ONLY_FALSE@ parseconfig.h port_midi.cpp port_midi.h \ +@CLIENT_ONLY_FALSE@ port_audio.cpp port_audio.h ringbuffer.cpp \ +@CLIENT_ONLY_FALSE@ ringbuffer.h shoutcast.cpp shoutcast.h \ +@CLIENT_ONLY_FALSE@ sockfuncs.cpp sockfuncs.h strfuncs.cpp \ +@CLIENT_ONLY_FALSE@ strfuncs.h timer.cpp timer.h util.cpp \ +@CLIENT_ONLY_FALSE@ util.h vorbis_encode.cpp vorbis_encode.h \ +@CLIENT_ONLY_FALSE@ vu_meter.cpp vu_meter.h webrtc.cpp webrtc.h \ +@CLIENT_ONLY_FALSE@ wav_header.cpp wav_header.h opus_encode.cpp \ +@CLIENT_ONLY_FALSE@ opus_encode.h flac_encode.cpp flac_encode.h \ +@CLIENT_ONLY_FALSE@ dsp.cpp dsp.hpp Biquad.cpp Biquad.h \ +@CLIENT_ONLY_FALSE@ command.cpp command.h update.cpp update.h \ +@CLIENT_ONLY_FALSE@ logos.h tray_agent.cpp tray_agent.h \ +@CLIENT_ONLY_FALSE@ sha256.cpp sha256.h cJSON.cpp cJSON.h \ +@CLIENT_ONLY_FALSE@ url.cpp url.h atom.h uri_encode.cpp \ +@CLIENT_ONLY_FALSE@ uri_encode.h FLTK/Fl_ILM216.cpp \ +@CLIENT_ONLY_FALSE@ FLTK/Fl_ILM216.h FLTK/fl_callbacks.cpp \ +@CLIENT_ONLY_FALSE@ FLTK/fl_callbacks.h FLTK/fl_funcs.cpp \ +@CLIENT_ONLY_FALSE@ FLTK/fl_funcs.h FLTK/flgui.cpp FLTK/flgui.h \ +@CLIENT_ONLY_FALSE@ FLTK/FL/Fl_My_Double_Window.H \ +@CLIENT_ONLY_FALSE@ FLTK/FL/Fl_My_Value_Slider.H \ +@CLIENT_ONLY_FALSE@ FLTK/Fl_My_Native_File_Chooser.cxx \ +@CLIENT_ONLY_FALSE@ FLTK/FL/Fl_My_Native_File_Chooser.H \ +@CLIENT_ONLY_FALSE@ FLTK/Fl_vu_meter.cpp FLTK/Fl_vu_meter.h \ +@CLIENT_ONLY_FALSE@ FLTK/fl_timer_funcs.cpp \ +@CLIENT_ONLY_FALSE@ FLTK/fl_timer_funcs.h aac_encode.cpp \ +@CLIENT_ONLY_FALSE@ aac_encode.h FLTK/Fl_LED.cpp FLTK/Fl_LED.h \ +@CLIENT_ONLY_FALSE@ FLTK/FL/Fl_My_Invisible_Box.H \ +@CLIENT_ONLY_FALSE@ $(am__append_2) $(am__append_3) \ +@CLIENT_ONLY_FALSE@ $(am__append_4) $(am__append_5) +@CLIENT_ONLY_FALSE@@WITH_RADIOCO_TRUE@nodist_butt_SOURCES = radioco.cpp radioco.h oauth.cpp oauth.h +@CLIENT_ONLY_FALSE@@WINDOWS_TRUE@butt_LDADD = -lintl +@WITH_CLIENT_TRUE@butt_client_SOURCES = butt.cpp command.cpp sockfuncs.cpp +@WITH_CLIENT_TRUE@butt_client_CPPFLAGS = -DBUILD_CLIENT $(AM_CPPFLAGS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .cxx .m .o .obj .rc +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) +FLTK/$(am__dirstamp): + @$(MKDIR_P) FLTK + @: > FLTK/$(am__dirstamp) +FLTK/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) FLTK/$(DEPDIR) + @: > FLTK/$(DEPDIR)/$(am__dirstamp) +FLTK/Fl_ILM216.$(OBJEXT): FLTK/$(am__dirstamp) \ + FLTK/$(DEPDIR)/$(am__dirstamp) +FLTK/fl_callbacks.$(OBJEXT): FLTK/$(am__dirstamp) \ + FLTK/$(DEPDIR)/$(am__dirstamp) +FLTK/fl_funcs.$(OBJEXT): FLTK/$(am__dirstamp) \ + FLTK/$(DEPDIR)/$(am__dirstamp) +FLTK/flgui.$(OBJEXT): FLTK/$(am__dirstamp) \ + FLTK/$(DEPDIR)/$(am__dirstamp) +FLTK/Fl_My_Native_File_Chooser.$(OBJEXT): FLTK/$(am__dirstamp) \ + FLTK/$(DEPDIR)/$(am__dirstamp) +FLTK/Fl_vu_meter.$(OBJEXT): FLTK/$(am__dirstamp) \ + FLTK/$(DEPDIR)/$(am__dirstamp) +FLTK/fl_timer_funcs.$(OBJEXT): FLTK/$(am__dirstamp) \ + FLTK/$(DEPDIR)/$(am__dirstamp) +FLTK/Fl_LED.$(OBJEXT): FLTK/$(am__dirstamp) \ + FLTK/$(DEPDIR)/$(am__dirstamp) + +butt$(EXEEXT): $(butt_OBJECTS) $(butt_DEPENDENCIES) $(EXTRA_butt_DEPENDENCIES) + @rm -f butt$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(butt_OBJECTS) $(butt_LDADD) $(LIBS) + +butt-client$(EXEEXT): $(butt_client_OBJECTS) $(butt_client_DEPENDENCIES) $(EXTRA_butt_client_DEPENDENCIES) + @rm -f butt-client$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(butt_client_OBJECTS) $(butt_client_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f FLTK/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AskForMicPermission.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Biquad.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CurrentTrackOSX.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aac_encode.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/butt.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/butt_client-butt.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/butt_client-command.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/butt_client-sockfuncs.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cJSON.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/command.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/currentTrack.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/currentTrackLinux.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsp.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flac_encode.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icecast.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lame_encode.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oauth.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opus_encode.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parseconfig.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/port_audio.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/port_midi.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radioco.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ringbuffer.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha256.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shoutcast.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sockfuncs.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strfuncs.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tray_agent.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/update.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uri_encode.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/url.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vorbis_encode.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vu_meter.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wav_header.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webrtc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@FLTK/$(DEPDIR)/Fl_ILM216.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@FLTK/$(DEPDIR)/Fl_LED.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@FLTK/$(DEPDIR)/Fl_My_Native_File_Chooser.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@FLTK/$(DEPDIR)/Fl_vu_meter.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@FLTK/$(DEPDIR)/fl_callbacks.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@FLTK/$(DEPDIR)/fl_funcs.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@FLTK/$(DEPDIR)/fl_timer_funcs.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@FLTK/$(DEPDIR)/flgui.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +butt_client-butt.o: butt.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(butt_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT butt_client-butt.o -MD -MP -MF $(DEPDIR)/butt_client-butt.Tpo -c -o butt_client-butt.o `test -f 'butt.cpp' || echo '$(srcdir)/'`butt.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/butt_client-butt.Tpo $(DEPDIR)/butt_client-butt.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='butt.cpp' object='butt_client-butt.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(butt_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o butt_client-butt.o `test -f 'butt.cpp' || echo '$(srcdir)/'`butt.cpp + +butt_client-butt.obj: butt.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(butt_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT butt_client-butt.obj -MD -MP -MF $(DEPDIR)/butt_client-butt.Tpo -c -o butt_client-butt.obj `if test -f 'butt.cpp'; then $(CYGPATH_W) 'butt.cpp'; else $(CYGPATH_W) '$(srcdir)/butt.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/butt_client-butt.Tpo $(DEPDIR)/butt_client-butt.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='butt.cpp' object='butt_client-butt.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(butt_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o butt_client-butt.obj `if test -f 'butt.cpp'; then $(CYGPATH_W) 'butt.cpp'; else $(CYGPATH_W) '$(srcdir)/butt.cpp'; fi` + +butt_client-command.o: command.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(butt_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT butt_client-command.o -MD -MP -MF $(DEPDIR)/butt_client-command.Tpo -c -o butt_client-command.o `test -f 'command.cpp' || echo '$(srcdir)/'`command.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/butt_client-command.Tpo $(DEPDIR)/butt_client-command.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='command.cpp' object='butt_client-command.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(butt_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o butt_client-command.o `test -f 'command.cpp' || echo '$(srcdir)/'`command.cpp + +butt_client-command.obj: command.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(butt_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT butt_client-command.obj -MD -MP -MF $(DEPDIR)/butt_client-command.Tpo -c -o butt_client-command.obj `if test -f 'command.cpp'; then $(CYGPATH_W) 'command.cpp'; else $(CYGPATH_W) '$(srcdir)/command.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/butt_client-command.Tpo $(DEPDIR)/butt_client-command.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='command.cpp' object='butt_client-command.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(butt_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o butt_client-command.obj `if test -f 'command.cpp'; then $(CYGPATH_W) 'command.cpp'; else $(CYGPATH_W) '$(srcdir)/command.cpp'; fi` + +butt_client-sockfuncs.o: sockfuncs.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(butt_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT butt_client-sockfuncs.o -MD -MP -MF $(DEPDIR)/butt_client-sockfuncs.Tpo -c -o butt_client-sockfuncs.o `test -f 'sockfuncs.cpp' || echo '$(srcdir)/'`sockfuncs.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/butt_client-sockfuncs.Tpo $(DEPDIR)/butt_client-sockfuncs.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='sockfuncs.cpp' object='butt_client-sockfuncs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(butt_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o butt_client-sockfuncs.o `test -f 'sockfuncs.cpp' || echo '$(srcdir)/'`sockfuncs.cpp + +butt_client-sockfuncs.obj: sockfuncs.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(butt_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT butt_client-sockfuncs.obj -MD -MP -MF $(DEPDIR)/butt_client-sockfuncs.Tpo -c -o butt_client-sockfuncs.obj `if test -f 'sockfuncs.cpp'; then $(CYGPATH_W) 'sockfuncs.cpp'; else $(CYGPATH_W) '$(srcdir)/sockfuncs.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/butt_client-sockfuncs.Tpo $(DEPDIR)/butt_client-sockfuncs.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='sockfuncs.cpp' object='butt_client-sockfuncs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(butt_client_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o butt_client-sockfuncs.obj `if test -f 'sockfuncs.cpp'; then $(CYGPATH_W) 'sockfuncs.cpp'; else $(CYGPATH_W) '$(srcdir)/sockfuncs.cpp'; fi` + +.cxx.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cxx.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.m.o: +@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepOBJC_TRUE@ $(OBJCCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepOBJC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(OBJCCOMPILE) -c -o $@ $< + +.m.obj: +@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepOBJC_TRUE@ $(OBJCCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepOBJC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(OBJCCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f FLTK/$(DEPDIR)/$(am__dirstamp) + -rm -f FLTK/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/AskForMicPermission.Po + -rm -f ./$(DEPDIR)/Biquad.Po + -rm -f ./$(DEPDIR)/CurrentTrackOSX.Po + -rm -f ./$(DEPDIR)/aac_encode.Po + -rm -f ./$(DEPDIR)/butt.Po + -rm -f ./$(DEPDIR)/butt_client-butt.Po + -rm -f ./$(DEPDIR)/butt_client-command.Po + -rm -f ./$(DEPDIR)/butt_client-sockfuncs.Po + -rm -f ./$(DEPDIR)/cJSON.Po + -rm -f ./$(DEPDIR)/cfg.Po + -rm -f ./$(DEPDIR)/command.Po + -rm -f ./$(DEPDIR)/currentTrack.Po + -rm -f ./$(DEPDIR)/currentTrackLinux.Po + -rm -f ./$(DEPDIR)/dsp.Po + -rm -f ./$(DEPDIR)/flac_encode.Po + -rm -f ./$(DEPDIR)/icecast.Po + -rm -f ./$(DEPDIR)/lame_encode.Po + -rm -f ./$(DEPDIR)/oauth.Po + -rm -f ./$(DEPDIR)/opus_encode.Po + -rm -f ./$(DEPDIR)/parseconfig.Po + -rm -f ./$(DEPDIR)/port_audio.Po + -rm -f ./$(DEPDIR)/port_midi.Po + -rm -f ./$(DEPDIR)/radioco.Po + -rm -f ./$(DEPDIR)/ringbuffer.Po + -rm -f ./$(DEPDIR)/sha256.Po + -rm -f ./$(DEPDIR)/shoutcast.Po + -rm -f ./$(DEPDIR)/sockfuncs.Po + -rm -f ./$(DEPDIR)/strfuncs.Po + -rm -f ./$(DEPDIR)/timer.Po + -rm -f ./$(DEPDIR)/tls.Po + -rm -f ./$(DEPDIR)/tray_agent.Po + -rm -f ./$(DEPDIR)/update.Po + -rm -f ./$(DEPDIR)/uri_encode.Po + -rm -f ./$(DEPDIR)/url.Po + -rm -f ./$(DEPDIR)/util.Po + -rm -f ./$(DEPDIR)/vorbis_encode.Po + -rm -f ./$(DEPDIR)/vu_meter.Po + -rm -f ./$(DEPDIR)/wav_header.Po + -rm -f ./$(DEPDIR)/webrtc.Po + -rm -f FLTK/$(DEPDIR)/Fl_ILM216.Po + -rm -f FLTK/$(DEPDIR)/Fl_LED.Po + -rm -f FLTK/$(DEPDIR)/Fl_My_Native_File_Chooser.Po + -rm -f FLTK/$(DEPDIR)/Fl_vu_meter.Po + -rm -f FLTK/$(DEPDIR)/fl_callbacks.Po + -rm -f FLTK/$(DEPDIR)/fl_funcs.Po + -rm -f FLTK/$(DEPDIR)/fl_timer_funcs.Po + -rm -f FLTK/$(DEPDIR)/flgui.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/AskForMicPermission.Po + -rm -f ./$(DEPDIR)/Biquad.Po + -rm -f ./$(DEPDIR)/CurrentTrackOSX.Po + -rm -f ./$(DEPDIR)/aac_encode.Po + -rm -f ./$(DEPDIR)/butt.Po + -rm -f ./$(DEPDIR)/butt_client-butt.Po + -rm -f ./$(DEPDIR)/butt_client-command.Po + -rm -f ./$(DEPDIR)/butt_client-sockfuncs.Po + -rm -f ./$(DEPDIR)/cJSON.Po + -rm -f ./$(DEPDIR)/cfg.Po + -rm -f ./$(DEPDIR)/command.Po + -rm -f ./$(DEPDIR)/currentTrack.Po + -rm -f ./$(DEPDIR)/currentTrackLinux.Po + -rm -f ./$(DEPDIR)/dsp.Po + -rm -f ./$(DEPDIR)/flac_encode.Po + -rm -f ./$(DEPDIR)/icecast.Po + -rm -f ./$(DEPDIR)/lame_encode.Po + -rm -f ./$(DEPDIR)/oauth.Po + -rm -f ./$(DEPDIR)/opus_encode.Po + -rm -f ./$(DEPDIR)/parseconfig.Po + -rm -f ./$(DEPDIR)/port_audio.Po + -rm -f ./$(DEPDIR)/port_midi.Po + -rm -f ./$(DEPDIR)/radioco.Po + -rm -f ./$(DEPDIR)/ringbuffer.Po + -rm -f ./$(DEPDIR)/sha256.Po + -rm -f ./$(DEPDIR)/shoutcast.Po + -rm -f ./$(DEPDIR)/sockfuncs.Po + -rm -f ./$(DEPDIR)/strfuncs.Po + -rm -f ./$(DEPDIR)/timer.Po + -rm -f ./$(DEPDIR)/tls.Po + -rm -f ./$(DEPDIR)/tray_agent.Po + -rm -f ./$(DEPDIR)/update.Po + -rm -f ./$(DEPDIR)/uri_encode.Po + -rm -f ./$(DEPDIR)/url.Po + -rm -f ./$(DEPDIR)/util.Po + -rm -f ./$(DEPDIR)/vorbis_encode.Po + -rm -f ./$(DEPDIR)/vu_meter.Po + -rm -f ./$(DEPDIR)/wav_header.Po + -rm -f ./$(DEPDIR)/webrtc.Po + -rm -f FLTK/$(DEPDIR)/Fl_ILM216.Po + -rm -f FLTK/$(DEPDIR)/Fl_LED.Po + -rm -f FLTK/$(DEPDIR)/Fl_My_Native_File_Chooser.Po + -rm -f FLTK/$(DEPDIR)/Fl_vu_meter.Po + -rm -f FLTK/$(DEPDIR)/fl_callbacks.Po + -rm -f FLTK/$(DEPDIR)/fl_funcs.Po + -rm -f FLTK/$(DEPDIR)/fl_timer_funcs.Po + -rm -f FLTK/$(DEPDIR)/flgui.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \ + distclean distclean-compile distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-binPROGRAMS install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-binPROGRAMS + +.PRECIOUS: Makefile + + +# used only under MinGW to compile the resource.rc file (manifest and program icon) +# +@CLIENT_ONLY_FALSE@@WINDOWS_TRUE@.rc.o: +@CLIENT_ONLY_FALSE@@WINDOWS_TRUE@ windres $^ -o $@ +@CLIENT_ONLY_FALSE@@WINDOWS_TRUE@%.o : %.rc +@CLIENT_ONLY_FALSE@@WINDOWS_TRUE@ windres $^ -o $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/aac_dll.h b/src/aac_dll.h new file mode 100644 index 0000000..7a32d2c --- /dev/null +++ b/src/aac_dll.h @@ -0,0 +1,25 @@ +#ifndef AAC_DLL_H +#define AAC_DLL_H + +#include +#include + +typedef AACENC_ERROR (*aacEncOpenPtr)(HANDLE_AACENCODER *, UINT, UINT); +extern aacEncOpenPtr aacEncOpen_butt; + +typedef AACENC_ERROR (*aacEncoder_SetParamPtr)(HANDLE_AACENCODER, AACENC_PARAM, UINT); +extern aacEncoder_SetParamPtr aacEncoder_SetParam_butt; + +typedef AACENC_ERROR (*aacEncoder_GetParamPtr)(HANDLE_AACENCODER, AACENC_PARAM); +extern aacEncoder_GetParamPtr aacEncoder_GetParam_butt; + +typedef AACENC_ERROR (*aacEncEncodePtr)(HANDLE_AACENCODER, const AACENC_BufDesc *, const AACENC_BufDesc *, const AACENC_InArgs *, AACENC_OutArgs *); +extern aacEncEncodePtr aacEncEncode_butt; + +typedef AACENC_ERROR (*aacEncInfoPtr)(HANDLE_AACENCODER, AACENC_InfoStruct *); +extern aacEncInfoPtr aacEncInfo_butt; + +typedef AACENC_ERROR (*aacEncClosePtr)(HANDLE_AACENCODER *); +extern aacEncClosePtr aacEncClose_butt; + +#endif // AAC_DLL_H diff --git a/src/aac_encode.cpp b/src/aac_encode.cpp new file mode 100644 index 0000000..56ea333 --- /dev/null +++ b/src/aac_encode.cpp @@ -0,0 +1,277 @@ +// aac encoding functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include +#include +#include "config.h" +#include "fl_funcs.h" +#include "aac_encode.h" +#include "wav_header.h" + +int g_aac_lib_available = 0; + +#ifdef HAVE_LIBFDK_AAC + +int aac_enc_init(aac_enc *aac) +{ + int rc; + int aot; + int vbr_mode = 0; + char info_buf[256]; + + if (g_aac_lib_available == 0) { + snprintf(info_buf, sizeof(info_buf), "libfdk-aac-2.dll not loaded"); + print_info(info_buf, 1); + return 1; + } + + switch (aac->profile) { + case 0: // Auto select profile + if (aac->bitrate < 48) { + aot = 29; // AAC+v2 + vbr_mode = 1; + } + else if (aac->bitrate >= 96) { + aot = 2; // AAC-LC + vbr_mode = 4; + } + else { + aot = 5; // AAC+v1 + vbr_mode = 2; + } + break; + case 1: + aot = 2; + vbr_mode = 4; + break; + case 2: + aot = 5; + vbr_mode = 2; + break; + case 3: + aot = 29; + vbr_mode = 1; + break; + default: + aot = 5; + vbr_mode = 2; + break; + } + + aacEncOpen_butt(&aac->handle, 0, aac->channel); + aacEncoder_SetParam_butt(aac->handle, AACENC_AOT, aot); + aacEncoder_SetParam_butt(aac->handle, AACENC_SAMPLERATE, aac->samplerate); + aacEncoder_SetParam_butt(aac->handle, AACENC_CHANNELMODE, aac->channel); + aacEncoder_SetParam_butt(aac->handle, AACENC_CHANNELORDER, 1); + aacEncoder_SetParam_butt(aac->handle, AACENC_BITRATE, aac->bitrate * 1000); + aacEncoder_SetParam_butt(aac->handle, AACENC_TRANSMUX, 2); // taken from the example aac-enc.c (ADTS output) + aacEncoder_SetParam_butt(aac->handle, AACENC_AFTERBURNER, aac->afterburner); + + if (aac->bitrate_mode == 1) { // VBR + aacEncoder_SetParam_butt(aac->handle, AACENC_BITRATEMODE, vbr_mode); + } + + if ((rc = aacEncEncode_butt(aac->handle, NULL, NULL, NULL, NULL)) != AACENC_OK) { + snprintf(info_buf, sizeof(info_buf), "unable to init aac params %d", rc); + print_info(info_buf, 1); + return 1; + } + + aacEncInfo_butt(aac->handle, &aac->info); + + /* + printf("AAC profile: %d (aot: %d)\n", aac->profile, aot); + printf("AAC afterburner: %d\n", aac->afterburner); + printf("AAC bitrate_mode: %d (vbr: %d)\n\n", aac->bitrate_mode, vbr_mode); + */ + // printf("AAC bitrate: %d\n", aac->bitrate); + + return 0; +} + +int aac_enc_reinit(aac_enc *aac) +{ + if (g_aac_lib_available == 0) { + char info_buf[256]; + snprintf(info_buf, sizeof(info_buf), "libfdk-aac-2.dll not loaded"); + print_info(info_buf, 1); + return 1; + } + + if (aac != NULL) { + aac_enc_close(aac); + return aac_enc_init(aac); + } + return 1; +} + +void aac_enc_close(aac_enc *aac) +{ + if (g_aac_lib_available == 0) { + char info_buf[256]; + snprintf(info_buf, sizeof(info_buf), "libfdk-aac-2.dll not loaded"); + print_info(info_buf, 1); + return; + } + + while (aac->state == AAC_BUSY) { + ; + } + + if (aac->handle != NULL) { + aacEncClose_butt(&aac->handle); + } + + aac->handle = NULL; +} + +int aac_enc_encode(aac_enc *aac, float *pcm_float, char *enc_buf, int frames, int enc_buf_size) +{ + if (g_aac_lib_available == 0) { + char info_buf[256]; + snprintf(info_buf, sizeof(info_buf), "libfdk-aac-2.dll not loaded"); + print_info(info_buf, 1); + return 0; + } + + AACENC_BufDesc in_buf = {0}; + AACENC_BufDesc out_buf = {0}; + AACENC_InArgs in_args = {0}; + AACENC_OutArgs out_args = {0}; + + int in_identifier = IN_AUDIO_DATA; + int in_size, in_elem_size; + int out_identifier = OUT_BITSTREAM_DATA; + int out_size, out_elem_size; + void *in_ptr, *out_ptr; + int32_t *pcm_int32; + + if (frames == 0 || aac->handle == NULL) { + return 0; + } + + in_size = frames * sizeof(int32_t) * aac->channel; + in_elem_size = sizeof(int32_t); + + pcm_int32 = (int32_t *)pcm_float; + in_ptr = pcm_int32; + in_args.numInSamples = frames * aac->channel; + in_buf.numBufs = 1; + in_buf.bufs = &in_ptr; + in_buf.bufferIdentifiers = &in_identifier; + in_buf.bufSizes = &in_size; + in_buf.bufElSizes = &in_elem_size; + + out_ptr = enc_buf; + out_size = enc_buf_size; + out_elem_size = 1; + out_buf.numBufs = 1; + out_buf.bufs = &out_ptr; + out_buf.bufferIdentifiers = &out_identifier; + out_buf.bufSizes = &out_size; + out_buf.bufElSizes = &out_elem_size; + + aac->state = AAC_BUSY; + + // Convert from float to int32 + for (int i = 0; i < frames * aac->channel; i++) { + if (pcm_float[i] > 0) { + pcm_int32[i] = (int32_t)round(fmin(pcm_float[i] * INT32_MAX, INT32_MAX)); + } + else { + pcm_int32[i] = (int32_t)round(fmax(-pcm_float[i] * INT32_MIN, INT32_MIN)); + } + } + + if (aacEncEncode_butt(aac->handle, &in_buf, &out_buf, &in_args, &out_args) != AACENC_OK) { + return 0; + } + + aac->state = AAC_READY; + return out_args.numOutBytes; +} + +int aac_enc_flush_file(aac_enc *aac, FILE *file) +{ + AACENC_BufDesc in_buf = {0}; + AACENC_BufDesc out_buf = {0}; + AACENC_InArgs in_args = {0}; + AACENC_OutArgs out_args = {0}; + + int ret; + int in_identifier = IN_AUDIO_DATA; + int in_size, in_elem_size; + int out_identifier = OUT_BITSTREAM_DATA; + int out_size, out_elem_size; + void *out_ptr; + char enc_buf[8192]; + int32_t dummy_buf[1] = {0}; + + if (aac->handle == NULL) { + printf("handle == NULL"); + return 1; + } + + in_size = 0; + in_elem_size = sizeof(int32_t); + + in_args.numInSamples = -1; + + in_buf.numBufs = 1; + in_buf.bufs = (void **)&dummy_buf; + in_buf.bufferIdentifiers = &in_identifier; + in_buf.bufSizes = &in_size; + in_buf.bufElSizes = &in_elem_size; + + out_ptr = enc_buf; + out_size = sizeof(enc_buf); + out_elem_size = 1; + + out_buf.numBufs = 1; + out_buf.bufs = &out_ptr; + out_buf.bufferIdentifiers = &out_identifier; + out_buf.bufSizes = &out_size; + out_buf.bufElSizes = &out_elem_size; + + aac->state = AAC_BUSY; + + for (;;) { + if ((ret = aacEncEncode_butt(aac->handle, &in_buf, &out_buf, &in_args, &out_args)) != AACENC_OK) { + if (ret == AACENC_ENCODE_EOF) { + break; + } + else { + //NOTE: When using the asan profile on macOS the flushing fails + printf("AAC flushing error: 0x%04X\n", ret); + aac->state = AAC_READY; + return 1; + } + } + + fwrite(enc_buf, sizeof(char), out_args.numOutBytes, file); + } + + aac->state = AAC_READY; + + return 0; +} + +int aac_enc_get_samplerate(aac_enc *aac) +{ + // return aacEncoder_GetParam_butt(aac->handle, AACENC_SAMPLERATE); + return aacEncoder_GetParam_butt(aac->handle, AACENC_SAMPLERATE); +} +#endif diff --git a/src/aac_encode.h b/src/aac_encode.h new file mode 100644 index 0000000..350a1a8 --- /dev/null +++ b/src/aac_encode.h @@ -0,0 +1,53 @@ +// aac encoding functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef AAC_ENCODE_H +#define AAC_ENCODE_H + +#include "config.h" + +#ifdef HAVE_LIBFDK_AAC + +#include "aac_dll.h" + +struct aac_enc { + HANDLE_AACENCODER handle; + AACENC_InfoStruct info; + int bitrate; + int samplerate; + int channel; + int bitrate_mode; + int afterburner; + int profile; + volatile int state; +}; + +enum { + AAC_READY = 0, + AAC_BUSY = 1, +}; + +int aac_enc_init(aac_enc *aac); +int aac_enc_encode(aac_enc *aac, float *pcm_buf, char *enc_buf, int samples, int enc_buf_size); +int aac_enc_get_samplerate(aac_enc *aac); +int aac_enc_reinit(aac_enc *aac); +int aac_enc_flush_file(aac_enc *aac, FILE *file); +void aac_enc_close(aac_enc *aac); + +#endif // HAVE_LIBFDK_AAC + +extern int g_aac_lib_available; + +#endif // AAC_ENCODE_H diff --git a/src/atom.h b/src/atom.h new file mode 100644 index 0000000..ad61798 --- /dev/null +++ b/src/atom.h @@ -0,0 +1,104 @@ +/* +Author: + Daniel Nöthen +Date: + August 2022 +Description: + Helper functions to create and handle atomic variables with pthreads +*/ + +#ifndef ATOM_H +#define ATOM_H +#include +#include +#include + +#define ATOM_NEW_COND(cond) atom_cond_t cond = {0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER} +#define ATOM_NEW_INT(atom, initial_value) atom_int_t atom = {initial_value, PTHREAD_MUTEX_INITIALIZER} + +typedef struct atom_cond { + int cond; + pthread_mutex_t m; + pthread_cond_t c; +} atom_cond_t; + +typedef struct atom_int { + int val; + pthread_mutex_t m; +} atom_int_t; + +inline void atom_cond_init(atom_cond_t *cond) +{ + cond->cond = 0; + pthread_mutex_init(&cond->m, NULL); + pthread_cond_init(&cond->c, NULL); +} + +inline void atom_cond_reset(atom_cond_t *cond) +{ + pthread_mutex_lock(&cond->m); + cond->cond = 0; + pthread_mutex_unlock(&cond->m); +} + +inline void atom_cond_destroy(atom_cond_t *cond) +{ + pthread_cond_destroy(&cond->c); + pthread_mutex_destroy(&cond->m); +} + +inline void atom_cond_wait(atom_cond_t *cond) +{ + pthread_mutex_lock(&cond->m); + while (cond->cond == 0) { + pthread_cond_wait(&cond->c, &cond->m); + } + cond->cond = 0; + pthread_mutex_unlock(&cond->m); +} + +inline int atom_cond_timedwait(atom_cond_t *cond, uint32_t timeout_us) +{ + int ret; + struct timespec t = {0}; + t.tv_sec = 0; + t.tv_nsec = timeout_us * 1000; + + pthread_mutex_lock(&cond->m); + while (cond->cond == 0) { + ret = pthread_cond_timedwait(&cond->c, &cond->m, &t); + if (ret == ETIMEDOUT) { + pthread_mutex_unlock(&cond->m); + return 0; + } + } + cond->cond = 0; + pthread_mutex_unlock(&cond->m); + return 1; +} + +inline void atom_cond_signal(atom_cond_t *cond) +{ + pthread_mutex_lock(&cond->m); + cond->cond = 1; + pthread_cond_signal(&cond->c); + pthread_mutex_unlock(&cond->m); +} + +inline void atom_set_int(atom_int_t *atom, int val) +{ + pthread_mutex_lock(&atom->m); + atom->val = val; + pthread_mutex_unlock(&atom->m); +} + +inline int atom_get_int(atom_int_t *atom) +{ + int val; + pthread_mutex_lock(&atom->m); + val = atom->val; + pthread_mutex_unlock(&atom->m); + return val; +} + +#endif // ATOM_H diff --git a/src/butt.cpp b/src/butt.cpp new file mode 100644 index 0000000..23d7c74 --- /dev/null +++ b/src/butt.cpp @@ -0,0 +1,933 @@ +// butt - broadcast using this tool +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include +#include +#include + +#include +#include +#ifdef WIN32 +#include +#define IDI_ICON 101 +#endif + +#ifndef BUILD_CLIENT +#include +#include +#if !defined(__APPLE__) && !defined(WIN32) +#include +#include +#endif + +#if defined(__APPLE__) +#include // for dirname +#include // for _NSGetExecutablePath +#include +#include "AskForMicPermission.h" +#endif +#endif // #ifndef BUILD_CLIENT + +#include "config.h" +#include "gettext.h" + +#include "butt.h" +#include "command.h" +#include "sockfuncs.h" +#ifndef BUILD_CLIENT +#include "cfg.h" +#include "port_audio.h" +#include "lame_encode.h" +#include "opus_encode.h" +#include "flac_encode.h" +#include "shoutcast.h" +#include "parseconfig.h" +#include "vu_meter.h" +#include "util.h" +#include "flgui.h" +#include "fl_funcs.h" +#include "fl_timer_funcs.h" +#include "update.h" +#include "tray_agent.h" +#ifdef WITH_RADIOCO +#include "radioco.h" +#endif +#ifdef HAVE_LIBFDK_AAC +#include "aac_encode.h" +#endif + +#include "port_midi.h" + +int g_print_debug_info = 0; + +bool recording; +bool connected; +bool streaming; +bool disconnect; +bool try_to_connect; + +int stream_socket; +double kbytes_sent; +double kbytes_written; +unsigned int record_start_hour; + +timer_ms_t rec_timer; +timer_ms_t stream_timer; + +lame_enc lame_stream; +lame_enc lame_rec; +vorbis_enc vorbis_stream; +vorbis_enc vorbis_rec; +opus_enc opus_stream; +opus_enc opus_rec; +flac_enc flac_stream; +flac_enc flac_rec; + +#ifdef HAVE_LIBFDK_AAC +aac_enc aac_stream; +aac_enc aac_rec; +aacEncOpenPtr aacEncOpen_butt; +aacEncoder_SetParamPtr aacEncoder_SetParam_butt; +aacEncoder_GetParamPtr aacEncoder_GetParam_butt; +aacEncEncodePtr aacEncEncode_butt; +aacEncInfoPtr aacEncInfo_butt; +aacEncClosePtr aacEncClose_butt; +#endif // ifdef HAVE_LIBFDK_AAC + +#endif // ifndef BUILD_CLIENT + +void print_usage(void) +{ +#ifndef BUILD_CLIENT + printf( + "Usage: butt [-h | -v | -s [name] | -u | -M | -m | -O | -o | -SLdrtqn | -c ] [-A | -U | -x] [-a ] [-p ]\n"); +#else + printf( + "Usage: butt-client [-h | -v | -s [name] | -u | -M | -m | -O | -o | -USdrtqn ] [-a ] [-p ]\n"); +#endif + fflush(stdout); +} + +#ifndef BUILD_CLIENT +void load_AAC_lib(void) +{ +#ifdef WIN32 + // Load aac library + HMODULE hModule = LoadLibrary(TEXT("libfdk-aac-2.dll")); + if (hModule != NULL) { + aacEncOpen_butt = (aacEncOpenPtr)GetProcAddress(hModule, "aacEncOpen"); + aacEncoder_SetParam_butt = (aacEncoder_SetParamPtr)GetProcAddress(hModule, "aacEncoder_SetParam"); + aacEncoder_GetParam_butt = (aacEncoder_GetParamPtr)GetProcAddress(hModule, "aacEncoder_GetParam"); + aacEncEncode_butt = (aacEncEncodePtr)GetProcAddress(hModule, "aacEncEncode"); + aacEncInfo_butt = (aacEncInfoPtr)GetProcAddress(hModule, "aacEncInfo"); + aacEncClose_butt = (aacEncClosePtr)GetProcAddress(hModule, "aacEncClose"); + g_aac_lib_available = 1; + } +#endif + +#if defined(__APPLE__) +#ifdef HAVE_LIBFDK_AAC + void *dylib = dlopen("libfdk-aac.2.dylib", RTLD_LAZY); + + if (dylib == NULL) { + dylib = dlopen("/Library/Application Support/butt/libfdk-aac.2.dylib", RTLD_LAZY); // New path since 0.1.34 + } + + if (dylib != NULL) { + // typedef AACENC_ERROR(WINAPI *aacEncOpenPtr)(HANDLE_AACENCODER*, UINT, UINT); + + aacEncOpen_butt = (aacEncOpenPtr)dlsym(dylib, "aacEncOpen"); + aacEncoder_SetParam_butt = (aacEncoder_SetParamPtr)dlsym(dylib, "aacEncoder_SetParam"); + aacEncoder_GetParam_butt = (aacEncoder_GetParamPtr)dlsym(dylib, "aacEncoder_GetParam"); + aacEncEncode_butt = (aacEncEncodePtr)dlsym(dylib, "aacEncEncode"); + aacEncInfo_butt = (aacEncInfoPtr)dlsym(dylib, "aacEncInfo"); + aacEncClose_butt = (aacEncClosePtr)dlsym(dylib, "aacEncClose"); + + g_aac_lib_available = 1; + } + + // askForMicPermission(); +#endif +#endif + +#if !defined(__APPLE__) && !defined(WIN32) // LINUX +#ifdef HAVE_LIBFDK_AAC + void *dylib = dlopen("libfdk-aac.so", RTLD_LAZY); + + if (dylib == NULL) { // Try other lib name + dylib = dlopen("libfdk-aac.so.2", RTLD_LAZY); + } + + if (dylib != NULL) { + // typedef AACENC_ERROR(WINAPI *aacEncOpenPtr)(HANDLE_AACENCODER*, UINT, UINT); + + aacEncOpen_butt = (aacEncOpenPtr)dlsym(dylib, "aacEncOpen"); + aacEncoder_SetParam_butt = (aacEncoder_SetParamPtr)dlsym(dylib, "aacEncoder_SetParam"); + aacEncoder_GetParam_butt = (aacEncoder_GetParamPtr)dlsym(dylib, "aacEncoder_GetParam"); + aacEncEncode_butt = (aacEncEncodePtr)dlsym(dylib, "aacEncEncode"); + aacEncInfo_butt = (aacEncInfoPtr)dlsym(dylib, "aacEncInfo"); + aacEncClose_butt = (aacEncClosePtr)dlsym(dylib, "aacEncClose"); + + g_aac_lib_available = 1; + } +#endif +#endif +} + +int read_cfg(void) +{ + char *p; + int shift_pressed; + + if (Fl::get_key(FL_Shift_L) || Fl::get_key(FL_Shift_R)) { + shift_pressed = 1; + } + else { + shift_pressed = 0; + } + + // Prepare configuration loading +#ifdef WIN32 + if ((cfg_path == NULL) || (shift_pressed == 1)) { + if ((p = fl_getenv("APPDATA")) == NULL) { + // If there is no "%APPDATA% we are probably in none-NT Windows + // So we save the config file to the programm directory + cfg_path = (char *)malloc(strlen(CONFIG_FILE) + 1); + strcpy(cfg_path, CONFIG_FILE); + } + else { + cfg_path = (char *)malloc((PATH_MAX + strlen(CONFIG_FILE) + 1) * sizeof(char)); + snprintf(cfg_path, PATH_MAX + strlen(CONFIG_FILE), "%s\\%s", p, CONFIG_FILE); + } + } +#else // UNIX/MacOS + if ((cfg_path == NULL) || (shift_pressed == 1)) { + if ((p = fl_getenv("HOME")) == NULL) { + fl_alert(_("No home-directory found")); + return 1; + } + else { + cfg_path = (char *)malloc((PATH_MAX + strlen(CONFIG_FILE) + 1) * sizeof(char)); + snprintf(cfg_path, PATH_MAX + strlen(CONFIG_FILE), "%s/%s", p, CONFIG_FILE); + } + } +#endif + + if (shift_pressed) { + int rc = fl_choice(_("The shift key was held down during startup.\n" + "Do you want to start butt with a new configuration file?\n" + "This will overwrite your existing configuration file at\n%s"), + 0, _("Start with old"), _("Start with new"), cfg_path); + if (rc == 2) { + if (cfg_create_default()) { + fl_alert(_("Could not create config %s\nbutt is going to close now"), cfg_path); + return 1; + } + } + } + + printf(_("Reading config %s\n"), cfg_path); + + fflush(stdout); + DEBUG_LOG("Reading config from "); + DEBUG_LOG(cfg_path); + + if (cfg_set_values(NULL) != 0) // read config file and initialize config struct + { + printf(_("Could not find config %s\n"), cfg_path); + fflush(stdout); + if (cfg_create_default()) { + fl_alert(_("Could not create config %s\nbutt is going to close now"), cfg_path); + DEBUG_LOG("Could not create default config file"); + return 1; + } + printf(_("butt created a default config at\n%s\n"), cfg_path); + fflush(stdout); + cfg_set_values(NULL); + } + + if (cfg.audio.dev_count == 0) { + DEBUG_LOG("Could not find input audio devices"); + fl_alert(_( + "Could not find any audio device with input channels.\nbutt requires at least one audio device with input channels in order to work.\nThis can either be a built-in audio device, an external audio device or a virtual audio device.\n\nbutt is going to close now.")); + return 1; + } + + return 0; +} + +void set_locale_from_system(void) +{ + setlocale(LC_CTYPE, ""); + setlocale(LC_MESSAGES, ""); + +#if defined(__APPLE__) + + char path_to_executeable[PATH_MAX]; + char path_to_locale_dir[PATH_MAX]; + + uint32_t path_len = (uint32_t)sizeof(path_to_executeable); + if (_NSGetExecutablePath(path_to_executeable, &path_len) == 0) { + char *folder_of_executable = strdup(dirname(path_to_executeable)); + snprintf(path_to_locale_dir, PATH_MAX, "%s%s", folder_of_executable, "/../Resources/locale"); + free(folder_of_executable); + } + + bindtextdomain(PACKAGE, path_to_locale_dir); + +#elif defined(WIN32) + bindtextdomain(PACKAGE, "locale"); +#else // Linux + char *p; + if ((p = fl_getenv("APPDIR")) != NULL) { // Set locale dir when launched from .AppImage + char path_to_locale_dir[PATH_MAX]; + snprintf(path_to_locale_dir, sizeof(path_to_locale_dir), "%s/usr/share/locale", p); + bindtextdomain(PACKAGE, path_to_locale_dir); + } + else { // Set locale dir to dir found by ./configure + bindtextdomain(PACKAGE, LOCALEDIR); + } +#endif + + textdomain(PACKAGE); + bind_textdomain_codeset(PACKAGE, "UTF-8"); +} + +void set_locale_from_config(void) +{ + int lang; + static char env_str[32]; + + setlocale(LC_CTYPE, ""); + setlocale(LC_MESSAGES, ""); + snprintf(env_str, sizeof(env_str), "LANG=%s", cfg.gui.lang_str); + putenv(env_str); + + snprintf(env_str, sizeof(env_str), "LANGUAGE=%s", cfg.gui.lang_str); + putenv(env_str); + +#if defined(__APPLE__) + char path_to_executeable[PATH_MAX]; + char path_to_locale_dir[PATH_MAX]; + + uint32_t path_len = (uint32_t)sizeof(path_to_executeable); + if (_NSGetExecutablePath(path_to_executeable, &path_len) == 0) { + char *folder_of_executable = strdup(dirname(path_to_executeable)); + snprintf(path_to_locale_dir, PATH_MAX, "%s%s", folder_of_executable, "/../Resources/locale"); + printf("%s\n", path_to_locale_dir); + free(folder_of_executable); + } + + bindtextdomain(PACKAGE, path_to_locale_dir); +#elif defined(WIN32) + bindtextdomain(PACKAGE, "locale"); +#else // Linux + char *p; + if ((p = fl_getenv("APPDIR")) != NULL) { // Set locale dir when launched from .AppImage + char path_to_locale_dir[PATH_MAX]; + snprintf(path_to_locale_dir, sizeof(path_to_locale_dir), "%s/usr/share/locale", p); + bindtextdomain(PACKAGE, path_to_locale_dir); + } + else { // Set locale dir to dir found by ./configure + bindtextdomain(PACKAGE, LOCALEDIR); + } +#endif + + textdomain(PACKAGE); + bind_textdomain_codeset(PACKAGE, "UTF-8"); +} +#endif // BUILD_CLIENT + +int get_threshold_from_args(char opt, char *optarg, command_t *command) +{ + float threshold = atof(optarg); + if (threshold < 0) { + printf(_("Illegal argument: Threshold must be a non-negative number\n")); + fflush(stdout); + } + else { + switch (opt) { + case 'M': + command->cmd = CMD_SET_STREAM_SIGNAL_THRESHOLD; + break; + case 'm': + command->cmd = CMD_SET_STREAM_SILENCE_THRESHOLD; + break; + case 'O': + command->cmd = CMD_SET_RECORD_SIGNAL_THRESHOLD; + break; + case 'o': + command->cmd = CMD_SET_RECORD_SILENCE_THRESHOLD; + break; + default: + printf("Internal error: Illegal value for \"opt\"\n"); + return -1; + } + command->param_size = sizeof(float); + command->param = (float *)malloc(command->param_size); + *((float *)command->param) = threshold; + printf(_("%c threshold set to %0.1f\n"), opt, threshold); + } + return threshold; +} + +int main(int argc, char *argv[]) +{ + DEBUG_LOG("Starting BUTT"); + char lcd_buf[33]; + char info_buf[256]; + int opt; + int port = 1256; + int search_port = 1; + int skip_opening_audio_device = 0; + int server_mode = SERVER_MODE_LOCAL; + sock_proto_t command_proto = SOCK_PROTO_TCP; + char server_addr[128]; + uint32_t song_len; + + srand(time(NULL)); + +#ifndef BUILD_CLIENT + + cfg_path = NULL; + // Activate support for multi threading + Fl::lock(); +#endif + + command_t command; + command.cmd = CMD_EMPTY; + command.param_size = 0; + command.param = NULL; + + snprintf(server_addr, sizeof(server_addr), "%s", "127.0.0.1"); + +#ifndef WIN32 + // ignore the SIGPIPE signal. (In case the server closes the connection unexpected) + signal(SIGPIPE, SIG_IGN); +#endif + +#ifndef BUILD_CLIENT +#ifdef ENABLE_NLS + DEBUG_LOG("Setting up locale"); + set_locale_from_system(); +#endif +#endif + + DEBUG_LOG("Init sockets"); + sock_init(); + +#ifdef BUILD_CLIENT + if (argc < 2) { + print_usage(); + } +#endif + + // Parse command line parameters + DEBUG_LOG("Parsing command line parameters"); + while ((opt = getopt(argc, argv, ":vhc:AULxs:drtnqu:a:p:SM:m:O:o:")) != -1) { + switch (opt) { +#ifndef BUILD_CLIENT + case 'A': + server_mode = SERVER_MODE_ALL; + break; + case 'x': + server_mode = SERVER_MODE_OFF; + break; + case 'c': + cfg_path = (char *)malloc((strlen(optarg) + 1) * sizeof(char)); + strcpy(cfg_path, optarg); + break; + case 'L': + snd_print_devices(); + return 0; + break; +#endif + case 'U': + command_proto = SOCK_PROTO_UDP; + break; + case 'p': + port = atoi(optarg); + if (port < 1024 || port > 65535) { + printf(_("Illegal argument: Port must be a number between 1023 and 65535\n")); + fflush(stdout); + return 1; + } + search_port = 0; + break; + case 's': + if (command.cmd != CMD_EMPTY) { + printf(_("Warning: You may only pass one control option. Option -%c has been ignored.\n"), opt); + break; + } + command.cmd = CMD_CONNECT; + command.param_size = (uint32_t)strlen(optarg) + 1; + command.param = (char *)malloc(command.param_size); + sprintf((char *)command.param, "%s", optarg); + break; + case 'd': + if (command.cmd != CMD_EMPTY) { + printf(_("Warning: You may only pass one control option. Option -%c has been ignored.\n"), opt); + break; + } + command.cmd = CMD_DISCONNECT; + break; + case 'r': + if (command.cmd != CMD_EMPTY) { + printf(_("Warning: You may only pass one control option. Option -%c has been ignored.\n"), opt); + break; + } + command.cmd = CMD_START_RECORDING; + break; + case 't': + if (command.cmd != CMD_EMPTY) { + printf(_("Warning: You may only pass one control option. Option -%c has been ignored.\n"), opt); + break; + } + command.cmd = CMD_STOP_RECORDING; + break; + case 'n': + if (command.cmd != CMD_EMPTY) { + printf(_("Warning: You may only pass one control option. Option -%c has been ignored.\n"), opt); + break; + } + command.cmd = CMD_SPLIT_RECORDING; + break; + case 'q': + if (command.cmd != CMD_EMPTY) { + printf(_("Warning: You may only pass one control option. Option -%c has been ignored.\n"), opt); + break; + } + command.cmd = CMD_QUIT; + break; + case 'v': + printf("%s %s\n", argv[0], VERSION); + fflush(stdout); + return 0; + case 'u': + if (command.cmd != CMD_EMPTY) { + printf(_("Warning: You may only pass one control option. Option -%c has been ignored.\n"), opt); + break; + } + song_len = strlen(optarg) + 1; + if (song_len > 1000) { + song_len = 1000; + } + + command.cmd = CMD_UPDATE_SONGNAME; + command.param_size = song_len; + command.param = (char *)malloc(command.param_size); + sprintf((char *)command.param, "%s", optarg); + break; + case 'a': + memset(server_addr, 0, sizeof(server_addr)); + snprintf(server_addr, sizeof(server_addr), "%s", optarg); + break; + case 'S': + if (command.cmd != CMD_EMPTY) { + printf(_("Warning: You may only pass one control option. Option -%c has been ignored.\n"), opt); + break; + } + command.cmd = CMD_GET_STATUS; + break; + case 'M': + case 'm': + case 'O': + case 'o': + if (command.cmd != CMD_EMPTY) { + printf(_("Warning: You may only pass one control option. Option -%c has been ignored.\n"), opt); + break; + } + if (get_threshold_from_args(opt, optarg, &command) < 0) { + return 1; + } + break; + case 'h': + print_usage(); + printf(_("\nOptions:\n" + "-h\tPrint this help text\n" + "-v\tPrint version information\n")); +#ifndef BUILD_CLIENT + printf(_("\nOptions for operating mode:\n" + "-c\tPath to configuration file\n" + "-L\tPrint available audio devices\n" + "-A\tCommand server will be accessible from your network/internet (default: localhost only)\n" + "-U\tCommand server will use UDP instead of TCP\n" + "-x\tDo not start a command server\n" + "-p\tPort where the command server shall listen to (default: 1256)\n")); +#endif + + printf(_("\nOptions for control mode:\n" + "-s\tConnect to streaming server\n" + "-d\tDisconnect from streaming server\n" + "-r\tStart recording\n" + "-t\tStop recording\n" + "-n\tSplit recording\n" + "-q\tQuit butt\n" + "-u\tupdate song name\n" + "-S\tRequest status\n" + "-M\tSet streaming signal threshold (seconds)\n" + "-m\tSet streaming silence threshold (seconds)\n" + "-O\tSet recording signal threshold (seconds)\n" + "-o\tSet recording silence threshold (seconds)\n" + "-U\tConnect via UDP instead of TCP\n" + "-a\tAddress of the butt instance to be controlled (default: 127.0.0.1)\n" + "-p\tPort of the butt instance to be controlled (default: 1256)\n")); + fflush(stdout); + return 0; + case '?': + printf(_("Illegal option -%c.\nType butt -h to get a list of supported options.\n"), optopt); + print_usage(); + return 1; + case ':': + if (optopt == 's') { // Handle connect option without argument + if (command.cmd != CMD_EMPTY) { + printf(_("Warning: You may only pass one control option. Option -%c has been ignored.\n"), optopt); + break; + } + command.cmd = CMD_CONNECT; + break; + } + printf(_("Option -%c requires an argument\n"), optopt); + print_usage(); + return 1; + default: + printf(_("Command line parsing failed\n")); + print_usage(); + return 1; + } + } + + // Handle commands + if (command.cmd != CMD_EMPTY) { + int ret; +#ifndef BUILD_CLIENT + if (cfg_path != NULL) { + free(cfg_path); + } +#endif + + ret = command_send_cmd(command, server_addr, port, command_proto); + + if (command.param != NULL) { + free(command.param); + } + + switch (ret) { + case CMD_ERR_CONNECT: + printf(_("No butt instance running on %s at port %d\n"), server_addr, port); + fflush(stdout); + return 1; + break; + case CMD_ERR_SEND_CMD: + printf(_("Error while sending command\n")); + fflush(stdout); + return 1; + break; + case CMD_ERR_RECV_RESPONSE: + printf(_("Error: Did not receive response packet\n")); + fflush(stdout); + return 1; + break; + default: + break; + } + + if (command.cmd == CMD_GET_STATUS) { + status_packet_t status_packet; + + ret = command_recv_status_reply(&status_packet, command_proto); + if (ret == SOCK_ERR_RECV) { + printf(_("Error: You may only request one status packet per second\n")); + return 1; + } + if (ret == CMD_ERR_RECV_STATUS) { + printf(_("Error: Did not receive status packet (UDP server not running?)\n")); + return 1; + } + if (ret < 0) { + printf(_("Network error while receiving status packet: %d\n"), ret); + return 1; + } + else if (ret == 0) { + printf(_("Error: Client and server versions do not match\n")); + return 1; + } + else if (ret > 0) { + int connected = (status_packet.status & (1 << STATUS_CONNECTED)) > 0; + int connecting = (status_packet.status & (1 << STATUS_CONNECTING)) > 0; + int recording = (status_packet.status & (1 << STATUS_RECORDING)) > 0; + int signal = (status_packet.status & (1 << STATUS_SIGNAL_DETECTED)) > 0; + int silence = (status_packet.status & (1 << STATUS_SILENCE_DETECTED)) > 0; + int is_extended_packet = (status_packet.status & (1 << STATUS_EXTENDED_PACKET)) > 0; + + printf(_("connected: %d\nconnecting: %d\nrecording: %d\nsignal present: %d\nsignal absent: %d\n"), connected, connecting, recording, signal, + silence); + fflush(stdout); + + if (is_extended_packet == 1) { + printf(_("stream seconds: %lu\n"), (unsigned long)status_packet.stream_seconds); + printf(_("stream kBytes: %lu\n"), (unsigned long)status_packet.stream_kByte); + printf(_("record seconds: %lu\n"), (unsigned long)status_packet.record_seconds); + printf(_("record kBytes: %lu\n"), (unsigned long)status_packet.record_kByte); + printf(_("volume left: %0.1f\n"), status_packet.volume_left / 10.0); + printf(_("volume right: %0.1f\n"), status_packet.volume_right / 10.0); + printf(_("song: %s\n"), status_packet.song); + printf(_("record path: %s\n"), status_packet.rec_path); + printf(_("listeners: %d\n"), status_packet.listener_count); + fflush(stdout); + free(status_packet.song); + free(status_packet.rec_path); + } + } + } + + return 0; + } + DEBUG_LOG("Parsing done"); + +#ifndef BUILD_CLIENT + if (Fl::get_key(FL_Control_L) || Fl::get_key(FL_Control_R)) { + fl_alert(_("The control key was held down during startup.\n" + "butt will start without opening an audio device.\n" + "Please select your preferred audio device in settings->audio")); + + skip_opening_audio_device = 1; + } + + DEBUG_LOG("Init audio subsystem"); + if (snd_init() != 0) { + fl_alert(_("PortAudio init failed\nbutt is going to close now")); + return 1; + } + + DEBUG_LOG("Trying to load AAC "); + load_AAC_lib(); + + DEBUG_LOG("Reading config"); + if (read_cfg() != 0) { + DEBUG_LOG("Failed to read config"); + return 1; + } + + DEBUG_LOG("Init DSP modules"); + snd_init_dsp(); + +#ifdef ENABLE_NLS + if (strcmp(cfg.gui.lang_str, "system") != 0) { + set_locale_from_config(); + } +#endif + +#if !defined(__APPLE__) && !defined(WIN32) // LINUX + Fl_File_Icon::load_system_icons(); + FL_NORMAL_SIZE = 12; +#endif + + DEBUG_LOG("Setting up GUI"); + fl_g = new flgui(); + fl_g->window_main->xclass("butt_FLTK"); + + DEBUG_LOG("Showing GUI"); + fl_g->window_main->show(); + fl_font(fl_font(), 10); + + strcpy(lcd_buf, _("idle")); + print_lcd(lcd_buf, strlen(lcd_buf), -2, 1); + fl_g->label_current_listeners->hide(); + +#ifdef WIN32 + DEBUG_LOG("Loading icons"); + fl_g->window_main->icon((char *)LoadIcon(fl_display, MAKEINTRESOURCE(IDI_ICON))); + // The fltk icon code above only loads the default icon. + // Here, once the window is shown, we can assign + // additional icons, just to make things look a bit nicer. + HANDLE bigicon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 32, 32, 0); + SendMessage(fl_xid(fl_g->window_main), WM_SETICON, ICON_BIG, (LPARAM)bigicon); + HANDLE smallicon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 16, 16, 0); + SendMessage(fl_xid(fl_g->window_main), WM_SETICON, ICON_SMALL, (LPARAM)smallicon); +#endif + +#ifndef BUILD_CLIENT +#if defined(__APPLE__) + DEBUG_LOG("Asking for mic permission"); + askForMicPermission(); +#endif +#endif + + lame_stream.gfp = NULL; + lame_rec.gfp = NULL; + flac_rec.encoder = NULL; + flac_stream.encoder = NULL; +#ifdef HAVE_LIBFDK_AAC + aac_stream.handle = NULL; + aac_rec.handle = NULL; +#endif + + snprintf(info_buf, sizeof(info_buf), + _("Starting %s\nWritten by Daniel Nöthen\n" + "iPhone/iPad client: https://izicast.de\n" + "Donate: paypal@danielnoethen.de\n"), + PACKAGE_STRING); + print_info(info_buf, 0); + + DEBUG_LOG("Init GUI and audio"); + init_main_gui_and_audio(); + if ((skip_opening_audio_device == 0) && (snd_open_streams() != 0)) { + DEBUG_LOG("Error opening audio stream"); + DEBUG_LOG("Trying system default audio device"); + cfg.audio.dev_num = 0; + cfg.audio.dev_name = (char *)realloc(cfg.audio.dev_name, strlen(_("Default PCM device (default)")) + 1); + strcpy(cfg.audio.dev_name, _("Default PCM device (default)")); + + cfg.audio.dev2_num = -1; + cfg.audio.dev2_name = (char *)realloc(cfg.audio.dev2_name, strlen(_("None")) + 1); + strcpy(cfg.audio.dev2_name, _("None")); + + if (snd_open_streams() != 0) { + fl_alert(_("Could not open audio device.\nPlease select your preferred audio device in settings->audio")); + } + else { + fl_alert(_("butt could not open previously used audio device.\nThe system default audio device will be used.\n")); + } + } + vu_init(); + + DEBUG_LOG("Initializing timers"); + Fl::add_timeout(5, &display_rotate_timer); + Fl::add_timeout(0.25, &cmd_timer); + Fl::add_timeout(0, &rotate_sponsor_logo_timer); + + if (cfg.main.connect_at_startup) { + button_connect_cb(); + } + else if (cfg.main.signal_detection == 1 && cfg.main.signal_threshold > 0) { + Fl::add_timeout(1, &stream_signal_timer); + } + + if (cfg.rec.rec_after_launch && !recording) { + button_record_cb(false); + } + else if (cfg.rec.signal_detection == 1 && cfg.rec.signal_threshold > 0) { + Fl::add_timeout(1, &record_signal_timer); + } + + if (server_mode != SERVER_MODE_OFF) { + int command_port = command_start_server(port, search_port, server_mode, command_proto); + if (command_port > 0) { + snprintf(info_buf, sizeof(info_buf), _("Command server listening on port %d\n"), command_port); + printf("%s", info_buf); + fflush(stdout); + // print_info(info_buf, 0); + } + else { + printf("ret command_start_server: %d\n", command_port); + snprintf(info_buf, sizeof(info_buf), _("Warning: could not start command server on port %d\n"), port); + printf("%s", info_buf); + fflush(stdout); + print_info(info_buf, 0); + } + } + + DEBUG_LOG("Checking for available updates"); + if (cfg.main.check_for_update) { + int rc; + char uri[100]; + char *new_version; + int ret = update_check_for_new_version(); + + if (ret == UPDATE_NEW_VERSION) { + new_version = update_get_version(); + rc = fl_choice(_("New version available: %s\nYou have version %s"), _("Don't ask again"), _("Cancel"), _("Get new version"), new_version, VERSION); + if (rc == 0) { + cfg.main.check_for_update = 0; + } + if (rc == 2) { + snprintf(uri, sizeof(uri) - 1, "https://danielnoethen.de/butt/index.html#_download"); + fl_open_uri(uri); + } + } + } + + DEBUG_LOG("Init MIDI module"); + PmError midi_result = midi_init(); + if (midi_result == 0) { + if (strcmp(cfg.midi.dev_name, "Disabled") != 0) { + if (midi_open_device(cfg.midi.dev_name) == 0) { + midi_start_polling(); + } + } + } + else { + snprintf(info_buf, sizeof(info_buf), _("Could not initialize PortMidi: %s"), Pm_GetErrorText(midi_result)); + print_info(info_buf, 1); + } + + DEBUG_LOG("Fill widgets with config data"); + fill_cfg_widgets(); + +#ifdef WIN32 + if (cfg.main.minimize_to_tray == 1) { + fl_g->window_main->minimize_to_tray = true; + } + + if (cfg.main.start_agent == 1) { + if ((tray_agent_start() == 0) && (cfg.gui.start_minimized == 0)) { + tray_agent_send_cmd(TA_START); + } + } + +#else + fl_g->group_agent->deactivate(); +#endif + +#ifndef WITH_RADIOCO + fl_g->radio_add_srv_radioco->hide(); +#endif + +#ifndef HAVE_LIBDATACHANNEL + fl_g->radio_add_srv_webrtc->deactivate(); + fl_g->radio_add_srv_webrtc->tooltip(_("butt was built without WebRTC support")); +#endif + + if (cfg.gui.start_minimized == 1) { + DEBUG_LOG("Starting minimized"); + fl_g->window_main->iconize(); + } + + // Make sure input field callbacks are called when the Enter key is pressed or when the field is released. + // Unfortunately this can not be configured in fluid, so we have to do it here. + fl_g->input_gui_vu_mid_range_start->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + fl_g->input_gui_vu_high_range_start->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + fl_g->input_cfg_silence->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + fl_g->input_cfg_signal->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + fl_g->input_rec_signal->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + fl_g->input_rec_silence->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + fl_g->input_gui_listeners_update_rate->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + fl_g->input_rec_filename->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + fl_g->input_stream_mp3_lowpass_freq->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + fl_g->input_stream_mp3_lowpass_width->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + fl_g->input_stream_mp3_highpass_freq->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + fl_g->input_stream_mp3_highpass_width->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + fl_g->input_rec_mp3_lowpass_freq->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + fl_g->input_rec_mp3_lowpass_width->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + fl_g->input_rec_mp3_highpass_freq->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + fl_g->input_rec_mp3_highpass_width->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); + + DEBUG_LOG("Launching final event handler"); + return GUI_LOOP(); + +#endif // BUILD_CLIENT +} diff --git a/src/butt.h b/src/butt.h new file mode 100644 index 0000000..e7cede0 --- /dev/null +++ b/src/butt.h @@ -0,0 +1,71 @@ +// butt - broadcast using this tool +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef BUTT_H +#define BUTT_H + +#include "config.h" + +#ifdef BUILD_CLIENT + #define DEBUG_LOG(str) "" +#endif + +#ifndef BUILD_CLIENT +#include "timer.h" +#include "lame_encode.h" +#include "vorbis_encode.h" +#include "opus_encode.h" +#include "flac_encode.h" +#include "aac_encode.h" +#include "fl_funcs.h" + +extern int g_print_debug_info; +#define DEBUG_LOG(str) \ + do { \ + if (g_print_debug_info == 1) { \ + write_log(str, "butt_debug.txt"); \ + } \ + } while (0) + +extern bool recording; // TRUE if butt is recording +extern bool connected; // TRUE if butt is connected to server +extern bool disconnect; // TRUE if butt should disconnect +extern bool streaming; +extern bool try_to_connect; + +extern int stream_socket; +extern double kbytes_sent; +extern double kbytes_written; + +extern unsigned int record_start_hour; // the hour when last recording started + +extern timer_ms_t rec_timer; +extern timer_ms_t stream_timer; + +extern lame_enc lame_stream; +extern lame_enc lame_rec; +extern vorbis_enc vorbis_stream; +extern vorbis_enc vorbis_rec; +extern opus_enc opus_stream; +extern opus_enc opus_rec; +extern flac_enc flac_rec; +extern flac_enc flac_stream; +#ifdef HAVE_LIBFDK_AAC +extern aac_enc aac_stream; +extern aac_enc aac_rec; +#endif + +#endif // #ifndef BUILD_CLIENT +#endif // #ifndef BUTT_H diff --git a/src/butt.manifest b/src/butt.manifest new file mode 100644 index 0000000..78f3d65 --- /dev/null +++ b/src/butt.manifest @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/cJSON.cpp b/src/cJSON.cpp new file mode 100644 index 0000000..95289aa --- /dev/null +++ b/src/cJSON.cpp @@ -0,0 +1,2781 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +/* disable warnings about old C89 functions in MSVC */ +#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#ifdef __GNUC__ +#pragma GCC visibility push(default) +#endif +#if defined(_MSC_VER) +#pragma warning(push) +/* disable warning about single line comments in system headers */ +#pragma warning(disable : 4001) +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef ENABLE_LOCALES +#include +#endif + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif +#ifdef __GNUC__ +#pragma GCC visibility pop +#endif + +#include "cJSON.h" + +/* define our own boolean type */ +#ifdef true +#undef true +#endif +#define true ((cJSON_bool)1) + +#ifdef false +#undef false +#endif +#define false ((cJSON_bool)0) + +/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */ +#ifndef isinf +#define isinf(d) (isnan((d - d)) && !isnan(d)) +#endif +#ifndef isnan +#define isnan(d) (d != d) +#endif + +#ifndef NAN +#ifdef _WIN32 +#define NAN sqrt(-1.0) +#else +#define NAN 0.0 / 0.0 +#endif +#endif + +typedef struct { + const unsigned char *json; + size_t position; +} error; +static error global_error = {NULL, 0}; + +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) +{ + return (const char *)(global_error.json + global_error.position); +} + +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON *const item) +{ + if (!cJSON_IsString(item)) { + return NULL; + } + + return item->valuestring; +} + +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item) +{ + if (!cJSON_IsNumber(item)) { + return (double)NAN; + } + + return item->valuedouble; +} + +/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 15) +#error cJSON.h and cJSON.c have different versions. Make sure that both have the same. +#endif + +CJSON_PUBLIC(const char *) cJSON_Version(void) +{ + static char version[15]; + sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + + return version; +} + +/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ +static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) +{ + if ((string1 == NULL) || (string2 == NULL)) { + return 1; + } + + if (string1 == string2) { + return 0; + } + + for (; tolower(*string1) == tolower(*string2); (void)string1++, string2++) { + if (*string1 == '\0') { + return 0; + } + } + + return tolower(*string1) - tolower(*string2); +} + +typedef struct internal_hooks { + void *(CJSON_CDECL *allocate)(size_t size); + void(CJSON_CDECL *deallocate)(void *pointer); + void *(CJSON_CDECL *reallocate)(void *pointer, size_t size); +} internal_hooks; + +#if defined(_MSC_VER) +/* work around MSVC error C2322: '...' address of dllimport '...' is not static */ +static void *CJSON_CDECL internal_malloc(size_t size) +{ + return malloc(size); +} +static void CJSON_CDECL internal_free(void *pointer) +{ + free(pointer); +} +static void *CJSON_CDECL internal_realloc(void *pointer, size_t size) +{ + return realloc(pointer, size); +} +#else +#define internal_malloc malloc +#define internal_free free +#define internal_realloc realloc +#endif + +/* strlen of character literals resolved at compile time */ +#define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) + +static internal_hooks global_hooks = {internal_malloc, internal_free, internal_realloc}; + +static unsigned char *cJSON_strdup(const unsigned char *string, const internal_hooks *const hooks) +{ + size_t length = 0; + unsigned char *copy = NULL; + + if (string == NULL) { + return NULL; + } + + length = strlen((const char *)string) + sizeof(""); + copy = (unsigned char *)hooks->allocate(length); + if (copy == NULL) { + return NULL; + } + memcpy(copy, string, length); + + return copy; +} + +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks *hooks) +{ + if (hooks == NULL) { + /* Reset hooks */ + global_hooks.allocate = malloc; + global_hooks.deallocate = free; + global_hooks.reallocate = realloc; + return; + } + + global_hooks.allocate = malloc; + if (hooks->malloc_fn != NULL) { + global_hooks.allocate = hooks->malloc_fn; + } + + global_hooks.deallocate = free; + if (hooks->free_fn != NULL) { + global_hooks.deallocate = hooks->free_fn; + } + + /* use realloc only if both free and malloc are used */ + global_hooks.reallocate = NULL; + if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) { + global_hooks.reallocate = realloc; + } +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(const internal_hooks *const hooks) +{ + cJSON *node = (cJSON *)hooks->allocate(sizeof(cJSON)); + if (node) { + memset(node, '\0', sizeof(cJSON)); + } + + return node; +} + +/* Delete a cJSON structure. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) +{ + cJSON *next = NULL; + while (item != NULL) { + next = item->next; + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) { + cJSON_Delete(item->child); + } + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) { + global_hooks.deallocate(item->valuestring); + } + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { + global_hooks.deallocate(item->string); + } + global_hooks.deallocate(item); + item = next; + } +} + +/* get the decimal point character of the current locale */ +static unsigned char get_decimal_point(void) +{ +#ifdef ENABLE_LOCALES + struct lconv *lconv = localeconv(); + return (unsigned char)lconv->decimal_point[0]; +#else + return '.'; +#endif +} + +typedef struct { + const unsigned char *content; + size_t length; + size_t offset; + size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ + internal_hooks hooks; +} parse_buffer; + +/* check if the given size is left to read in a given parse buffer (starting with 1) */ +#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) +/* check if the buffer can be accessed at the given index (starting with 0) */ +#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) +#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) +/* get a pointer to the buffer at the position */ +#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) + +/* Parse the input text to generate a number, and populate the result into item. */ +static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) +{ + double number = 0; + unsigned char *after_end = NULL; + unsigned char number_c_string[64]; + unsigned char decimal_point = get_decimal_point(); + size_t i = 0; + + if ((input_buffer == NULL) || (input_buffer->content == NULL)) { + return false; + } + + /* copy the number into a temporary buffer and replace '.' with the decimal point + * of the current locale (for strtod) + * This also takes care of '\0' not necessarily being available for marking the end of the input */ + for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) { + switch (buffer_at_offset(input_buffer)[i]) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '+': + case '-': + case 'e': + case 'E': + number_c_string[i] = buffer_at_offset(input_buffer)[i]; + break; + + case '.': + number_c_string[i] = decimal_point; + break; + + default: + goto loop_end; + } + } +loop_end: + number_c_string[i] = '\0'; + + number = strtod((const char *)number_c_string, (char **)&after_end); + if (number_c_string == after_end) { + return false; /* parse_error */ + } + + item->valuedouble = number; + + /* use saturation in case of overflow */ + if (number >= INT_MAX) { + item->valueint = INT_MAX; + } + else if (number <= (double)INT_MIN) { + item->valueint = INT_MIN; + } + else { + item->valueint = (int)number; + } + + item->type = cJSON_Number; + + input_buffer->offset += (size_t)(after_end - number_c_string); + return true; +} + +/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) +{ + if (number >= INT_MAX) { + object->valueint = INT_MAX; + } + else if (number <= (double)INT_MIN) { + object->valueint = INT_MIN; + } + else { + object->valueint = (int)number; + } + + return object->valuedouble = number; +} + +CJSON_PUBLIC(char *) cJSON_SetValuestring(cJSON *object, const char *valuestring) +{ + char *copy = NULL; + /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */ + if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference)) { + return NULL; + } + if (strlen(valuestring) <= strlen(object->valuestring)) { + strcpy(object->valuestring, valuestring); + return object->valuestring; + } + copy = (char *)cJSON_strdup((const unsigned char *)valuestring, &global_hooks); + if (copy == NULL) { + return NULL; + } + if (object->valuestring != NULL) { + cJSON_free(object->valuestring); + } + object->valuestring = copy; + + return copy; +} + +typedef struct { + unsigned char *buffer; + size_t length; + size_t offset; + size_t depth; /* current nesting depth (for formatted printing) */ + cJSON_bool noalloc; + cJSON_bool format; /* is this print a formatted print */ + internal_hooks hooks; +} printbuffer; + +/* realloc printbuffer if necessary to have at least "needed" bytes more */ +static unsigned char *ensure(printbuffer *const p, size_t needed) +{ + unsigned char *newbuffer = NULL; + size_t newsize = 0; + + if ((p == NULL) || (p->buffer == NULL)) { + return NULL; + } + + if ((p->length > 0) && (p->offset >= p->length)) { + /* make sure that offset is valid */ + return NULL; + } + + if (needed > INT_MAX) { + /* sizes bigger than INT_MAX are currently not supported */ + return NULL; + } + + needed += p->offset + 1; + if (needed <= p->length) { + return p->buffer + p->offset; + } + + if (p->noalloc) { + return NULL; + } + + /* calculate new buffer size */ + if (needed > (INT_MAX / 2)) { + /* overflow of int, use INT_MAX if possible */ + if (needed <= INT_MAX) { + newsize = INT_MAX; + } + else { + return NULL; + } + } + else { + newsize = needed * 2; + } + + if (p->hooks.reallocate != NULL) { + /* reallocate with realloc if available */ + newbuffer = (unsigned char *)p->hooks.reallocate(p->buffer, newsize); + if (newbuffer == NULL) { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + } + else { + /* otherwise reallocate manually */ + newbuffer = (unsigned char *)p->hooks.allocate(newsize); + if (!newbuffer) { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + + memcpy(newbuffer, p->buffer, p->offset + 1); + p->hooks.deallocate(p->buffer); + } + p->length = newsize; + p->buffer = newbuffer; + + return newbuffer + p->offset; +} + +/* calculate the new length of the string in a printbuffer and update the offset */ +static void update_offset(printbuffer *const buffer) +{ + const unsigned char *buffer_pointer = NULL; + if ((buffer == NULL) || (buffer->buffer == NULL)) { + return; + } + buffer_pointer = buffer->buffer + buffer->offset; + + buffer->offset += strlen((const char *)buffer_pointer); +} + +/* securely comparison of floating-point variables */ +static cJSON_bool compare_double(double a, double b) +{ + double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); + return (fabs(a - b) <= maxVal * DBL_EPSILON); +} + +/* Render the number nicely from the given item into a string. */ +static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer) +{ + unsigned char *output_pointer = NULL; + double d = item->valuedouble; + int length = 0; + size_t i = 0; + unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */ + unsigned char decimal_point = get_decimal_point(); + double test = 0.0; + + if (output_buffer == NULL) { + return false; + } + + /* This checks for NaN and Infinity */ + if (isnan(d) || isinf(d)) { + length = sprintf((char *)number_buffer, "null"); + } + else { + /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ + length = sprintf((char *)number_buffer, "%1.15g", d); + + /* Check whether the original double can be recovered */ + if ((sscanf((char *)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) { + /* If not, print with 17 decimal places of precision */ + length = sprintf((char *)number_buffer, "%1.17g", d); + } + } + + /* sprintf failed or buffer overrun occurred */ + if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) { + return false; + } + + /* reserve appropriate space in the output */ + output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); + if (output_pointer == NULL) { + return false; + } + + /* copy the printed number to the output and replace locale + * dependent decimal point with '.' */ + for (i = 0; i < ((size_t)length); i++) { + if (number_buffer[i] == decimal_point) { + output_pointer[i] = '.'; + continue; + } + + output_pointer[i] = number_buffer[i]; + } + output_pointer[i] = '\0'; + + output_buffer->offset += (size_t)length; + + return true; +} + +/* parse 4 digit hexadecimal number */ +static unsigned parse_hex4(const unsigned char *const input) +{ + unsigned int h = 0; + size_t i = 0; + + for (i = 0; i < 4; i++) { + /* parse digit */ + if ((input[i] >= '0') && (input[i] <= '9')) { + h += (unsigned int)input[i] - '0'; + } + else if ((input[i] >= 'A') && (input[i] <= 'F')) { + h += (unsigned int)10 + input[i] - 'A'; + } + else if ((input[i] >= 'a') && (input[i] <= 'f')) { + h += (unsigned int)10 + input[i] - 'a'; + } + else /* invalid */ + { + return 0; + } + + if (i < 3) { + /* shift left to make place for the next nibble */ + h = h << 4; + } + } + + return h; +} + +/* converts a UTF-16 literal to UTF-8 + * A literal can be one or two sequences of the form \uXXXX */ +static unsigned char utf16_literal_to_utf8(const unsigned char *const input_pointer, const unsigned char *const input_end, unsigned char **output_pointer) +{ + long unsigned int codepoint = 0; + unsigned int first_code = 0; + const unsigned char *first_sequence = input_pointer; + unsigned char utf8_length = 0; + unsigned char utf8_position = 0; + unsigned char sequence_length = 0; + unsigned char first_byte_mark = 0; + + if ((input_end - first_sequence) < 6) { + /* input ends unexpectedly */ + goto fail; + } + + /* get the first utf16 sequence */ + first_code = parse_hex4(first_sequence + 2); + + /* check that the code is valid */ + if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) { + goto fail; + } + + /* UTF16 surrogate pair */ + if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) { + const unsigned char *second_sequence = first_sequence + 6; + unsigned int second_code = 0; + sequence_length = 12; /* \uXXXX\uXXXX */ + + if ((input_end - second_sequence) < 6) { + /* input ends unexpectedly */ + goto fail; + } + + if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) { + /* missing second half of the surrogate pair */ + goto fail; + } + + /* get the second utf16 sequence */ + second_code = parse_hex4(second_sequence + 2); + /* check that the code is valid */ + if ((second_code < 0xDC00) || (second_code > 0xDFFF)) { + /* invalid second half of the surrogate pair */ + goto fail; + } + + /* calculate the unicode codepoint from the surrogate pair */ + codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); + } + else { + sequence_length = 6; /* \uXXXX */ + codepoint = first_code; + } + + /* encode as UTF-8 + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if (codepoint < 0x80) { + /* normal ascii, encoding 0xxxxxxx */ + utf8_length = 1; + } + else if (codepoint < 0x800) { + /* two bytes, encoding 110xxxxx 10xxxxxx */ + utf8_length = 2; + first_byte_mark = 0xC0; /* 11000000 */ + } + else if (codepoint < 0x10000) { + /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ + utf8_length = 3; + first_byte_mark = 0xE0; /* 11100000 */ + } + else if (codepoint <= 0x10FFFF) { + /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ + utf8_length = 4; + first_byte_mark = 0xF0; /* 11110000 */ + } + else { + /* invalid unicode codepoint */ + goto fail; + } + + /* encode as utf8 */ + for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) { + /* 10xxxxxx */ + (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); + codepoint >>= 6; + } + /* encode first byte */ + if (utf8_length > 1) { + (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); + } + else { + (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); + } + + *output_pointer += utf8_length; + + return sequence_length; + +fail: + return 0; +} + +/* Parse the input text into an unescaped cinput, and populate item. */ +static cJSON_bool parse_string(cJSON *const item, parse_buffer *const input_buffer) +{ + const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; + const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; + unsigned char *output_pointer = NULL; + unsigned char *output = NULL; + + /* not a string */ + if (buffer_at_offset(input_buffer)[0] != '\"') { + goto fail; + } + + { + /* calculate approximate size of the output (overestimate) */ + size_t allocation_length = 0; + size_t skipped_bytes = 0; + while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) { + /* is escape sequence */ + if (input_end[0] == '\\') { + if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) { + /* prevent buffer overflow when last input character is a backslash */ + goto fail; + } + skipped_bytes++; + input_end++; + } + input_end++; + } + if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) { + goto fail; /* string ended unexpectedly */ + } + + /* This is at most how much we need for the output */ + allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes; + output = (unsigned char *)input_buffer->hooks.allocate(allocation_length + sizeof("")); + if (output == NULL) { + goto fail; /* allocation failure */ + } + } + + output_pointer = output; + /* loop through the string literal */ + while (input_pointer < input_end) { + if (*input_pointer != '\\') { + *output_pointer++ = *input_pointer++; + } + /* escape sequence */ + else { + unsigned char sequence_length = 2; + if ((input_end - input_pointer) < 1) { + goto fail; + } + + switch (input_pointer[1]) { + case 'b': + *output_pointer++ = '\b'; + break; + case 'f': + *output_pointer++ = '\f'; + break; + case 'n': + *output_pointer++ = '\n'; + break; + case 'r': + *output_pointer++ = '\r'; + break; + case 't': + *output_pointer++ = '\t'; + break; + case '\"': + case '\\': + case '/': + *output_pointer++ = input_pointer[1]; + break; + + /* UTF-16 literal */ + case 'u': + sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); + if (sequence_length == 0) { + /* failed to convert UTF16-literal to UTF-8 */ + goto fail; + } + break; + + default: + goto fail; + } + input_pointer += sequence_length; + } + } + + /* zero terminate the output */ + *output_pointer = '\0'; + + item->type = cJSON_String; + item->valuestring = (char *)output; + + input_buffer->offset = (size_t)(input_end - input_buffer->content); + input_buffer->offset++; + + return true; + +fail: + if (output != NULL) { + input_buffer->hooks.deallocate(output); + } + + if (input_pointer != NULL) { + input_buffer->offset = (size_t)(input_pointer - input_buffer->content); + } + + return false; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer) +{ + const unsigned char *input_pointer = NULL; + unsigned char *output = NULL; + unsigned char *output_pointer = NULL; + size_t output_length = 0; + /* numbers of additional characters needed for escaping */ + size_t escape_characters = 0; + + if (output_buffer == NULL) { + return false; + } + + /* empty string */ + if (input == NULL) { + output = ensure(output_buffer, sizeof("\"\"")); + if (output == NULL) { + return false; + } + strcpy((char *)output, "\"\""); + + return true; + } + + /* set "flag" to 1 if something needs to be escaped */ + for (input_pointer = input; *input_pointer; input_pointer++) { + switch (*input_pointer) { + case '\"': + case '\\': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + /* one character escape sequence */ + escape_characters++; + break; + default: + if (*input_pointer < 32) { + /* UTF-16 escape sequence uXXXX */ + escape_characters += 5; + } + break; + } + } + output_length = (size_t)(input_pointer - input) + escape_characters; + + output = ensure(output_buffer, output_length + sizeof("\"\"")); + if (output == NULL) { + return false; + } + + /* no characters have to be escaped */ + if (escape_characters == 0) { + output[0] = '\"'; + memcpy(output + 1, input, output_length); + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; + } + + output[0] = '\"'; + output_pointer = output + 1; + /* copy the string */ + for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) { + if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) { + /* normal character, copy */ + *output_pointer = *input_pointer; + } + else { + /* character needs to be escaped */ + *output_pointer++ = '\\'; + switch (*input_pointer) { + case '\\': + *output_pointer = '\\'; + break; + case '\"': + *output_pointer = '\"'; + break; + case '\b': + *output_pointer = 'b'; + break; + case '\f': + *output_pointer = 'f'; + break; + case '\n': + *output_pointer = 'n'; + break; + case '\r': + *output_pointer = 'r'; + break; + case '\t': + *output_pointer = 't'; + break; + default: + /* escape and print as unicode codepoint */ + sprintf((char *)output_pointer, "u%04x", *input_pointer); + output_pointer += 4; + break; + } + } + } + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; +} + +/* Invoke print_string_ptr (which is useful) on an item. */ +static cJSON_bool print_string(const cJSON *const item, printbuffer *const p) +{ + return print_string_ptr((unsigned char *)item->valuestring, p); +} + +/* Predeclare these prototypes. */ +static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer); +static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer); +static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer); +static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer); +static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer); +static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer); + +/* Utility to jump whitespace and cr/lf */ +static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL)) { + return NULL; + } + + if (cannot_access_at_index(buffer, 0)) { + return buffer; + } + + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) { + buffer->offset++; + } + + if (buffer->offset == buffer->length) { + buffer->offset--; + } + + return buffer; +} + +/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ +static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) { + return NULL; + } + + if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) { + buffer->offset += 3; + } + + return buffer; +} + +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + size_t buffer_length; + + if (NULL == value) { + return NULL; + } + + /* Adding null character size due to require_null_terminated. */ + buffer_length = strlen(value) + sizeof(""); + + return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated); +} + +/* Parse an object - create a new root, and populate. */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + parse_buffer buffer = {0, 0, 0, 0, {0, 0, 0}}; + cJSON *item = NULL; + + /* reset error position */ + global_error.json = NULL; + global_error.position = 0; + + if (value == NULL || 0 == buffer_length) { + goto fail; + } + + buffer.content = (const unsigned char *)value; + buffer.length = buffer_length; + buffer.offset = 0; + buffer.hooks = global_hooks; + + item = cJSON_New_Item(&global_hooks); + if (item == NULL) /* memory fail */ + { + goto fail; + } + + if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) { + /* parse failure. ep is set. */ + goto fail; + } + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) { + buffer_skip_whitespace(&buffer); + if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') { + goto fail; + } + } + if (return_parse_end) { + *return_parse_end = (const char *)buffer_at_offset(&buffer); + } + + return item; + +fail: + if (item != NULL) { + cJSON_Delete(item); + } + + if (value != NULL) { + error local_error; + local_error.json = (const unsigned char *)value; + local_error.position = 0; + + if (buffer.offset < buffer.length) { + local_error.position = buffer.offset; + } + else if (buffer.length > 0) { + local_error.position = buffer.length - 1; + } + + if (return_parse_end != NULL) { + *return_parse_end = (const char *)local_error.json + local_error.position; + } + + global_error = local_error; + } + + return NULL; +} + +/* Default options for cJSON_Parse */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) +{ + return cJSON_ParseWithOpts(value, 0, 0); +} + +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length) +{ + return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); +} + +#define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) + +static unsigned char *print(const cJSON *const item, cJSON_bool format, const internal_hooks *const hooks) +{ + static const size_t default_buffer_size = 256; + printbuffer buffer[1]; + unsigned char *printed = NULL; + + memset(buffer, 0, sizeof(buffer)); + + /* create buffer */ + buffer->buffer = (unsigned char *)hooks->allocate(default_buffer_size); + buffer->length = default_buffer_size; + buffer->format = format; + buffer->hooks = *hooks; + if (buffer->buffer == NULL) { + goto fail; + } + + /* print the value */ + if (!print_value(item, buffer)) { + goto fail; + } + update_offset(buffer); + + /* check if reallocate is available */ + if (hooks->reallocate != NULL) { + printed = (unsigned char *)hooks->reallocate(buffer->buffer, buffer->offset + 1); + if (printed == NULL) { + goto fail; + } + buffer->buffer = NULL; + } + else /* otherwise copy the JSON over to a new buffer */ + { + printed = (unsigned char *)hooks->allocate(buffer->offset + 1); + if (printed == NULL) { + goto fail; + } + memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); + printed[buffer->offset] = '\0'; /* just to be sure */ + + /* free the buffer */ + hooks->deallocate(buffer->buffer); + } + + return printed; + +fail: + if (buffer->buffer != NULL) { + hooks->deallocate(buffer->buffer); + } + + if (printed != NULL) { + hooks->deallocate(printed); + } + + return NULL; +} + +/* Render a cJSON item/entity/structure to text. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) +{ + return (char *)print(item, true, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) +{ + return (char *)print(item, false, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) +{ + printbuffer p = {0, 0, 0, 0, 0, 0, {0, 0, 0}}; + + if (prebuffer < 0) { + return NULL; + } + + p.buffer = (unsigned char *)global_hooks.allocate((size_t)prebuffer); + if (!p.buffer) { + return NULL; + } + + p.length = (size_t)prebuffer; + p.offset = 0; + p.noalloc = false; + p.format = fmt; + p.hooks = global_hooks; + + if (!print_value(item, &p)) { + global_hooks.deallocate(p.buffer); + return NULL; + } + + return (char *)p.buffer; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) +{ + printbuffer p = {0, 0, 0, 0, 0, 0, {0, 0, 0}}; + + if ((length < 0) || (buffer == NULL)) { + return false; + } + + p.buffer = (unsigned char *)buffer; + p.length = (size_t)length; + p.offset = 0; + p.noalloc = true; + p.format = format; + p.hooks = global_hooks; + + return print_value(item, &p); +} + +/* Parser core - when encountering text, process appropriately. */ +static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer) +{ + if ((input_buffer == NULL) || (input_buffer->content == NULL)) { + return false; /* no input */ + } + + /* parse the different types of values */ + /* null */ + if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) { + item->type = cJSON_NULL; + input_buffer->offset += 4; + return true; + } + /* false */ + if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) { + item->type = cJSON_False; + input_buffer->offset += 5; + return true; + } + /* true */ + if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) { + item->type = cJSON_True; + item->valueint = 1; + input_buffer->offset += 4; + return true; + } + /* string */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) { + return parse_string(item, input_buffer); + } + /* number */ + if (can_access_at_index(input_buffer, 0) && + ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) { + return parse_number(item, input_buffer); + } + /* array */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) { + return parse_array(item, input_buffer); + } + /* object */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) { + return parse_object(item, input_buffer); + } + + return false; +} + +/* Render a value to text. */ +static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer) +{ + unsigned char *output = NULL; + + if ((item == NULL) || (output_buffer == NULL)) { + return false; + } + + switch ((item->type) & 0xFF) { + case cJSON_NULL: + output = ensure(output_buffer, 5); + if (output == NULL) { + return false; + } + strcpy((char *)output, "null"); + return true; + + case cJSON_False: + output = ensure(output_buffer, 6); + if (output == NULL) { + return false; + } + strcpy((char *)output, "false"); + return true; + + case cJSON_True: + output = ensure(output_buffer, 5); + if (output == NULL) { + return false; + } + strcpy((char *)output, "true"); + return true; + + case cJSON_Number: + return print_number(item, output_buffer); + + case cJSON_Raw: { + size_t raw_length = 0; + if (item->valuestring == NULL) { + return false; + } + + raw_length = strlen(item->valuestring) + sizeof(""); + output = ensure(output_buffer, raw_length); + if (output == NULL) { + return false; + } + memcpy(output, item->valuestring, raw_length); + return true; + } + + case cJSON_String: + return print_string(item, output_buffer); + + case cJSON_Array: + return print_array(item, output_buffer); + + case cJSON_Object: + return print_object(item, output_buffer); + + default: + return false; + } +} + +/* Build an array from input text. */ +static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer) +{ + cJSON *head = NULL; /* head of the linked list */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (buffer_at_offset(input_buffer)[0] != '[') { + /* not an array */ + goto fail; + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) { + /* empty array */ + goto success; + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) { + /* start the linked list */ + current_item = head = new_item; + } + else { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse next value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') { + goto fail; /* expected end of array */ + } + +success: + input_buffer->depth--; + + if (head != NULL) { + head->prev = current_item; + } + + item->type = cJSON_Array; + item->child = head; + + input_buffer->offset++; + + return true; + +fail: + if (head != NULL) { + cJSON_Delete(head); + } + + return false; +} + +/* Render an array to text */ +static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_element = item->child; + + if (output_buffer == NULL) { + return false; + } + + /* Compose the output array. */ + /* opening square bracket */ + output_pointer = ensure(output_buffer, 1); + if (output_pointer == NULL) { + return false; + } + + *output_pointer = '['; + output_buffer->offset++; + output_buffer->depth++; + + while (current_element != NULL) { + if (!print_value(current_element, output_buffer)) { + return false; + } + update_offset(output_buffer); + if (current_element->next) { + length = (size_t)(output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) { + return false; + } + *output_pointer++ = ','; + if (output_buffer->format) { + *output_pointer++ = ' '; + } + *output_pointer = '\0'; + output_buffer->offset += length; + } + current_element = current_element->next; + } + + output_pointer = ensure(output_buffer, 2); + if (output_pointer == NULL) { + return false; + } + *output_pointer++ = ']'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Build an object from the text. */ +static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer) +{ + cJSON *head = NULL; /* linked list head */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) { + goto fail; /* not an object */ + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) { + goto success; /* empty object */ + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) { + /* start the linked list */ + current_item = head = new_item; + } + else { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse the name of the child */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_string(current_item, input_buffer)) { + goto fail; /* failed to parse name */ + } + buffer_skip_whitespace(input_buffer); + + /* swap valuestring and string, because we parsed the name */ + current_item->string = current_item->valuestring; + current_item->valuestring = NULL; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) { + goto fail; /* invalid object */ + } + + /* parse the value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) { + goto fail; /* expected end of object */ + } + +success: + input_buffer->depth--; + + if (head != NULL) { + head->prev = current_item; + } + + item->type = cJSON_Object; + item->child = head; + + input_buffer->offset++; + return true; + +fail: + if (head != NULL) { + cJSON_Delete(head); + } + + return false; +} + +/* Render an object to text. */ +static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_item = item->child; + + if (output_buffer == NULL) { + return false; + } + + /* Compose the output: */ + length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */ + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) { + return false; + } + + *output_pointer++ = '{'; + output_buffer->depth++; + if (output_buffer->format) { + *output_pointer++ = '\n'; + } + output_buffer->offset += length; + + while (current_item) { + if (output_buffer->format) { + size_t i; + output_pointer = ensure(output_buffer, output_buffer->depth); + if (output_pointer == NULL) { + return false; + } + for (i = 0; i < output_buffer->depth; i++) { + *output_pointer++ = '\t'; + } + output_buffer->offset += output_buffer->depth; + } + + /* print key */ + if (!print_string_ptr((unsigned char *)current_item->string, output_buffer)) { + return false; + } + update_offset(output_buffer); + + length = (size_t)(output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length); + if (output_pointer == NULL) { + return false; + } + *output_pointer++ = ':'; + if (output_buffer->format) { + *output_pointer++ = '\t'; + } + output_buffer->offset += length; + + /* print value */ + if (!print_value(current_item, output_buffer)) { + return false; + } + update_offset(output_buffer); + + /* print comma if not last */ + length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) { + return false; + } + if (current_item->next) { + *output_pointer++ = ','; + } + + if (output_buffer->format) { + *output_pointer++ = '\n'; + } + *output_pointer = '\0'; + output_buffer->offset += length; + + current_item = current_item->next; + } + + output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); + if (output_pointer == NULL) { + return false; + } + if (output_buffer->format) { + size_t i; + for (i = 0; i < (output_buffer->depth - 1); i++) { + *output_pointer++ = '\t'; + } + } + *output_pointer++ = '}'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Get Array size/item / object item. */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) +{ + cJSON *child = NULL; + size_t size = 0; + + if (array == NULL) { + return 0; + } + + child = array->child; + + while (child != NULL) { + size++; + child = child->next; + } + + /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ + + return (int)size; +} + +static cJSON *get_array_item(const cJSON *array, size_t index) +{ + cJSON *current_child = NULL; + + if (array == NULL) { + return NULL; + } + + current_child = array->child; + while ((current_child != NULL) && (index > 0)) { + index--; + current_child = current_child->next; + } + + return current_child; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) +{ + if (index < 0) { + return NULL; + } + + return get_array_item(array, (size_t)index); +} + +static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) +{ + cJSON *current_element = NULL; + + if ((object == NULL) || (name == NULL)) { + return NULL; + } + + current_element = object->child; + if (case_sensitive) { + while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) { + current_element = current_element->next; + } + } + else { + while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) { + current_element = current_element->next; + } + } + + if ((current_element == NULL) || (current_element->string == NULL)) { + return NULL; + } + + return current_element; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *const object, const char *const string) +{ + return get_object_item(object, string, false); +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON *const object, const char *const string) +{ + return get_object_item(object, string, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) +{ + return cJSON_GetObjectItem(object, string) ? 1 : 0; +} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev, cJSON *item) +{ + prev->next = item; + item->prev = prev; +} + +/* Utility for handling references. */ +static cJSON *create_reference(const cJSON *item, const internal_hooks *const hooks) +{ + cJSON *reference = NULL; + if (item == NULL) { + return NULL; + } + + reference = cJSON_New_Item(hooks); + if (reference == NULL) { + return NULL; + } + + memcpy(reference, item, sizeof(cJSON)); + reference->string = NULL; + reference->type |= cJSON_IsReference; + reference->next = reference->prev = NULL; + return reference; +} + +static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) +{ + cJSON *child = NULL; + + if ((item == NULL) || (array == NULL) || (array == item)) { + return false; + } + + child = array->child; + /* + * To find the last item in array quickly, we use prev in array + */ + if (child == NULL) { + /* list is empty, start new one */ + array->child = item; + item->prev = item; + item->next = NULL; + } + else { + /* append to the end */ + if (child->prev) { + suffix_object(child->prev, item); + array->child->prev = item; + } + } + + return true; +} + +/* Add item to array/object. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) +{ + return add_item_to_array(array, item); +} + +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) +#pragma GCC diagnostic push +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif +/* helper function to cast away const */ +static void *cast_away_const(const void *string) +{ + return (void *)string; +} +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) +#pragma GCC diagnostic pop +#endif + +static cJSON_bool add_item_to_object(cJSON *const object, const char *const string, cJSON *const item, const internal_hooks *const hooks, + const cJSON_bool constant_key) +{ + char *new_key = NULL; + int new_type = cJSON_Invalid; + + if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) { + return false; + } + + if (constant_key) { + new_key = (char *)cast_away_const(string); + new_type = item->type | cJSON_StringIsConst; + } + else { + new_key = (char *)cJSON_strdup((const unsigned char *)string, hooks); + if (new_key == NULL) { + return false; + } + + new_type = item->type & ~cJSON_StringIsConst; + } + + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { + hooks->deallocate(item->string); + } + + item->string = new_key; + item->type = new_type; + + return add_item_to_array(object, item); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) +{ + return add_item_to_object(object, string, item, &global_hooks, false); +} + +/* Add an item to an object with constant string as key */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) +{ + return add_item_to_object(object, string, item, &global_hooks, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) +{ + if (array == NULL) { + return false; + } + + return add_item_to_array(array, create_reference(item, &global_hooks)); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) +{ + if ((object == NULL) || (string == NULL)) { + return false; + } + + return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); +} + +CJSON_PUBLIC(cJSON *) cJSON_AddNullToObject(cJSON *const object, const char *const name) +{ + cJSON *null = cJSON_CreateNull(); + if (add_item_to_object(object, name, null, &global_hooks, false)) { + return null; + } + + cJSON_Delete(null); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_AddTrueToObject(cJSON *const object, const char *const name) +{ + cJSON *true_item = cJSON_CreateTrue(); + if (add_item_to_object(object, name, true_item, &global_hooks, false)) { + return true_item; + } + + cJSON_Delete(true_item); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_AddFalseToObject(cJSON *const object, const char *const name) +{ + cJSON *false_item = cJSON_CreateFalse(); + if (add_item_to_object(object, name, false_item, &global_hooks, false)) { + return false_item; + } + + cJSON_Delete(false_item); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_AddBoolToObject(cJSON *const object, const char *const name, const cJSON_bool boolean) +{ + cJSON *bool_item = cJSON_CreateBool(boolean); + if (add_item_to_object(object, name, bool_item, &global_hooks, false)) { + return bool_item; + } + + cJSON_Delete(bool_item); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_AddNumberToObject(cJSON *const object, const char *const name, const double number) +{ + cJSON *number_item = cJSON_CreateNumber(number); + if (add_item_to_object(object, name, number_item, &global_hooks, false)) { + return number_item; + } + + cJSON_Delete(number_item); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_AddStringToObject(cJSON *const object, const char *const name, const char *const string) +{ + cJSON *string_item = cJSON_CreateString(string); + if (add_item_to_object(object, name, string_item, &global_hooks, false)) { + return string_item; + } + + cJSON_Delete(string_item); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_AddRawToObject(cJSON *const object, const char *const name, const char *const raw) +{ + cJSON *raw_item = cJSON_CreateRaw(raw); + if (add_item_to_object(object, name, raw_item, &global_hooks, false)) { + return raw_item; + } + + cJSON_Delete(raw_item); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_AddObjectToObject(cJSON *const object, const char *const name) +{ + cJSON *object_item = cJSON_CreateObject(); + if (add_item_to_object(object, name, object_item, &global_hooks, false)) { + return object_item; + } + + cJSON_Delete(object_item); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_AddArrayToObject(cJSON *const object, const char *const name) +{ + cJSON *array = cJSON_CreateArray(); + if (add_item_to_object(object, name, array, &global_hooks, false)) { + return array; + } + + cJSON_Delete(array); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item) +{ + if ((parent == NULL) || (item == NULL)) { + return NULL; + } + + if (item != parent->child) { + /* not the first element */ + item->prev->next = item->next; + } + if (item->next != NULL) { + /* not the last element */ + item->next->prev = item->prev; + } + + if (item == parent->child) { + /* first element */ + parent->child = item->next; + } + else if (item->next == NULL) { + /* last element */ + parent->child->prev = item->prev; + } + + /* make sure the detached item doesn't point anywhere anymore */ + item->prev = NULL; + item->next = NULL; + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) +{ + if (which < 0) { + return NULL; + } + + return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) +{ + cJSON_Delete(cJSON_DetachItemFromArray(array, which)); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItem(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObject(object, string)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); +} + +/* Replace array/object items with new ones. */ +CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *after_inserted = NULL; + + if (which < 0) { + return false; + } + + after_inserted = get_array_item(array, (size_t)which); + if (after_inserted == NULL) { + return add_item_to_array(array, newitem); + } + + newitem->next = after_inserted; + newitem->prev = after_inserted->prev; + after_inserted->prev = newitem; + if (after_inserted == array->child) { + array->child = newitem; + } + else { + newitem->prev->next = newitem; + } + return true; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement) +{ + if ((parent == NULL) || (replacement == NULL) || (item == NULL)) { + return false; + } + + if (replacement == item) { + return true; + } + + replacement->next = item->next; + replacement->prev = item->prev; + + if (replacement->next != NULL) { + replacement->next->prev = replacement; + } + if (parent->child == item) { + if (parent->child->prev == parent->child) { + replacement->prev = replacement; + } + parent->child = replacement; + } + else { /* + * To find the last item in array quickly, we use prev in array. + * We can't modify the last item's next pointer where this item was the parent's child + */ + if (replacement->prev != NULL) { + replacement->prev->next = replacement; + } + if (replacement->next == NULL) { + parent->child->prev = replacement; + } + } + + item->next = NULL; + item->prev = NULL; + cJSON_Delete(item); + + return true; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +{ + if (which < 0) { + return false; + } + + return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); +} + +static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) +{ + if ((replacement == NULL) || (string == NULL)) { + return false; + } + + /* replace the name in the replacement */ + if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) { + cJSON_free(replacement->string); + } + replacement->string = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); + replacement->type &= ~cJSON_StringIsConst; + + return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) +{ + return replace_item_in_object(object, string, newitem, false); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) +{ + return replace_item_in_object(object, string, newitem, true); +} + +/* Create basic types: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_NULL; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_True; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = boolean ? cJSON_True : cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_Number; + item->valuedouble = num; + + /* use saturation in case of overflow */ + if (num >= INT_MAX) { + item->valueint = INT_MAX; + } + else if (num <= (double)INT_MIN) { + item->valueint = INT_MIN; + } + else { + item->valueint = (int)num; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_String; + item->valuestring = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); + if (!item->valuestring) { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_String | cJSON_IsReference; + item->valuestring = (char *)cast_away_const(string); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Object | cJSON_IsReference; + item->child = (cJSON *)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Array | cJSON_IsReference; + item->child = (cJSON *)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_Raw; + item->valuestring = (char *)cJSON_strdup((const unsigned char *)raw, &global_hooks); + if (!item->valuestring) { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_Array; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_Object; + } + + return item; +} + +/* Create Arrays: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) { + n = cJSON_CreateNumber(numbers[i]); + if (!n) { + cJSON_Delete(a); + return NULL; + } + if (!i) { + a->child = n; + } + else { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) { + n = cJSON_CreateNumber((double)numbers[i]); + if (!n) { + cJSON_Delete(a); + return NULL; + } + if (!i) { + a->child = n; + } + else { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) { + n = cJSON_CreateNumber(numbers[i]); + if (!n) { + cJSON_Delete(a); + return NULL; + } + if (!i) { + a->child = n; + } + else { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (strings == NULL)) { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) { + n = cJSON_CreateString(strings[i]); + if (!n) { + cJSON_Delete(a); + return NULL; + } + if (!i) { + a->child = n; + } + else { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +/* Duplication */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) +{ + cJSON *newitem = NULL; + cJSON *child = NULL; + cJSON *next = NULL; + cJSON *newchild = NULL; + + /* Bail on bad ptr */ + if (!item) { + goto fail; + } + /* Create new item */ + newitem = cJSON_New_Item(&global_hooks); + if (!newitem) { + goto fail; + } + /* Copy over all vars */ + newitem->type = item->type & (~cJSON_IsReference); + newitem->valueint = item->valueint; + newitem->valuedouble = item->valuedouble; + if (item->valuestring) { + newitem->valuestring = (char *)cJSON_strdup((unsigned char *)item->valuestring, &global_hooks); + if (!newitem->valuestring) { + goto fail; + } + } + if (item->string) { + newitem->string = (item->type & cJSON_StringIsConst) ? item->string : (char *)cJSON_strdup((unsigned char *)item->string, &global_hooks); + if (!newitem->string) { + goto fail; + } + } + /* If non-recursive, then we're done! */ + if (!recurse) { + return newitem; + } + /* Walk the ->next chain for the child. */ + child = item->child; + while (child != NULL) { + newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) { + goto fail; + } + if (next != NULL) { + /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + next->next = newchild; + newchild->prev = next; + next = newchild; + } + else { + /* Set newitem->child and move to it */ + newitem->child = newchild; + next = newchild; + } + child = child->next; + } + if (newitem && newitem->child) { + newitem->child->prev = newchild; + } + + return newitem; + +fail: + if (newitem != NULL) { + cJSON_Delete(newitem); + } + + return NULL; +} + +static void skip_oneline_comment(char **input) +{ + *input += static_strlen("//"); + + for (; (*input)[0] != '\0'; ++(*input)) { + if ((*input)[0] == '\n') { + *input += static_strlen("\n"); + return; + } + } +} + +static void skip_multiline_comment(char **input) +{ + *input += static_strlen("/*"); + + for (; (*input)[0] != '\0'; ++(*input)) { + if (((*input)[0] == '*') && ((*input)[1] == '/')) { + *input += static_strlen("*/"); + return; + } + } +} + +static void minify_string(char **input, char **output) +{ + (*output)[0] = (*input)[0]; + *input += static_strlen("\""); + *output += static_strlen("\""); + + for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { + (*output)[0] = (*input)[0]; + + if ((*input)[0] == '\"') { + (*output)[0] = '\"'; + *input += static_strlen("\""); + *output += static_strlen("\""); + return; + } + else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { + (*output)[1] = (*input)[1]; + *input += static_strlen("\""); + *output += static_strlen("\""); + } + } +} + +CJSON_PUBLIC(void) cJSON_Minify(char *json) +{ + char *into = json; + + if (json == NULL) { + return; + } + + while (json[0] != '\0') { + switch (json[0]) { + case ' ': + case '\t': + case '\r': + case '\n': + json++; + break; + + case '/': + if (json[1] == '/') { + skip_oneline_comment(&json); + } + else if (json[1] == '*') { + skip_multiline_comment(&json); + } + else { + json++; + } + break; + + case '\"': + minify_string(&json, (char **)&into); + break; + + default: + into[0] = json[0]; + json++; + into++; + } + } + + /* and null-terminate. */ + *into = '\0'; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_Invalid; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_False; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xff) == cJSON_True; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & (cJSON_True | cJSON_False)) != 0; +} +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_NULL; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_Number; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_String; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_Array; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_Object; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_Raw; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive) +{ + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) { + return false; + } + + /* check if type is valid */ + switch (a->type & 0xFF) { + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + case cJSON_Number: + case cJSON_String: + case cJSON_Raw: + case cJSON_Array: + case cJSON_Object: + break; + + default: + return false; + } + + /* identical objects are equal */ + if (a == b) { + return true; + } + + switch (a->type & 0xFF) { + /* in these cases and equal type is enough */ + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + return true; + + case cJSON_Number: + if (compare_double(a->valuedouble, b->valuedouble)) { + return true; + } + return false; + + case cJSON_String: + case cJSON_Raw: + if ((a->valuestring == NULL) || (b->valuestring == NULL)) { + return false; + } + if (strcmp(a->valuestring, b->valuestring) == 0) { + return true; + } + + return false; + + case cJSON_Array: { + cJSON *a_element = a->child; + cJSON *b_element = b->child; + + for (; (a_element != NULL) && (b_element != NULL);) { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) { + return false; + } + + a_element = a_element->next; + b_element = b_element->next; + } + + /* one of the arrays is longer than the other */ + if (a_element != b_element) { + return false; + } + + return true; + } + + case cJSON_Object: { + cJSON *a_element = NULL; + cJSON *b_element = NULL; + cJSON_ArrayForEach(a_element, a) + { + b_element = get_object_item(b, a_element->string, case_sensitive); + if (b_element == NULL) { + return false; + } + + if (!cJSON_Compare(a_element, b_element, case_sensitive)) { + return false; + } + } + + /* doing this twice, once on a and b to prevent true comparison if a subset of b*/ + cJSON_ArrayForEach(b_element, b) + { + a_element = get_object_item(a, b_element->string, case_sensitive); + if (a_element == NULL) { + return false; + } + + if (!cJSON_Compare(b_element, a_element, case_sensitive)) { + return false; + } + } + + return true; + } + + default: + return false; + } +} + +CJSON_PUBLIC(void *) cJSON_malloc(size_t size) +{ + return global_hooks.allocate(size); +} + +CJSON_PUBLIC(void) cJSON_free(void *object) +{ + global_hooks.deallocate(object); +} diff --git a/src/cJSON.h b/src/cJSON.h new file mode 100644 index 0000000..8d4cbf3 --- /dev/null +++ b/src/cJSON.h @@ -0,0 +1,297 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) +#define __WINDOWS__ +#endif + +#ifdef __WINDOWS__ + +/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default +calling convention. For windows you have 3 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols +CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) +CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol + +For *nix builds that support visibility attribute, you can define similar behavior by + +setting default visibility to hidden by adding +-fvisibility=hidden (for gcc) +or +-xldscope=hidden (for sun cc) +to CFLAGS + +then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does + +*/ + +#define CJSON_CDECL __cdecl +#define CJSON_STDCALL __stdcall + +/* export symbols by default, this is necessary for copy pasting the C and header file */ +#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_EXPORT_SYMBOLS +#endif + +#if defined(CJSON_HIDE_SYMBOLS) +#define CJSON_PUBLIC(type) type CJSON_STDCALL +#elif defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL +#elif defined(CJSON_IMPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL +#endif +#else /* !__WINDOWS__ */ +#define CJSON_CDECL +#define CJSON_STDCALL + +#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) +#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type +#else +#define CJSON_PUBLIC(type) type +#endif +#endif + +/* project version */ +#define CJSON_VERSION_MAJOR 1 +#define CJSON_VERSION_MINOR 7 +#define CJSON_VERSION_PATCH 15 + +#include + +/* cJSON Types: */ +#define cJSON_Invalid (0) +#define cJSON_False (1 << 0) +#define cJSON_True (1 << 1) +#define cJSON_NULL (1 << 2) +#define cJSON_Number (1 << 3) +#define cJSON_String (1 << 4) +#define cJSON_Array (1 << 5) +#define cJSON_Object (1 << 6) +#define cJSON_Raw (1 << 7) /* raw json */ + +#define cJSON_IsReference 256 +#define cJSON_StringIsConst 512 + +/* The cJSON structure: */ +typedef struct cJSON { + /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *next; + struct cJSON *prev; + /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + struct cJSON *child; + + /* The type of the item, as above. */ + int type; + + /* The item's string, if type==cJSON_String and type == cJSON_Raw */ + char *valuestring; + /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ + int valueint; + /* The item's number, if type==cJSON_Number */ + double valuedouble; + + /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + char *string; +} cJSON; + +typedef struct cJSON_Hooks { + /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions + * directly. */ + void *(CJSON_CDECL *malloc_fn)(size_t sz); + void(CJSON_CDECL *free_fn)(void *ptr); +} cJSON_Hooks; + +typedef int cJSON_bool; + +/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. + * This is to prevent stack overflows. */ +#ifndef CJSON_NESTING_LIMIT +#define CJSON_NESTING_LIMIT 1000 +#endif + +/* returns the version of cJSON as a string */ +CJSON_PUBLIC(const char *) cJSON_Version(void); + +/* Supply malloc, realloc and free functions to cJSON */ +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks *hooks); + +/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib + * free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. + */ +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length); +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated); + +/* Render a cJSON entity to text for transfer/storage. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. */ +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); +/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, + * =1 gives formatted */ +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); +/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ +/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); +/* Delete a cJSON entity and all subentities. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); + +/* Returns the number of items in an array (or object). */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); +/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); +/* Get item "string" from object. Case insensitive. */ +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *const object, const char *const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON *const object, const char *const string); +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); +/* 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. */ +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); + +/* Check item type and return its value */ +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON *const item); +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item); + +/* These functions check the type of an item */ +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON *const item); + +/* These calls create a cJSON item of the appropriate type. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); +/* raw json */ +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); + +/* Create a string where valuestring references a string so + * it will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); +/* Create an object/array that only references it's elements so + * they will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); + +/* These utilities create an Array of count items. + * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count); + +/* Append item to the specified array/object. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); +/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. + * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before + * writing to `item->string` */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); +/* 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. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); + +/* Remove/Detach items from Arrays/Objects. */ +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); + +/* Update array items. */ +CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem); + +/* Duplicate a cJSON item */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will + * need to be released. With recurse!=0, it will duplicate any children connected to the item. + * The item->next and ->prev pointers are always zero on return from Duplicate. */ +/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. + * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive); + +/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings. + * The input pointer json cannot point to a read-only address area, such as a string constant, + * but should point to a readable and writable address area. */ +CJSON_PUBLIC(void) cJSON_Minify(char *json); + +/* Helper functions for creating and adding items to an object at the same time. + * They return the added item or NULL on failure. */ +CJSON_PUBLIC(cJSON *) cJSON_AddNullToObject(cJSON *const object, const char *const name); +CJSON_PUBLIC(cJSON *) cJSON_AddTrueToObject(cJSON *const object, const char *const name); +CJSON_PUBLIC(cJSON *) cJSON_AddFalseToObject(cJSON *const object, const char *const name); +CJSON_PUBLIC(cJSON *) cJSON_AddBoolToObject(cJSON *const object, const char *const name, const cJSON_bool boolean); +CJSON_PUBLIC(cJSON *) cJSON_AddNumberToObject(cJSON *const object, const char *const name, const double number); +CJSON_PUBLIC(cJSON *) cJSON_AddStringToObject(cJSON *const object, const char *const name, const char *const string); +CJSON_PUBLIC(cJSON *) cJSON_AddRawToObject(cJSON *const object, const char *const name, const char *const raw); +CJSON_PUBLIC(cJSON *) cJSON_AddObjectToObject(cJSON *const object, const char *const name); +CJSON_PUBLIC(cJSON *) cJSON_AddArrayToObject(cJSON *const object, const char *const name); + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) +/* helper for the cJSON_SetNumberValue macro */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); +#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) +/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ +CJSON_PUBLIC(char *) cJSON_SetValuestring(cJSON *object, const char *valuestring); + +/* Macro for iterating over an array or object */ +#define cJSON_ArrayForEach(element, array) for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) + +/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ +CJSON_PUBLIC(void *) cJSON_malloc(size_t size); +CJSON_PUBLIC(void) cJSON_free(void *object); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/cfg.cpp b/src/cfg.cpp new file mode 100644 index 0000000..06bf27f --- /dev/null +++ b/src/cfg.cpp @@ -0,0 +1,1329 @@ +// config functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include +#include + +#include "config.h" +#include "gettext.h" + +#include "cfg.h" +#include "butt.h" +#include "flgui.h" +#include "util.h" +#include "fl_funcs.h" +#include "strfuncs.h" +#include "port_midi.h" + +#ifdef WIN32 +const char CONFIG_FILE[] = "buttrc"; +#else +const char CONFIG_FILE[] = ".buttrc"; +#endif + +const char *lang_array_new[] = {"system", "ar", "de", "en", "es", "fr", "nl", "pt_BR"}; +const char *lang_array_old[] = {"system", "de", "en", "fr", "pt_BR"}; + +config_t cfg; +char *cfg_path; + +int cfg_write_file(char *path) +{ + int i; + FILE *cfg_fd; + char info_buf[256]; + + if (path == NULL) { + path = cfg_path; + } + + cfg_fd = fl_fopen(path, "wb"); + if (cfg_fd == NULL) { + snprintf(info_buf, sizeof(info_buf), _("Could not write to file: %s"), path); + print_info(cfg_path, 1); + return 1; + } + + fprintf(cfg_fd, "#This is a configuration file for butt (broadcast using this tool)\n\n"); + fprintf(cfg_fd, "[main]\n"); + + fprintf(cfg_fd, "bg_color = %d\n", cfg.main.bg_color); + fprintf(cfg_fd, "txt_color = %d\n", cfg.main.txt_color); + + if (cfg.main.num_of_srv > 0) { + fprintf(cfg_fd, + "server = %s\n" + "srv_ent = %s\n", + cfg.main.srv, cfg.main.srv_ent); + } + else { + fprintf(cfg_fd, "server = \n" + "srv_ent = \n"); + } + + if (cfg.main.num_of_icy > 0) { + fprintf(cfg_fd, + "icy = %s\n" + "icy_ent = %s\n", + cfg.main.icy, cfg.main.icy_ent); + } + else { + fprintf(cfg_fd, "icy = \n" + "icy_ent = \n"); + } + + fprintf(cfg_fd, + "num_of_srv = %d\n" + "num_of_icy = %d\n", + cfg.main.num_of_srv, cfg.main.num_of_icy); + + fprintf(cfg_fd, "song_update_url_active = %d\n", cfg.main.song_update_url_active); + fprintf(cfg_fd, "song_update_url_interval = %d\n", cfg.main.song_update_url_interval); + + if (cfg.main.song_update_url != NULL) { + fprintf(cfg_fd, "song_update_url = %s\n", cfg.main.song_update_url); + } + else { + fprintf(cfg_fd, "song_update_url =\n"); + } + + if (cfg.main.song_path != NULL) { + fprintf(cfg_fd, "song_path = %s\n", cfg.main.song_path); + } + else { + fprintf(cfg_fd, "song_path = \n"); + } + + fprintf(cfg_fd, "song_update = %d\n", cfg.main.song_update); + fprintf(cfg_fd, "song_delay = %d\n", cfg.main.song_delay); + + if (cfg.main.song_prefix != NULL) { + char *tmp = strdup(cfg.main.song_prefix); + strrpl(&tmp, (char *)" ", (char *)"%20", MODE_ALL); + fprintf(cfg_fd, "song_prefix = %s\n", tmp); + free(tmp); + } + else + fprintf(cfg_fd, "song_prefix = \n"); + + if (cfg.main.song_suffix != NULL) { + char *tmp = strdup(cfg.main.song_suffix); + strrpl(&tmp, (char *)" ", (char *)"%20", MODE_ALL); + fprintf(cfg_fd, "song_suffix = %s\n", tmp); + free(tmp); + } + else + fprintf(cfg_fd, "song_suffix = \n"); + + fprintf(cfg_fd, "read_last_line = %d\n", cfg.main.read_last_line); + + fprintf(cfg_fd, "app_update_service = %d\n", cfg.main.app_update_service); + fprintf(cfg_fd, "app_update = %d\n", cfg.main.app_update); + fprintf(cfg_fd, "app_artist_title_order = %d\n", cfg.main.app_artist_title_order); + + fprintf(cfg_fd, "gain = %f\n", cfg.main.gain); + + fprintf(cfg_fd, "signal_threshold = %f\n", cfg.main.signal_threshold); + fprintf(cfg_fd, "silence_threshold = %f\n", cfg.main.silence_threshold); + fprintf(cfg_fd, "signal_detection = %d\n", cfg.main.signal_detection); + fprintf(cfg_fd, "silence_detection = %d\n", cfg.main.silence_detection); + fprintf(cfg_fd, "check_for_update = %d\n", cfg.main.check_for_update); + fprintf(cfg_fd, "start_agent = %d\n", cfg.main.start_agent); + fprintf(cfg_fd, "minimize_to_tray = %d\n", cfg.main.minimize_to_tray); + fprintf(cfg_fd, "connect_at_startup = %d\n", cfg.main.connect_at_startup); + fprintf(cfg_fd, "force_reconnecting = %d\n", cfg.main.force_reconnecting); + fprintf(cfg_fd, "reconnect_delay = %d\n", cfg.main.reconnect_delay); + + if (cfg.main.ic_charset != NULL) { + fprintf(cfg_fd, "ic_charset = %s\n", cfg.main.ic_charset); + } + else { + fprintf(cfg_fd, "ic_charset = \n"); + } + + if (cfg.main.log_file != NULL) { + fprintf(cfg_fd, "log_file = %s\n\n", cfg.main.log_file); + } + else { + fprintf(cfg_fd, "log_file = \n\n"); + } + + fprintf(cfg_fd, + "[audio]\n" + "device = %d\n" + "device2 = %d\n" + "dev_remember = %d\n" + "samplerate = %d\n" + "bitrate = %d\n" + "channel = %d\n" + "left_ch = %d\n" + "right_ch = %d\n" + "left_ch2 = %d\n" + "right_ch2 = %d\n" + "codec = %s\n" + "resample_mode = %d\n" + "silence_level = %f\n" + "signal_level = %f\n" + "disable_dithering = %d\n" + "buffer_ms = %d\n", + cfg.audio.dev_num, cfg.audio.dev2_num, cfg.audio.dev_remember, cfg.audio.samplerate, cfg.audio.bitrate, cfg.audio.channel, cfg.audio.left_ch, + cfg.audio.right_ch, cfg.audio.left_ch2, cfg.audio.right_ch2, cfg.audio.codec, cfg.audio.resample_mode, cfg.audio.silence_level, + cfg.audio.signal_level, cfg.audio.disable_dithering, cfg.audio.buffer_ms); + + if (cfg.audio.dev_name != NULL) { + fprintf(cfg_fd, "dev_name = %s\n", cfg.audio.dev_name); + } + else { + fprintf(cfg_fd, "dev_name = \n"); + } + + if (cfg.audio.dev2_name != NULL) { + fprintf(cfg_fd, "dev2_name = %s\n\n", cfg.audio.dev2_name); + } + else { + fprintf(cfg_fd, "dev2_name = \n\n"); + } + + fprintf(cfg_fd, + "[record]\n" + "bitrate = %d\n" + "codec = %s\n" + "start_rec = %d\n" + "stop_rec = %d\n" + "rec_after_launch = %d\n" + "overwrite_files = %d\n" + "sync_to_hour = %d\n" + "split_time = %d\n" + "filename = %s\n" + "signal_threshold = %f\n" + "silence_threshold = %f\n" + "signal_detection = %d\n" + "silence_detection = %d\n" + "folder = %s\n\n", + cfg.rec.bitrate, cfg.rec.codec, cfg.rec.start_rec, cfg.rec.stop_rec, cfg.rec.rec_after_launch, cfg.rec.overwrite_files, cfg.rec.sync_to_hour, + cfg.rec.split_time, cfg.rec.filename, cfg.rec.signal_threshold, cfg.rec.silence_threshold, cfg.rec.signal_detection, cfg.rec.silence_detection, + cfg.rec.folder); + + fprintf(cfg_fd, + "[tls]\n" + "cert_file = %s\n" + "cert_dir = %s\n\n", + cfg.tls.cert_file != NULL ? cfg.tls.cert_file : "", cfg.tls.cert_dir != NULL ? cfg.tls.cert_dir : ""); + + fprintf(cfg_fd, + "[dsp]\n" + "equalizer = %d\n" + "equalizer_rec = %d\n" + "eq_preset = %s\n" + "gain1 = %f\n" + "gain2 = %f\n" + "gain3 = %f\n" + "gain4 = %f\n" + "gain5 = %f\n" + "gain6 = %f\n" + "gain7 = %f\n" + "gain8 = %f\n" + "gain9 = %f\n" + "gain10 = %f\n" + "compressor = %d\n" + "compressor_rec = %d\n" + "aggressive_mode = %d\n" + "threshold = %f\n" + "ratio = %f\n" + "attack = %f\n" + "release = %f\n" + "makeup_gain = %f\n\n", + cfg.dsp.equalizer_stream, cfg.dsp.equalizer_rec, cfg.dsp.eq_preset, cfg.dsp.eq_gain[0], cfg.dsp.eq_gain[1], cfg.dsp.eq_gain[2], cfg.dsp.eq_gain[3], + cfg.dsp.eq_gain[4], cfg.dsp.eq_gain[5], cfg.dsp.eq_gain[6], cfg.dsp.eq_gain[7], cfg.dsp.eq_gain[8], cfg.dsp.eq_gain[9], cfg.dsp.compressor_stream, + cfg.dsp.compressor_rec, cfg.dsp.aggressive_mode, cfg.dsp.threshold, cfg.dsp.ratio, cfg.dsp.attack, cfg.dsp.release, cfg.dsp.makeup_gain); + + fprintf(cfg_fd, + "[mixer]\n" + "primary_device_gain = %f\n" + "primary_device_muted = %d\n" + "secondary_device_gain = %f\n" + "secondary_device_muted = %d\n" + "streaming_gain = %f\n" + "recording_gain = %f\n" + "cross_fader = %f\n\n", + cfg.mixer.primary_device_gain, cfg.mixer.primary_device_muted, cfg.mixer.secondary_device_gain, cfg.mixer.secondary_device_muted, + cfg.mixer.streaming_gain, cfg.mixer.recording_gain, cfg.mixer.cross_fader); + + fprintf(cfg_fd, + "[gui]\n" + "attach = %d\n" + "ontop = %d\n" + "hide_log_window = %d\n" + "remember_pos = %d\n" + "x_pos = %d\n" + "y_pos = %d\n" + "window_height = %d\n" + "lcd_auto = %d\n" + "default_stream_info = %d\n" + "start_minimized = %d\n" + "disable_gain_slider = %d\n" + "show_listeners = %d\n" + "listeners_update_rate = %d\n" + "lang_str = %s\n" + "vu_low_color = %d\n" + "vu_mid_color = %d\n" + "vu_high_color = %d\n" + "vu_mid_range_start = %d\n" + "vu_high_range_start = %d\n" + "always_show_vu_tabs = %d\n" + "window_title = %s\n" + "vu_mode = %d\n\n", + cfg.gui.attach, cfg.gui.ontop, cfg.gui.hide_log_window, cfg.gui.remember_pos, cfg.gui.x_pos, cfg.gui.y_pos, cfg.gui.window_height, cfg.gui.lcd_auto, + cfg.gui.default_stream_info, cfg.gui.start_minimized, cfg.gui.disable_gain_slider, cfg.gui.show_listeners, cfg.gui.listeners_update_rate, + cfg.gui.lang_str, cfg.gui.vu_low_color, cfg.gui.vu_mid_color, cfg.gui.vu_high_color, cfg.gui.vu_mid_range_start, cfg.gui.vu_high_range_start, + cfg.gui.always_show_vu_tabs, cfg.gui.window_title, cfg.gui.vu_mode); + + fprintf(cfg_fd, + "[mp3_codec_stream]\n" + "enc_quality = %d\n" + "stereo_mode = %d\n" + "bitrate_mode = %d\n" + "vbr_quality = %d\n" + "vbr_min_bitrate = %d\n" + "vbr_max_bitrate = %d\n" + "vbr_force_min_bitrate = %d\n" + "resampling_freq = %d\n" + "lowpass_freq_active = %d\n" + "lowpass_freq = %f\n" + "lowpass_width_active = %d\n" + "lowpass_width = %f\n" + "highpass_freq_active = %d\n" + "highpass_freq = %f\n" + "highpass_width_active = %d\n" + "highpass_width = %f\n\n", + cfg.mp3_codec_stream.enc_quality, cfg.mp3_codec_stream.stereo_mode, cfg.mp3_codec_stream.bitrate_mode, cfg.mp3_codec_stream.vbr_quality, + cfg.mp3_codec_stream.vbr_min_bitrate, cfg.mp3_codec_stream.vbr_max_bitrate, cfg.mp3_codec_stream.vbr_force_min_bitrate, + cfg.mp3_codec_stream.resampling_freq, cfg.mp3_codec_stream.lowpass_freq_active, cfg.mp3_codec_stream.lowpass_freq, + cfg.mp3_codec_stream.lowpass_width_active, cfg.mp3_codec_stream.lowpass_width, cfg.mp3_codec_stream.highpass_freq_active, + cfg.mp3_codec_stream.highpass_freq, cfg.mp3_codec_stream.highpass_width_active, cfg.mp3_codec_stream.highpass_width); + + fprintf(cfg_fd, + "[mp3_codec_rec]\n" + "enc_quality = %d\n" + "stereo_mode = %d\n" + "bitrate_mode = %d\n" + "vbr_quality = %d\n" + "vbr_min_bitrate = %d\n" + "vbr_max_bitrate = %d\n" + "vbr_force_min_bitrate = %d\n" + "resampling_freq = %d\n" + "lowpass_freq_active = %d\n" + "lowpass_freq = %f\n" + "lowpass_width_active = %d\n" + "lowpass_width = %f\n" + "highpass_freq_active = %d\n" + "highpass_freq = %f\n" + "highpass_width_active = %d\n" + "highpass_width = %f\n\n", + cfg.mp3_codec_rec.enc_quality, cfg.mp3_codec_rec.stereo_mode, cfg.mp3_codec_rec.bitrate_mode, cfg.mp3_codec_rec.vbr_quality, + cfg.mp3_codec_rec.vbr_min_bitrate, cfg.mp3_codec_rec.vbr_max_bitrate, cfg.mp3_codec_rec.vbr_force_min_bitrate, cfg.mp3_codec_rec.resampling_freq, + cfg.mp3_codec_rec.lowpass_freq_active, cfg.mp3_codec_rec.lowpass_freq, cfg.mp3_codec_rec.lowpass_width_active, cfg.mp3_codec_rec.lowpass_width, + cfg.mp3_codec_rec.highpass_freq_active, cfg.mp3_codec_rec.highpass_freq, cfg.mp3_codec_rec.highpass_width_active, cfg.mp3_codec_rec.highpass_width); + + fprintf(cfg_fd, + "[vorbis_codec_stream]\n" + "bitrate_mode = %d\n" + "vbr_quality = %d\n" + "vbr_min_bitrate = %d\n" + "vbr_max_bitrate = %d\n\n", + cfg.vorbis_codec_stream.bitrate_mode, cfg.vorbis_codec_stream.vbr_quality, cfg.vorbis_codec_stream.vbr_min_bitrate, + cfg.vorbis_codec_stream.vbr_max_bitrate); + + fprintf(cfg_fd, + "[vorbis_codec_rec]\n" + "bitrate_mode = %d\n" + "vbr_quality = %d\n" + "vbr_min_bitrate = %d\n" + "vbr_max_bitrate = %d\n\n", + cfg.vorbis_codec_rec.bitrate_mode, cfg.vorbis_codec_rec.vbr_quality, cfg.vorbis_codec_rec.vbr_min_bitrate, cfg.vorbis_codec_rec.vbr_max_bitrate); + + fprintf(cfg_fd, + "[opus_codec_stream]\n" + "bitrate_mode = %d\n" + "quality = %d\n" + "audio_type = %d\n" + "bandwidth = %d\n\n", + cfg.opus_codec_stream.bitrate_mode, cfg.opus_codec_stream.quality, cfg.opus_codec_stream.audio_type, cfg.opus_codec_stream.bandwidth); + + fprintf(cfg_fd, + "[opus_codec_rec]\n" + "bitrate_mode = %d\n" + "quality = %d\n" + "audio_type = %d\n" + "bandwidth = %d\n\n", + cfg.opus_codec_rec.bitrate_mode, cfg.opus_codec_rec.quality, cfg.opus_codec_rec.audio_type, cfg.opus_codec_rec.bandwidth); + + fprintf(cfg_fd, + "[aac_codec_stream]\n" + "bitrate_mode = %d\n" + "afterburner = %d\n" + "profile = %d\n\n", + cfg.aac_codec_stream.bitrate_mode, cfg.aac_codec_stream.afterburner, cfg.aac_codec_stream.profile); + + fprintf(cfg_fd, + "[aac_codec_rec]\n" + "bitrate_mode = %d\n" + "afterburner = %d\n" + "profile = %d\n\n", + cfg.aac_codec_rec.bitrate_mode, cfg.aac_codec_rec.afterburner, cfg.aac_codec_rec.profile); + + fprintf(cfg_fd, + "[flac_codec_stream]\n" + "bit_depth = %d\n\n", + cfg.flac_codec_stream.bit_depth); + + fprintf(cfg_fd, + "[flac_codec_rec]\n" + "bit_depth = %d\n\n", + cfg.flac_codec_rec.bit_depth); + + fprintf(cfg_fd, + "[wav_codec_rec]\n" + "bit_depth = %d\n\n", + cfg.wav_codec_rec.bit_depth); + + fprintf(cfg_fd, + "[midi]\n" + "dev_name = %s\n\n", + cfg.midi.dev_name); + + for (i = 0; i < MIDI_COMMANDS_COUNT; i++) { + fprintf(cfg_fd, + "[midi_cmd_%u]\n" + "enabled = %u\n" + "channel = %u\n" + "msg_num = %u\n" + "msg_type = %u\n" + "mode = %u\n" + "soft_takeover = %u\n\n", + i, cfg.midi.commands[i].enabled, cfg.midi.commands[i].channel, cfg.midi.commands[i].msg_num, cfg.midi.commands[i].msg_type, + cfg.midi.commands[i].mode, cfg.midi.commands[i].soft_takeover); + } + + for (i = 0; i < cfg.main.num_of_srv; i++) { + if (cfg.srv[i]->type != WEBRTC) { + fprintf(cfg_fd, + "[%s]\n" + "address = %s\n" + "port = %u\n" + "password = %s\n" + "type = %d\n" + "tls = %d\n", + cfg.srv[i]->name, cfg.srv[i]->addr, cfg.srv[i]->port, cfg.srv[i]->pwd, cfg.srv[i]->type, cfg.srv[i]->tls); + } + else { // WEBRTC + fprintf(cfg_fd, + "[%s]\n" + "address = (none)\n" + "port = 0\n" + "password = (none)\n" + "type = %d\n" + "tls = 0\n", + cfg.srv[i]->name, WEBRTC); + } + + if (cfg.srv[i]->custom_listener_url != NULL) { + fprintf(cfg_fd, "custom_listener_url = %s\n", cfg.srv[i]->custom_listener_url); + } + else { + fprintf(cfg_fd, "custom_listener_url = \n"); + } + + if (cfg.srv[i]->custom_listener_mount != NULL) { + fprintf(cfg_fd, "custom_listener_mount = %s\n", cfg.srv[i]->custom_listener_mount); + } + else { + fprintf(cfg_fd, "custom_listener_mount = \n"); + } + + if (cfg.srv[i]->cert_hash != NULL) { + fprintf(cfg_fd, "cert_hash = %s\n", cfg.srv[i]->cert_hash); + } + else { + fprintf(cfg_fd, "cert_hash = \n"); + } + + if (cfg.srv[i]->type == ICECAST) { + fprintf(cfg_fd, "mount = %s\n", cfg.srv[i]->mount); + fprintf(cfg_fd, "usr = %s\n", cfg.srv[i]->usr); + fprintf(cfg_fd, "protocol = %d\n", cfg.srv[i]->icecast_protocol); + } + else { // Shoutcast has no mountpoint and user + fprintf(cfg_fd, "mount = (none)\n"); + fprintf(cfg_fd, "usr = (none)\n"); + } + + if (cfg.srv[i]->type == WEBRTC) { + if (cfg.srv[i]->webrtc_ice != NULL && strlen(cfg.srv[i]->webrtc_ice) > 0) { + fprintf(cfg_fd, "webrtc_ice = %s\n", cfg.srv[i]->webrtc_ice); + } + else { + fprintf(cfg_fd, "webrtc_ice = \n"); + } + + fprintf(cfg_fd, "webrtc_whip = %s\n", cfg.srv[i]->webrtc_whip); + + if (cfg.srv[i]->webrtc_auth != NULL && strlen(cfg.srv[i]->webrtc_auth) > 0) { + fprintf(cfg_fd, "webrtc_auth = %s\n\n", cfg.srv[i]->webrtc_auth); + } + else { + fprintf(cfg_fd, "webrtc_auth = \n\n"); + } + } + else { + fprintf(cfg_fd, "\n"); + } + } + + for (i = 0; i < cfg.main.num_of_icy; i++) { + fprintf(cfg_fd, + "[%s]\n" + "expand_variables = %d\n" + "pub = %s\n", + cfg.icy[i]->name, // + cfg.icy[i]->expand_variables, // + cfg.icy[i]->pub); + + if (cfg.icy[i]->desc != NULL) { + fprintf(cfg_fd, "description = %s\n", cfg.icy[i]->desc); + } + else { + fprintf(cfg_fd, "description = \n"); + } + + if (cfg.icy[i]->genre != NULL) { + fprintf(cfg_fd, "genre = %s\n", cfg.icy[i]->genre); + } + else { + fprintf(cfg_fd, "genre = \n"); + } + + if (cfg.icy[i]->url != NULL) { + fprintf(cfg_fd, "url = %s\n", cfg.icy[i]->url); + } + else { + fprintf(cfg_fd, "url = \n"); + } + + if (cfg.icy[i]->irc != NULL) { + fprintf(cfg_fd, "irc = %s\n", cfg.icy[i]->irc); + } + else { + fprintf(cfg_fd, "irc = \n"); + } + + if (cfg.icy[i]->icq != NULL) { + fprintf(cfg_fd, "icq = %s\n", cfg.icy[i]->icq); + } + else { + fprintf(cfg_fd, "icq = \n"); + } + + if (cfg.icy[i]->aim != NULL) { + fprintf(cfg_fd, "aim = %s\n\n", cfg.icy[i]->aim); + } + else { + fprintf(cfg_fd, "aim = \n\n"); + } + } + + fclose(cfg_fd); + + snprintf(info_buf, sizeof(info_buf), _("Config written to %s"), path); + print_info(info_buf, 0); + + return 0; +} + +int cfg_set_values(char *path) +{ + int i; + char *srv_ent; + char *icy_ent; + char *strtok_buf = NULL; + + if (path == NULL) { + path = cfg_path; + } + + if (cfg_parse_file(path) == -1) { + DEBUG_LOG("Parsing config failed"); + return 1; + } + + cfg.main.log_file = cfg_get_str("main", "log_file", NULL); + cfg.main.ic_charset = cfg_get_str("main", "ic_charset", NULL); + cfg.audio.pcm_list = snd_get_devices(&cfg.audio.dev_count); + cfg.audio.dev_num = cfg_get_int("audio", "device", 0); + cfg.audio.dev2_num = cfg_get_int("audio", "device2", -1); + cfg.audio.dev_name = cfg_get_str("audio", "dev_name", _("Default PCM device (default)")); + cfg.audio.dev2_name = cfg_get_str("audio", "dev2_name", _("None")); + cfg.audio.dev_remember = cfg_get_int("audio", "dev_remember", REMEMBER_BY_NAME); + cfg.audio.samplerate = cfg_get_int("audio", "samplerate", 44100); + cfg.audio.resolution = 16; + cfg.audio.bitrate = cfg_get_int("audio", "bitrate", 128); + cfg.audio.channel = cfg_get_int("audio", "channel", 2); + cfg.audio.left_ch = cfg_get_int("audio", "left_ch", 1); + cfg.audio.right_ch = cfg_get_int("audio", "right_ch", 2); + cfg.audio.left_ch2 = cfg_get_int("audio", "left_ch2", 1); + cfg.audio.right_ch2 = cfg_get_int("audio", "right_ch2", 2); + cfg.audio.buffer_ms = cfg_get_int("audio", "buffer_ms", 50); + cfg.audio.disable_dithering = cfg_get_int("audio", "disable_dithering", 0); + cfg.audio.resample_mode = cfg_get_int("audio", "resample_mode", 0); // 0 = SRC_SINC_BEST_QUALITY + + cfg.audio.codec = cfg_get_str("audio", "codec", "mp3"); + // Make sure that also "opus" and "flac" fit into the codec char array + cfg.audio.codec = (char *)realloc((char *)cfg.audio.codec, 5 * sizeof(char)); + + if (!strcmp(cfg.audio.codec, "aac") && g_aac_lib_available == 0) { + strcpy(cfg.audio.codec, "mp3"); + } + + // Will be interpreted as negative value (-50 dB) + cfg.audio.silence_level = cfg_get_float("audio", "silence_level", 50.0); + cfg.audio.signal_level = cfg_get_float("audio", "signal_level", 50.0); + + cfg.rec.bitrate = cfg_get_int("record", "bitrate", 192); + cfg.rec.start_rec = cfg_get_int("record", "start_rec", 0); + cfg.rec.stop_rec = cfg_get_int("record", "stop_rec", 0); + cfg.rec.rec_after_launch = cfg_get_int("record", "rec_after_launch", 0); + cfg.rec.overwrite_files = cfg_get_int("record", "overwrite_files", 0); + cfg.rec.sync_to_hour = cfg_get_int("record", "sync_to_hour", 0); + cfg.rec.split_time = cfg_get_int("record", "split_time", 0); + cfg.rec.filename = cfg_get_str("record", "filename", "rec_%Y%m%d-%H%M%S_%i.mp3"); + cfg.rec.signal_threshold = cfg_get_float("record", "signal_threshold", 0); + cfg.rec.silence_threshold = cfg_get_float("record", "silence_threshold", 0); + cfg.rec.signal_detection = cfg_get_int("record", "signal_detection", -1); + cfg.rec.silence_detection = cfg_get_int("record", "silence_detection", -1); + + // Backwards compatibility with versions < 0.1.41 + if (cfg.rec.signal_detection == -1) { + cfg.rec.signal_detection = cfg.rec.signal_threshold > 0 ? 1 : 0; + } + if (cfg.rec.silence_detection == -1) { + cfg.rec.silence_detection = cfg.rec.silence_threshold > 0 ? 1 : 0; + } + + cfg.rec.codec = cfg_get_str("record", "codec", "mp3"); + // Make sure that also "opus" and "flac" fit into the codec char array + cfg.rec.codec = (char *)realloc((char *)cfg.rec.codec, 5 * sizeof(char)); + + if (!strcmp(cfg.rec.codec, "aac") && g_aac_lib_available == 0) { + strcpy(cfg.rec.codec, "mp3"); + } + + cfg.rec.path = NULL; // Set to NULL, button_record_cb() may use realloc() + cfg.rec.folder = cfg_get_str("record", "folder", NULL); + if (cfg.rec.folder == NULL) { + char *p; + cfg.rec.folder = (char *)malloc(PATH_MAX * sizeof(char)); +#ifdef WIN32 + p = fl_getenv("USERPROFILE"); + if (p != NULL) { + snprintf(cfg.rec.folder, PATH_MAX, "%s\\Music\\", p); + } + else { + snprintf(cfg.rec.folder, PATH_MAX, "./"); + } +#elif __APPLE__ + p = fl_getenv("HOME"); + if (p != NULL) { + snprintf(cfg.rec.folder, PATH_MAX, "%s/Music/", p); + } + else { + snprintf(cfg.rec.folder, PATH_MAX, "~/"); + } +#else // UNIX + p = fl_getenv("HOME"); + if (p != NULL) { + snprintf(cfg.rec.folder, PATH_MAX, "%s/", p); + } + else { + snprintf(cfg.rec.folder, PATH_MAX, "~/"); + } +#endif + } + + cfg.tls.cert_file = cfg_get_str("tls", "cert_file", NULL); + cfg.tls.cert_dir = cfg_get_str("tls", "cert_dir", NULL); + + cfg.selected_srv = 0; + + cfg.main.num_of_srv = cfg_get_int("main", "num_of_srv", 0); + if (cfg.main.num_of_srv > 0) { + cfg.main.srv = cfg_get_str("main", "server", NULL); + if (cfg.main.srv == NULL) { + fl_alert(_("error while parsing config. Missing main/server entry.\nbutt will start with default settings")); + return 1; + } + + cfg.main.srv_ent = cfg_get_str("main", "srv_ent", NULL); + if (cfg.main.srv_ent == NULL) { + fl_alert(_("error while parsing config. Missing main/srv_ent entry.\nbutt will start with default settings")); + return 1; + } + + cfg.srv = (server_t **)malloc(sizeof(server_t *) * cfg.main.num_of_srv); + + for (i = 0; i < cfg.main.num_of_srv; i++) { + cfg.srv[i] = (server_t *)malloc(sizeof(server_t)); + } + + strtok_buf = strdup(cfg.main.srv_ent); + srv_ent = strtok(strtok_buf, ";"); + + for (i = 0; srv_ent != NULL; i++) { + cfg.srv[i]->name = (char *)malloc(strlen(srv_ent) + 1); + snprintf(cfg.srv[i]->name, strlen(srv_ent) + 1, "%s", srv_ent); + + cfg.srv[i]->type = cfg_get_int(srv_ent, "type", -1); + if (cfg.srv[i]->type == -1) { + fl_alert(_("error while parsing config. Missing type entry for server \"%s\"." + "\nbutt will start with default settings"), + srv_ent); + return 1; + } + + cfg.srv[i]->addr = cfg_get_str(srv_ent, "address", NULL); + if ((cfg.srv[i]->addr) == NULL && (cfg.srv[i]->type != WEBRTC)) { + fl_alert(_("error while parsing config. Missing address entry for server \"%s\"." + "\nbutt will start with default settings"), + srv_ent); + free(strtok_buf); + return 1; + } + + cfg.srv[i]->port = cfg_get_int(srv_ent, "port", -1); + if ((cfg.srv[i]->port) == -1 && (cfg.srv[i]->type != WEBRTC)) { + fl_alert(_("error while parsing config. Missing port entry for server \"%s\"." + "\nbutt will start with default settings"), + srv_ent); + free(strtok_buf); + return 1; + } + + cfg.srv[i]->pwd = cfg_get_str(srv_ent, "password", NULL); + if ((cfg.srv[i]->pwd == NULL) && (cfg.srv[i]->type != WEBRTC)) { + fl_alert(_("error while parsing config. Missing password entry for server \"%s\"." + "\nbutt will start with default settings"), + srv_ent); + free(strtok_buf); + return 1; + } + + cfg.srv[i]->mount = cfg_get_str(srv_ent, "mount", NULL); + if ((cfg.srv[i]->mount == NULL) && (cfg.srv[i]->type == ICECAST)) { + fl_alert(_("error while parsing config. Missing mount entry for server \"%s\"." + "\nbutt will start with default settings"), + srv_ent); + free(strtok_buf); + return 1; + } + + cfg.srv[i]->usr = cfg_get_str(srv_ent, "usr", NULL); + if ((cfg.srv[i]->usr == NULL) && (cfg.srv[i]->type == ICECAST)) { + cfg.srv[i]->usr = (char *)malloc(strlen("source") + 1); + strcpy(cfg.srv[i]->usr, "source"); + } + + cfg.srv[i]->webrtc_ice = cfg_get_str(srv_ent, "webrtc_ice", NULL); + + cfg.srv[i]->webrtc_whip = cfg_get_str(srv_ent, "webrtc_whip", NULL); + if ((cfg.srv[i]->webrtc_whip == NULL) && (cfg.srv[i]->type == WEBRTC)) { + cfg.srv[i]->webrtc_whip = (char *)malloc(strlen("(none)") + 1); + strcpy(cfg.srv[i]->webrtc_whip, "(none)"); + } + + cfg.srv[i]->webrtc_auth = cfg_get_str(srv_ent, "webrtc_auth", NULL); + cfg.srv[i]->icecast_protocol = cfg_get_int(srv_ent, "protocol", ICECAST_PROTOCOL_PUT); + +#ifdef HAVE_LIBSSL + cfg.srv[i]->tls = cfg_get_int(srv_ent, "tls", 0); +#else + cfg.srv[i]->tls = 0; +#endif + cfg.srv[i]->cert_hash = cfg_get_str(srv_ent, "cert_hash", NULL); + if ((cfg.srv[i]->cert_hash != NULL) && (strlen(cfg.srv[i]->cert_hash) != 64)) { + free(cfg.srv[i]->cert_hash); + cfg.srv[i]->cert_hash = NULL; + } + + if (!strcmp(cfg.srv[i]->name, cfg.main.srv)) { + cfg.selected_srv = i; + } + + cfg.srv[i]->custom_listener_url = cfg_get_str(srv_ent, "custom_listener_url", NULL); + cfg.srv[i]->custom_listener_mount = cfg_get_str(srv_ent, "custom_listener_mount", NULL); + + srv_ent = strtok(NULL, ";"); + } + free(strtok_buf); + } // if(cfg.main.num_of_srv > 0) + else { + cfg.main.srv = NULL; + } + + cfg.main.num_of_icy = cfg_get_int("main", "num_of_icy", 0); + + cfg.selected_icy = 0; + if (cfg.main.num_of_icy > 0) { + cfg.main.icy = cfg_get_str("main", "icy", NULL); + if (cfg.main.icy == NULL) { + fl_alert(_("error while parsing config. Missing main/icy entry.\nbutt will start with default settings")); + return 1; + } + cfg.main.icy_ent = cfg_get_str("main", "icy_ent", NULL); // icy entries + if (cfg.main.icy_ent == NULL) { + fl_alert(_("error while parsing config. Missing main/icy_ent entry.\nbutt will start with default settings")); + return 1; + } + + cfg.icy = (icy_t **)malloc(sizeof(icy_t *) * cfg.main.num_of_icy); + + for (i = 0; i < cfg.main.num_of_icy; i++) { + cfg.icy[i] = (icy_t *)malloc(sizeof(icy_t)); + } + + strtok_buf = strdup(cfg.main.icy_ent); + icy_ent = strtok(strtok_buf, ";"); + + for (i = 0; icy_ent != NULL; i++) { + cfg.icy[i]->name = (char *)malloc(strlen(icy_ent) + 1); + snprintf(cfg.icy[i]->name, strlen(icy_ent) + 1, "%s", icy_ent); + + cfg.icy[i]->desc = cfg_get_str(icy_ent, "description", NULL); + cfg.icy[i]->genre = cfg_get_str(icy_ent, "genre", NULL); + cfg.icy[i]->url = cfg_get_str(icy_ent, "url", NULL); + cfg.icy[i]->irc = cfg_get_str(icy_ent, "irc", NULL); + cfg.icy[i]->icq = cfg_get_str(icy_ent, "icq", NULL); + cfg.icy[i]->aim = cfg_get_str(icy_ent, "aim", NULL); + cfg.icy[i]->pub = cfg_get_str(icy_ent, "pub", NULL); + cfg.icy[i]->expand_variables = cfg_get_int(icy_ent, "expand_variables", 0); + if (cfg.icy[i]->pub == NULL) { + fl_alert(_("error while parsing config. Missing pub entry for icy \"%s\"." + "\nbutt will start with default settings"), + icy_ent); + free(strtok_buf); + return 1; + } + + if (!strcmp(cfg.icy[i]->name, cfg.main.icy)) { + cfg.selected_icy = i; + } + + icy_ent = strtok(NULL, ";"); + } + free(strtok_buf); + } // if(cfg.main.num_of_icy > 0) + else { + cfg.main.icy = NULL; + } + + cfg.main.song_path = cfg_get_str("main", "song_path", NULL); + + cfg.main.song_prefix = cfg_get_str("main", "song_prefix", NULL); + if (cfg.main.song_prefix != NULL) { + strrpl(&cfg.main.song_prefix, (char *)"%20", (char *)" ", MODE_ALL); + } + + cfg.main.song_suffix = cfg_get_str("main", "song_suffix", NULL); + if (cfg.main.song_suffix != NULL) { + strrpl(&cfg.main.song_suffix, (char *)"%20", (char *)" ", MODE_ALL); + } + + // song update from URL + cfg.main.song_update_url_active = cfg_get_int("main", "song_update_url_active", 0); + cfg.main.song_update_url_interval = cfg_get_int("main", "song_update_url_interval", 1); + cfg.main.song_update_url = cfg_get_str("main", "song_update_url", NULL); + + // song update from file is default set to off + cfg.main.song_update = cfg_get_int("main", "song_update", 0); + cfg.main.song_delay = cfg_get_int("main", "song_delay", 0); + cfg.main.read_last_line = cfg_get_int("main", "read_last_line", 0); + cfg.main.app_update = cfg_get_int("main", "app_update", 0); + cfg.main.app_update_service = cfg_get_int("main", "app_update_service", 0); + cfg.main.app_artist_title_order = cfg_get_int("main", "app_artist_title_order", APP_TITLE_FIRST); + cfg.main.signal_threshold = cfg_get_float("main", "signal_threshold", 0); + cfg.main.silence_threshold = cfg_get_float("main", "silence_threshold", 0); + cfg.main.signal_detection = cfg_get_int("main", "signal_detection", -1); + cfg.main.silence_detection = cfg_get_int("main", "silence_detection", -1); + + // Backwards compatibility with versions < 0.1.41 + if (cfg.main.signal_detection == -1) { + cfg.main.signal_detection = cfg.main.signal_threshold > 0 ? 1 : 0; + } + if (cfg.main.silence_detection == -1) { + cfg.main.silence_detection = cfg.main.silence_threshold > 0 ? 1 : 0; + } + + cfg.main.connect_at_startup = cfg_get_int("main", "connect_at_startup", 0); + cfg.main.force_reconnecting = cfg_get_int("main", "force_reconnecting", 0); + cfg.main.reconnect_delay = cfg_get_int("main", "reconnect_delay", 1); + cfg.main.check_for_update = cfg_get_int("main", "check_for_update", 1); + cfg.main.start_agent = cfg_get_int("main", "start_agent", 0); + cfg.main.minimize_to_tray = cfg_get_int("main", "minimize_to_tray", 0); + + cfg.main.gain = cfg_get_float("main", "gain", 1.0); + if (cfg.main.gain > util_db_to_factor(24)) { + cfg.main.gain = util_db_to_factor(24); + } + if (cfg.main.gain < 0) { + cfg.main.gain = util_db_to_factor(-24); + } + + // Mixer + cfg.mixer.primary_device_gain = cfg_get_float("mixer", "primary_device_gain", 1.0); + cfg.mixer.primary_device_muted = cfg_get_int("mixer", "primary_device_muted", 0); + cfg.mixer.secondary_device_gain = cfg_get_float("mixer", "secondary_device_gain", 1.0); + cfg.mixer.secondary_device_muted = cfg_get_int("mixer", "secondary_device_muted", 0); + cfg.mixer.streaming_gain = cfg_get_float("mixer", "streaming_gain", 1.0); + cfg.mixer.recording_gain = cfg_get_float("mixer", "recording_gain", 1.0); + cfg.mixer.cross_fader = cfg_get_float("mixer", "cross_fader", 0.0); + + // DSP + cfg.dsp.equalizer_stream = cfg_get_int("dsp", "equalizer", 0); + cfg.dsp.equalizer_rec = cfg_get_int("dsp", "equalizer_rec", -1); + + // Backwards compatability with <= 0.1.40 + if (cfg.dsp.equalizer_rec == -1) { + cfg.dsp.equalizer_rec = cfg.dsp.equalizer_stream; + } + + cfg.dsp.eq_preset = cfg_get_str("dsp", "eq_preset", "Manual"); + + cfg.dsp.eq_gain[0] = cfg_get_float("dsp", "gain1", 0.0); + cfg.dsp.eq_gain[1] = cfg_get_float("dsp", "gain2", 0.0); + cfg.dsp.eq_gain[2] = cfg_get_float("dsp", "gain3", 0.0); + cfg.dsp.eq_gain[3] = cfg_get_float("dsp", "gain4", 0.0); + cfg.dsp.eq_gain[4] = cfg_get_float("dsp", "gain5", 0.0); + cfg.dsp.eq_gain[5] = cfg_get_float("dsp", "gain6", 0.0); + cfg.dsp.eq_gain[6] = cfg_get_float("dsp", "gain7", 0.0); + cfg.dsp.eq_gain[7] = cfg_get_float("dsp", "gain8", 0.0); + cfg.dsp.eq_gain[8] = cfg_get_float("dsp", "gain9", 0.0); + cfg.dsp.eq_gain[9] = cfg_get_float("dsp", "gain10", NAN); + if (isnan(cfg.dsp.eq_gain[9])) { + // Reset all EQ gains if band 10 has no config value. This prevents false values when the user updates from an earlier 5-band EQ to the new + // 10-band EQ + for (int i = 0; i < EQ_BAND_COUNT; i++) { + cfg.dsp.eq_gain[i] = 0.0; + } + } + + cfg.dsp.compressor_stream = cfg_get_int("dsp", "compressor", 0); + cfg.dsp.compressor_rec = cfg_get_int("dsp", "compressor_rec", -1); + + // Backwards compatability with <= 0.1.40 + if (cfg.dsp.compressor_rec == -1) { + cfg.dsp.compressor_rec = cfg.dsp.compressor_stream; + } + + cfg.dsp.aggressive_mode = cfg_get_int("dsp", "aggressive_mode", 0); + cfg.dsp.threshold = cfg_get_float("dsp", "threshold", -20.0); + cfg.dsp.ratio = cfg_get_float("dsp", "ratio", 5.0); + cfg.dsp.attack = cfg_get_float("dsp", "attack", 0.01); + cfg.dsp.release = cfg_get_float("dsp", "release", 1.0); + cfg.dsp.makeup_gain = cfg_get_float("dsp", "makeup_gain", 0.0); + + // MIDI + cfg.midi.dev_name = cfg_get_str("midi", "dev_name", "Disabled"); + char midi_section[16]; + for (i = 0; i < MIDI_COMMANDS_COUNT; i++) { + snprintf(midi_section, sizeof(midi_section), "midi_cmd_%d", i); + cfg.midi.commands[i].enabled = cfg_get_int(midi_section, "enabled", 0); + cfg.midi.commands[i].channel = cfg_get_int(midi_section, "channel", 0); // channel = 0 means all channels are allowed + cfg.midi.commands[i].msg_num = cfg_get_int(midi_section, "msg_num", i); + cfg.midi.commands[i].msg_type = cfg_get_int(midi_section, "msg_type", MIDI_MSG_TYPE_CC); // As of BUTT 0.1.41 "type" defaults to CC. + cfg.midi.commands[i].mode = cfg_get_int(midi_section, "mode", MIDI_MODE_ABSOLUTE); + cfg.midi.commands[i].soft_takeover = cfg_get_int(midi_section, "soft_takeover", 0); + } + + // read GUI stuff + cfg.gui.attach = cfg_get_int("gui", "attach", 0); + cfg.gui.ontop = cfg_get_int("gui", "ontop", 0); + cfg.gui.hide_log_window = cfg_get_int("gui", "hide_log_window", 0); + cfg.gui.remember_pos = cfg_get_int("gui", "remember_pos", 1); + cfg.gui.x_pos = cfg_get_int("gui", "x_pos", -1); + cfg.gui.y_pos = cfg_get_int("gui", "y_pos", -1); + cfg.gui.window_height = cfg_get_int("gui", "window_height", 0); + cfg.gui.lcd_auto = cfg_get_int("gui", "lcd_auto", 0); + cfg.gui.default_stream_info = cfg_get_int("gui", "default_stream_info", STREAM_TIME); + cfg.gui.start_minimized = cfg_get_int("gui", "start_minimized", 0); + cfg.gui.disable_gain_slider = cfg_get_int("gui", "disable_gain_slider", 0); + cfg.gui.show_listeners = cfg_get_int("gui", "show_listeners", 1); + cfg.gui.listeners_update_rate = cfg_get_int("gui", "listeners_update_rate", 10); + cfg.gui.vu_mode = cfg_get_int("gui", "vu_mode", VU_MODE_SOLID); + cfg.gui.always_show_vu_tabs = cfg_get_int("gui", "always_show_vu_tabs", 1); + + cfg.gui.vu_low_color = cfg_get_int("gui", "vu_low_color", (int)fl_rgb_color((uchar)0, (uchar)210, (uchar)0)); // Green + cfg.gui.vu_mid_color = cfg_get_int("gui", "vu_mid_color", (int)fl_rgb_color((uchar)230, (uchar)230, (uchar)0)); // Yellow + cfg.gui.vu_high_color = cfg_get_int("gui", "vu_high_color", (int)fl_rgb_color((uchar)200, (uchar)0, (uchar)0)); // Red + + cfg.gui.vu_mid_range_start = cfg_get_int("gui", "vu_mid_range_start", -12); // dB + cfg.gui.vu_high_range_start = cfg_get_int("gui", "vu_high_range_start", -6); + + int lang_id = cfg_get_int("gui", "lang", -1); + if (lang_id != -1) { // For compatibility with butt configurations <= 0.1.33 + cfg.gui.lang_str = NULL; + lang_id_to_str(lang_id, &cfg.gui.lang_str, LANG_MAPPING_OLD); + } + else { + cfg.gui.lang_str = cfg_get_str("gui", "lang_str", "system"); // butt > 0.1.33 + if (cfg.gui.lang_str == NULL) { + lang_id_to_str(0, &cfg.gui.lang_str, LANG_MAPPING_NEW); + } + } + + cfg.gui.window_title = cfg_get_str("gui", "window_title", NULL); + if (cfg.gui.window_title == NULL) { + cfg.gui.window_title = (char *)malloc(1); + cfg.gui.window_title[0] = '\0'; + } + + // read FLTK related stuff + cfg.main.bg_color = cfg_get_int("main", "bg_color", (int)fl_rgb_color(15, 15, 15)); // dark gray + cfg.main.txt_color = cfg_get_int("main", "txt_color", (int)fl_rgb_color(255, 255, 255)); // white + + // read mp3 codec related stuff + cfg.mp3_codec_stream.enc_quality = cfg_get_int("mp3_codec_stream", "enc_quality", 3); + cfg.mp3_codec_stream.stereo_mode = cfg_get_int("mp3_codec_stream", "stereo_mode", 0); + cfg.mp3_codec_stream.bitrate_mode = cfg_get_int("mp3_codec_stream", "bitrate_mode", CHOICE_CBR); + cfg.mp3_codec_stream.vbr_quality = cfg_get_int("mp3_codec_stream", "vbr_quality", 4); + cfg.mp3_codec_stream.vbr_min_bitrate = cfg_get_int("mp3_codec_stream", "vbr_min_bitrate", 32); + cfg.mp3_codec_stream.vbr_max_bitrate = cfg_get_int("mp3_codec_stream", "vbr_max_bitrate", 320); + cfg.mp3_codec_stream.vbr_force_min_bitrate = cfg_get_int("mp3_codec_stream", "vbr_force_min_bitrate", 0); + cfg.mp3_codec_stream.resampling_freq = cfg_get_int("mp3_codec_stream", "resampling_freq", CHOICE_MP3_RESAMPLING_DISABLED); + cfg.mp3_codec_stream.lowpass_freq_active = cfg_get_int("mp3_codec_stream", "lowpass_freq_active", 0); + cfg.mp3_codec_stream.lowpass_freq = cfg_get_float("mp3_codec_stream", "lowpass_freq", 0); + cfg.mp3_codec_stream.lowpass_width_active = cfg_get_int("mp3_codec_stream", "lowpass_width_active", 0); + cfg.mp3_codec_stream.lowpass_width = cfg_get_float("mp3_codec_stream", "lowpass_width", 0); + cfg.mp3_codec_stream.highpass_freq_active = cfg_get_int("mp3_codec_stream", "highpass_freq_active", 0); + cfg.mp3_codec_stream.highpass_freq = cfg_get_float("mp3_codec_stream", "highpass_freq", 0); + cfg.mp3_codec_stream.highpass_width_active = cfg_get_int("mp3_codec_stream", "highpass_width_active", 0); + cfg.mp3_codec_stream.highpass_width = cfg_get_float("mp3_codec_stream", "highpass_width", 0); + + cfg.mp3_codec_rec.enc_quality = cfg_get_int("mp3_codec_rec", "enc_quality", 3); + cfg.mp3_codec_rec.stereo_mode = cfg_get_int("mp3_codec_rec", "stereo_mode", 0); + cfg.mp3_codec_rec.bitrate_mode = cfg_get_int("mp3_codec_rec", "bitrate_mode", CHOICE_CBR); + cfg.mp3_codec_rec.vbr_quality = cfg_get_int("mp3_codec_rec", "vbr_quality", 4); + cfg.mp3_codec_rec.vbr_min_bitrate = cfg_get_int("mp3_codec_rec", "vbr_min_bitrate", 32); + cfg.mp3_codec_rec.vbr_max_bitrate = cfg_get_int("mp3_codec_rec", "vbr_max_bitrate", 320); + cfg.mp3_codec_rec.vbr_force_min_bitrate = cfg_get_int("mp3_codec_rec", "vbr_force_min_bitrate", 0); + cfg.mp3_codec_rec.resampling_freq = cfg_get_int("mp3_codec_rec", "resampling_freq", CHOICE_MP3_RESAMPLING_DISABLED); + cfg.mp3_codec_rec.lowpass_freq_active = cfg_get_int("mp3_codec_rec", "lowpass_freq_active", 0); + cfg.mp3_codec_rec.lowpass_freq = cfg_get_float("mp3_codec_rec", "lowpass_freq", 0); + cfg.mp3_codec_rec.lowpass_width_active = cfg_get_int("mp3_codec_rec", "lowpass_width_active", 0); + cfg.mp3_codec_rec.lowpass_width = cfg_get_float("mp3_codec_rec", "lowpass_width", 0); + cfg.mp3_codec_rec.highpass_freq_active = cfg_get_int("mp3_codec_rec", "highpass_freq_active", 0); + cfg.mp3_codec_rec.highpass_freq = cfg_get_float("mp3_codec_rec", "highpass_freq", 0); + cfg.mp3_codec_rec.highpass_width_active = cfg_get_int("mp3_codec_rec", "highpass_width_active", 0); + cfg.mp3_codec_rec.highpass_width = cfg_get_float("mp3_codec_rec", "highpass_width", 0); + + // read ogg/vorbis codec related stuff + cfg.vorbis_codec_stream.bitrate_mode = cfg_get_int("vorbis_codec_stream", "bitrate_mode", CHOICE_CBR); + cfg.vorbis_codec_stream.vbr_quality = cfg_get_int("vorbis_codec_stream", "vbr_quality", 0); + cfg.vorbis_codec_stream.vbr_min_bitrate = cfg_get_int("vorbis_codec_stream", "vbr_min_bitrate", 0); + cfg.vorbis_codec_stream.vbr_max_bitrate = cfg_get_int("vorbis_codec_stream", "vbr_max_bitrate", 0); + cfg.vorbis_codec_rec.bitrate_mode = cfg_get_int("vorbis_codec_rec", "bitrate_mode", CHOICE_CBR); + cfg.vorbis_codec_rec.vbr_quality = cfg_get_int("vorbis_codec_rec", "vbr_quality", 0); + cfg.vorbis_codec_rec.vbr_min_bitrate = cfg_get_int("vorbis_codec_rec", "vbr_min_bitrate", 0); // 0 = Auto + cfg.vorbis_codec_rec.vbr_max_bitrate = cfg_get_int("vorbis_codec_rec", "vbr_max_bitrate", 0); // 0 = Auto + + // read opus codec related stuff + cfg.opus_codec_stream.bitrate_mode = cfg_get_int("opus_codec_stream", "bitrate_mode", CHOICE_VBR); + cfg.opus_codec_stream.quality = cfg_get_int("opus_codec_stream", "quality", 0); + cfg.opus_codec_stream.audio_type = cfg_get_int("opus_codec_stream", "audio_type", CHOICE_TYPE_MUSIC); + cfg.opus_codec_stream.bandwidth = cfg_get_int("opus_codec_stream", "bandwidth", 0); + + cfg.opus_codec_rec.bitrate_mode = cfg_get_int("opus_codec_rec", "bitrate_mode", CHOICE_VBR); + cfg.opus_codec_rec.quality = cfg_get_int("opus_codec_rec", "quality", 0); + cfg.opus_codec_rec.audio_type = cfg_get_int("opus_codec_rec", "audio_type", CHOICE_TYPE_MUSIC); + cfg.opus_codec_rec.bandwidth = cfg_get_int("opus_codec_rec", "bandwidth", 0); + + // read flac codec related stuff + cfg.flac_codec_stream.bit_depth = cfg_get_int("flac_codec_stream", "bit_depth", 16); + cfg.flac_codec_rec.bit_depth = cfg_get_int("flac_codec_rec", "bit_depth", 16); + + // read wav codec related stuff + cfg.wav_codec_rec.bit_depth = cfg_get_int("wav_codec_rec", "bit_depth", 16); + + // read aac codec related stuff + cfg.aac_codec_stream.bitrate_mode = cfg_get_int("aac_codec_stream", "bitrate_mode", CHOICE_CBR); + cfg.aac_codec_stream.profile = cfg_get_int("aac_codec_stream", "profile", CHOICE_AAC_PROFILE_AUTO); + cfg.aac_codec_stream.afterburner = cfg_get_int("aac_codec_stream", "afterburner", 0); // Default: After burner on + + cfg.aac_codec_rec.bitrate_mode = cfg_get_int("aac_codec_rec", "bitrate_mode", CHOICE_CBR); + cfg.aac_codec_rec.profile = cfg_get_int("aac_codec_rec", "profile", CHOICE_AAC_PROFILE_AUTO); + cfg.aac_codec_rec.afterburner = cfg_get_int("aac_codec_rec", "afterburner", 0); // Default: After burner on + +#ifdef HAVE_LIBFDK_AAC + // Backward compatability + if (cfg_get_int("audio", "aac_overwrite_aot", -1) != -1) { + switch (cfg_get_int("audio", "aac_aot", -1)) { + case 2: + cfg.aac_codec_stream.profile = CHOICE_AAC_PROFILE_AAC_LC; + cfg.aac_codec_rec.profile = CHOICE_AAC_PROFILE_AAC_LC; + break; + case 5: + cfg.aac_codec_stream.profile = CHOICE_AAC_PROFILE_HE_AACv1; + cfg.aac_codec_rec.profile = CHOICE_AAC_PROFILE_HE_AACv1; + break; + case 29: + cfg.aac_codec_stream.profile = CHOICE_AAC_PROFILE_HE_AACv2; + cfg.aac_codec_rec.profile = CHOICE_AAC_PROFILE_HE_AACv2; + break; + default: + cfg.aac_codec_stream.profile = CHOICE_AAC_PROFILE_AUTO; + cfg.aac_codec_rec.profile = CHOICE_AAC_PROFILE_AUTO; + break; + } + } + +#endif + + return 0; +} + +int cfg_create_default(void) +{ + FILE *cfg_fd; + char *p; + char def_rec_folder[PATH_MAX]; + + cfg_fd = fl_fopen(cfg_path, "wb"); + if (cfg_fd == NULL) { + return 1; + } + +#ifdef WIN32 + p = fl_getenv("USERPROFILE"); + if (p != NULL) { + snprintf(def_rec_folder, PATH_MAX, "%s\\Music\\", p); + } + else { + snprintf(def_rec_folder, PATH_MAX, "./"); + } +#elif __APPLE__ + p = fl_getenv("HOME"); + if (p != NULL) { + snprintf(def_rec_folder, PATH_MAX, "%s/Music/", p); + } + else { + snprintf(def_rec_folder, PATH_MAX, "~/"); + } +#else // UNIX + p = fl_getenv("HOME"); + if (p != NULL) { + snprintf(def_rec_folder, PATH_MAX, "%s/", p); + } + else { + snprintf(def_rec_folder, PATH_MAX, "~/"); + } +#endif + + fprintf(cfg_fd, "#This is a configuration file for butt (broadcast using this tool)\n\n"); + fprintf(cfg_fd, "[main]\n" + "server =\n" + "icy =\n" + "num_of_srv = 0\n" + "num_of_icy = 0\n" + "srv_ent =\n" + "icy_ent =\n" + "song_update_url_active = 0\n" + "song_update_url_interval = 1\n" + "song_update_url =\n" + "song_path =\n" + "song_update = 0\n" + "song_delay = 0\n" + "song_prefix = \n" + "song_suffix = \n" + "app_update = 0\n" + "app_update_service = 0\n" + "app_artist_title_order = 1\n" + "read_last_line = 0\n" + "log_file =\n" + "gain = 1.0\n" + "ic_charset =\n" + "signal_threshhold = 0\n" + "silence_threshhold = 0\n" + "signal_detection = 0\n" + "silence_detection = 0\n" + "check_for_update = 1\n" + "start_agent = 0\n" + "minimize_to_tray = 0\n" + "force_reconnecting = 0\n" + "reconnect_delay = 1\n" + "connect_at_startup = 0\n\n"); + + fprintf(cfg_fd, + "[audio]\n" + "device = default\n" + "samplerate = 44100\n" + "bitrate = 128\n" + "channel = 2\n" + "codec = mp3\n" + "resample_mode = 1\n" // SRC_SINC_MEDIUM_QUALITY + "silence_level = 50.0\n" + "signal_level = 50.0\n" + "disable_dithering = 0\n" + "buffer_ms = 50\n\n"); + + fprintf(cfg_fd, + "[record]\n" + "samplerate = 44100\n" + "bitrate = 192\n" + "channel = 2\n" + "codec = mp3\n" + "start_rec = 0\n" + "stop_rec = 0\n" + "rec_after_launch = 0\n" + "overwrite_files = 0\n" + "sync_to_hour = 0\n" + "split_time = 0\n" + "filename = rec_%%Y%%m%%d-%%H%%M%%S.mp3\n" + "signal_threshhold = 0\n" + "silence_threshhold = 0\n" + "signal_detection = 0\n" + "silence_detection = 0\n" + "folder = %s\n\n", + def_rec_folder); + + fprintf(cfg_fd, "[tls]\n" + "cert_file =\n" + "cert_dir =\n\n"); + + fprintf(cfg_fd, "[dsp]\n" + "equalizer = 0\n" + "eq_preset = Manual\n" + "gain1 = 0.0\n" + "gain2 = 0.0\n" + "gain3 = 0.0\n" + "gain4 = 0.0\n" + "gain5 = 0.0\n" + "gain6 = 0.0\n" + "gain7 = 0.0\n" + "gain8 = 0.0\n" + "gain9 = 0.0\n" + "gain10 = 0.0\n" + "compressor = 0\n" + "aggressive_mode = 0\n" + "threshold = -20.0\n" + "ratio = 5\n" + "attack = 0.01\n" + "release = 1.0\n" + "makeup_gain = 0.0\n"); + + fprintf(cfg_fd, "[gui]\n" + "attach = 0\n" + "ontop = 0\n" + "hide_log_window = 0\n" + "remember_pos = 1\n" + "lcd_auto = 0\n" + "default_stream_info = 0\n" + "start_minimized = 0\n" + "disable_gain_slider = 0\n" + "show_listeners = 1\n" + "listeners_update_rate = 10\n" + "window_title = \n" + "lang_str = system\n\n"); + + fprintf(cfg_fd, "[mp3_codec_stream]\n" + "enc_quality = 3\n" + "stereo_mode = 0\n" + "bitrate_mode = 0\n" + "vbr_quality = 4\n" + "vbr_min_bitrate = 32\n" + "vbr_max_bitrate = 320\n" + "vbr_force_min_bitrate = 0\n" + "resampling_freq = 0\n" + "lowpass_freq_active = 0\n" + "lowpass_freq = 0\n" + "lowpass_width_active = 0\n" + "lowpass_width = 0\n" + "highpass_freq_active = 0\n" + "highpass_freq = 0\n" + "highpass_width_active = 0\n" + "highpass_width = 0\n\n"); + + fprintf(cfg_fd, "[mp3_codec_rec]\n" + "enc_quality = 3\n" + "stereo_mode = 0\n" + "bitrate_mode = 0\n" + "vbr_quality = 4\n" + "vbr_min_bitrate = 32\n" + "vbr_max_bitrate = 320\n" + "vbr_force_min_bitrate = 0\n" + "resampling_freq = 0\n" + "lowpass_freq_active = 0\n" + "lowpass_freq = 0\n" + "lowpass_width_active = 0\n" + "lowpass_width = 0\n" + "highpass_freq_active = 0\n" + "highpass_freq = 0\n" + "highpass_width_active = 0\n" + "highpass_width = 0\n\n"); + + fprintf(cfg_fd, "[vorbis_codec_stream]\n" + "bitrate_mode = 0\n" + "vbr_quality = 0\n" + "vbr_min_bitrate = 0\n" + "vbr_max_bitrate = 0\n\n"); + + fprintf(cfg_fd, "[vorbis_codec_rec]\n" + "bitrate_mode = 0\n" + "vbr_quality = 0\n" + "vbr_min_bitrate = 0\n" + "vbr_max_bitrate = 0\n\n"); + + fprintf(cfg_fd, "[opus_codec_stream]\n" + "bitrate_mode = 1\n" + "quality = 0\n" + "audio_type = 0\n" + "bandwidth = 0\n\n"); + + fprintf(cfg_fd, "[opus_codec_rec]\n" + "bitrate_mode = 1\n" + "quality = 0\n" + "audio_type = 0\n" + "bandwidth = 0\n\n"); + + fprintf(cfg_fd, "[aac_codec_stream]\n" + "bitrate_mode = 0\n" + "afterburner = 0\n" + "profile = 0\n\n"); + + fprintf(cfg_fd, "[aac_codec_rec]\n" + "bitrate_mode = 0\n" + "afterburner = 0\n" + "profile = 0\n\n"); + + fprintf(cfg_fd, "[flac_codec_stream]\n" + "bit_depth = 16\n\n"); + + fprintf(cfg_fd, "[flac_codec_rec]\n" + "bit_depth = 16\n\n"); + + fprintf(cfg_fd, "[wav_codec_rec]\n" + "bit_depth = 16\n\n"); + + fclose(cfg_fd); + + return 0; +} diff --git a/src/cfg.h b/src/cfg.h new file mode 100644 index 0000000..49fcff7 --- /dev/null +++ b/src/cfg.h @@ -0,0 +1,400 @@ +// config functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef CFG_H +#define CFG_H + +#ifndef BUILD_CLIENT +#include "port_audio.h" +#endif +#include "parseconfig.h" + +enum { + SHOUTCAST = 0, + ICECAST = 1, + RADIOCO = 2, + WEBRTC = 3, +}; + +enum { + ICECAST_PROTOCOL_PUT = 0, + ICECAST_PROTOCOL_SOURCE = 1, +}; + +enum { + CHOICE_STEREO = 0, + CHOICE_MONO = 1, +}; + +enum { + CHOICE_MP3 = 0, + CHOICE_OGG = 1, + CHOICE_OPUS = 2, + CHOICE_AAC = 3, + CHOICE_FLAC = 4, + CHOICE_WAV = 5, +}; + +enum { + CHOICE_CBR = 0, + CHOICE_VBR = 1, + CHOICE_ABR = 2, +}; + +enum { + CHOICE_TYPE_MUSIC = 0, + CHOICE_TYPE_SPEECH = 1, +}; + +enum { + CHOICE_AAC_PROFILE_AUTO = 0, + CHOICE_AAC_PROFILE_AAC_LC = 1, + CHOICE_AAC_PROFILE_HE_AACv1 = 2, + CHOICE_AAC_PROFILE_HE_AACv2 = 3, +}; + +enum { + CHOICE_MP3_RESAMPLING_DISABLED = 0, + CHOICE_MP3_RESAMPLING_8000 = 1, + CHOICE_MP3_RESAMPLING_11025 = 2, + CHOICE_MP3_RESAMPLING_12000 = 3, + CHOICE_MP3_RESAMPLING_16000 = 4, + CHOICE_MP3_RESAMPLING_22050 = 5, + CHOICE_MP3_RESAMPLING_24000 = 6, + CHOICE_MP3_RESAMPLING_32000 = 7, + CHOICE_MP3_RESAMPLING_44100 = 8, + CHOICE_MP3_RESAMPLING_48000 = 9, +}; + +enum { + LANG_MAPPING_OLD = 0, + LANG_MAPPING_NEW = 1, +}; + +enum { + LANG_COUNT = 8, +}; + +enum { + MIDI_COMMANDS_COUNT = 14, +}; + +enum { + APP_ARTIST_FIRST = 0, + APP_TITLE_FIRST = 1, +}; + +enum { + VU_MODE_GRADIENT = 0, + VU_MODE_SOLID = 1, +}; + +enum { + REMEMBER_BY_ID = 0, + REMEMBER_BY_NAME = 1, +}; + +extern const char *lang_array_new[]; +extern const char *lang_array_old[]; +extern const char CONFIG_FILE[]; + +typedef struct { + char *name; + char *addr; + char *pwd; + char *mount; // mountpoint for icecast server + char *usr; // user for icecast server + char *cert_hash; // sha256 hash of trusted certificate + char *webrtc_ice; // ICE server for WebRTC + char *webrtc_whip; // WHIP URL for WebRTC + char *webrtc_auth; // WHIP URL Bearer Token for WebRTC + char *custom_listener_url; + char *custom_listener_mount; + int port; + int type; // SHOUTCAST, ICECAST or WEBRTC + int tls; // use tls: 0 = no, 1 = yes + int icecast_protocol; // Icecast protocol: 0 = PUT, 1 = SOURCE +} server_t; + +typedef struct { + int enabled; + int channel; // Any, or 1-16 + int msg_num; // CC number + int msg_type; // Currently unused + int mode; // CC Mode. Absolute or relative + int soft_takeover; // If active, value jumps are prevented + int picked_up; // 0 = not picked up, 1 = picked up (Only relevant if soft_takeover is active) +} midi_command_t; + +typedef struct { + char *name; + char *desc; // description + char *genre; + char *url; + char *irc; + char *icq; + char *aim; + char *pub; + int expand_variables; +} icy_t; + +typedef struct { + int selected_srv; + int selected_icy; + + struct { + char *srv; + char *icy; + char *srv_ent; + char *icy_ent; + char *song; + char *song_path; + FILE *song_fd; + char *song_prefix; + char *song_suffix; + int song_delay; + int song_update; // 1 = song info will be read from file + int read_last_line; + int app_update; + int app_update_service; + int app_artist_title_order; + char *song_update_url; + int song_update_url_active; + int song_update_url_interval; + int num_of_srv; + int num_of_icy; + int bg_color, txt_color; + int connect_at_startup; + int force_reconnecting; + int reconnect_delay; + float silence_threshold; // timeout duration of automatic stream stop + float signal_threshold; // timeout duration of automatic stream start + int signal_detection; + int silence_detection; + int check_for_update; + int start_agent; + int minimize_to_tray; + float gain; + char *log_file; + char *ic_charset; + } main; + + struct { + int dev_count; + int dev_num; + int dev2_num; + char *dev_name; + char *dev2_name; + int dev_remember; // Remember device by ID or Name + snd_dev_t **pcm_list; + int samplerate; + int resolution; + int channel; + int left_ch; + int right_ch; + int left_ch2; + int right_ch2; + int bitrate; + int buffer_ms; + int resample_mode; + float silence_level; + float signal_level; + int disable_dithering; + char *codec; + } audio; + + struct { + char *dev_name; + midi_command_t commands[MIDI_COMMANDS_COUNT]; + } midi; + + struct { + int channel; + int bitrate; + int quality; + int samplerate; + char *codec; + char *filename; + char *folder; + char *path; + FILE *fd; + int start_rec; + int stop_rec; + int overwrite_files; + int rec_after_launch; + int split_time; + int sync_to_hour; + float silence_threshold; + float signal_threshold; + int signal_detection; + int silence_detection; + } rec; + + struct { + char *cert_file; + char *cert_dir; + } tls; + + struct { + int equalizer_stream; + int equalizer_rec; + char *eq_preset; + double eq_gain[10]; + int compressor_stream; + int compressor_rec; + int aggressive_mode; + double threshold, ratio, attack, release, makeup_gain; + } dsp; + + struct { + double primary_device_gain; + int primary_device_muted; + int secondary_device_muted; + double secondary_device_gain; + double streaming_gain; + double recording_gain; + double cross_fader; + float primary_X_fader; + float secondary_X_fader; + } mixer; + + struct { + int attach; + int ontop; + int lcd_auto; + int default_stream_info; + int hide_log_window; + int remember_pos; + int window_height; + int x_pos, y_pos; + char *lang_str; + int vu_mode; + int always_show_vu_tabs; + int vu_low_color; + int vu_mid_color; + int vu_high_color; + int vu_mid_range_start; + int vu_high_range_start; + int start_minimized; + int disable_gain_slider; + int show_listeners; + int listeners_update_rate; + char *window_title; + } gui; + + struct { + int enc_quality; + int stereo_mode; + int bitrate_mode; + int vbr_quality; + int vbr_min_bitrate; + int vbr_max_bitrate; + int vbr_force_min_bitrate; + int resampling_freq; + int lowpass_freq_active; + float lowpass_freq; + int lowpass_width_active; + float lowpass_width; + int highpass_freq_active; + float highpass_freq; + int highpass_width_active; + float highpass_width; + + } mp3_codec_stream; + + struct { + int enc_quality; + int stereo_mode; + int bitrate_mode; + int vbr_quality; + int vbr_min_bitrate; + int vbr_max_bitrate; + int vbr_force_min_bitrate; + int resampling_freq; + int lowpass_freq_active; + float lowpass_freq; + int lowpass_width_active; + float lowpass_width; + int highpass_freq_active; + float highpass_freq; + int highpass_width_active; + float highpass_width; + } mp3_codec_rec; + + struct { + int bitrate_mode; + int vbr_quality; + int vbr_min_bitrate; + int vbr_max_bitrate; + } vorbis_codec_stream; + + struct { + int bitrate_mode; + int vbr_quality; + int vbr_min_bitrate; + int vbr_max_bitrate; + } vorbis_codec_rec; + + struct { + int bitrate_mode; + int quality; + int audio_type; + int bandwidth; + } opus_codec_stream; + + struct { + int bitrate_mode; + int quality; + int audio_type; + int bandwidth; + } opus_codec_rec; + + struct { + int bitrate_mode; + int profile; + int afterburner; + } aac_codec_stream; + + struct { + int bitrate_mode; + int profile; + int afterburner; + } aac_codec_rec; + + struct { + int bit_depth; + } flac_codec_stream; + + struct { + int bit_depth; + } flac_codec_rec; + + struct { + int bit_depth; + } wav_codec_rec; + + server_t **srv; + icy_t **icy; + +} config_t; + +extern char *cfg_path; // Path to config file +extern config_t cfg; // Holds config parameters + +int cfg_write_file(char *path); // Writes current config_t struct to path or cfg_path if path is NULL +int cfg_set_values(char *path); // Reads config file from path or cfg_path if path is NULL and fills the config_t struct +int cfg_create_default(void); // Creates a default config file, if there isn't one yet + +#endif diff --git a/src/command.cpp b/src/command.cpp new file mode 100644 index 0000000..51de6bf --- /dev/null +++ b/src/command.cpp @@ -0,0 +1,423 @@ +// command functions for butt +// +// Copyright 2007-2020 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include +#include + +#ifndef BUILD_CLIENT +#include +#endif + +#ifdef WIN32 +#include +#define usleep(us) Sleep(us / 1000) +#ifndef errno +#define errno WSAGetLastError() +#endif +#ifndef EWOULDBLOCK +#define EWOULDBLOCK WSAEWOULDBLOCK +#endif +#else +#include +#include +#include +#include //defines IPPROTO_TCP on BSD +#include +#include +#include +#endif + +#ifdef WIN32 +typedef int socklen_t; +#endif + +#include "command.h" +#include "sockfuncs.h" + +#ifndef BUILD_CLIENT +#include "timer.h" +#include "ringbuffer.h" +#endif + +int client_sock; +sock_proto_t server_proto; + +#ifndef BUILD_CLIENT + +pthread_t listen_thread_detached; +int listen_sock = -1; +int conn_sock; +int connection_established; +sock_udp_conn_t udp_conn; +ringbuf_t command_fifo; + +void *listen_thread_func(void *data) +{ + timer_ms_t status_timer; + timer_ms_t connection_timer; + command_t command; + int bytes_count; + struct sockaddr_in cli; + socklen_t len; + len = sizeof(cli); + char recv_buf[1024]; + int response = 0; + + rb_init(&command_fifo, COMMAND_FIFO_LEN * sizeof(command_t)); + + timer_init(&status_timer, 0.8); // Use 0.8 s instead of 1.0 s to allow small time fluctations + timer_init(&connection_timer, 5); + connection_established = 0; + + for (;;) { + // printf("num of commands in fifo: %d\n", rb_filled(&command_fifo)/sizeof(command_t)); + if (connection_established == 1 || + rb_space(&command_fifo) < (int)sizeof(command_t)) { // Do not accept new connections while a connection is established or the command fifo is full + // To prevent a deadlock reset the connection in case it stays in "connection_established = 1" for // more then 5 seconds + if (timer_is_elapsed(&connection_timer) == 1) { + if (server_proto == SOCK_PROTO_TCP) { + sock_close(conn_sock); + } + rb_clear(&command_fifo); + connection_established = 0; + } + usleep(100 * 1000); + // printf("continued\n"); + continue; + } + if (server_proto == SOCK_PROTO_TCP) { + conn_sock = accept(listen_sock, (struct sockaddr *)&cli, &len); + if (conn_sock < 0) { // conn_sock < 0 if error + usleep(100 * 1000); + continue; + } + } + else { + conn_sock = listen_sock; + } + sock_nonblock(conn_sock); + + if (server_proto == SOCK_PROTO_TCP) { + bytes_count = sock_recv(conn_sock, recv_buf, sizeof(recv_buf), COMMAND_TIMEOUT); + } + else { + bytes_count = sock_recvfrom(conn_sock, recv_buf, sizeof(recv_buf), &udp_conn, COMMAND_TIMEOUT); + } + + if (bytes_count == SOCK_TIMEOUT) { + if (server_proto == SOCK_PROTO_TCP) { + sock_close(conn_sock); + } + connection_established = 0; + continue; + } + + connection_established = 1; + timer_start(&connection_timer); + + if (bytes_count > 0) { + memcpy((char *)&command, recv_buf, COMMAND_PACKET_SIZE); + if (command.param_size > 0) { + // Limit parameter size to COMMAND_MAX_PARAM_SIZE + command.param_size = command.param_size > COMMAND_MAX_PARAM_SIZE ? COMMAND_MAX_PARAM_SIZE : command.param_size; + + int expected_bytes = COMMAND_PACKET_SIZE + command.param_size; + if (bytes_count < expected_bytes) { + int remaining_bytes = expected_bytes - bytes_count; + bytes_count += sock_recv(conn_sock, recv_buf + bytes_count, remaining_bytes, COMMAND_TIMEOUT); + if (bytes_count != expected_bytes) { + if (server_proto == SOCK_PROTO_TCP) { + sock_close(conn_sock); + } + connection_established = 0; + continue; // Still not all bytes received -> dismiss this command + } + } + command.param = (void *)calloc(command.param_size + 1, sizeof(uint8_t)); + memcpy((char *)command.param, recv_buf + COMMAND_PACKET_SIZE, command.param_size); + } + if (command.cmd == CMD_GET_STATUS) { + if (status_timer.is_running == false) { + timer_start(&status_timer); + } + else if (timer_is_elapsed(&status_timer) == 0) { // Limit status request to approx. one per second + if (server_proto == SOCK_PROTO_TCP) { + sock_close(conn_sock); + } + else { + response = SOCK_ERR_RECV; + sock_sendto(conn_sock, (char *)&response, sizeof(response), &udp_conn, SEND_TIMEOUT); + } + connection_established = 0; + continue; + } + } + else { // (command.cmd != CMD_GET_STATUS) + response = 0; + if (server_proto == SOCK_PROTO_TCP) { + sock_send(conn_sock, (char *)&response, sizeof(response), SEND_TIMEOUT); + sock_close(conn_sock); + connection_established = 0; + } + else { + sock_sendto(conn_sock, (char *)&response, sizeof(response), &udp_conn, SEND_TIMEOUT); + connection_established = 0; + } + } + + command_add_cmd_to_fifo(command); + } + } + + // Detach thread (free ressources) because no one will call pthread_join() on it + pthread_detach(pthread_self()); + + return NULL; +} + +int command_add_cmd_to_fifo(command_t new_cmd) +{ + return rb_write(&command_fifo, (char *)&new_cmd, sizeof(command_t)); +} + +int command_get_cmd_from_fifo(command_t *cmd) +{ + if (rb_filled(&command_fifo) < (int)sizeof(command_t)) { + return CMD_ERR_FIFO_EMPTY; + } + + return rb_read_len(&command_fifo, (char *)cmd, sizeof(command_t)); +} + +int command_start_server(int port, int search_port, int mode, sock_proto_t proto) +{ +#ifdef WIN32 + WSADATA wsa; + WSAStartup(MAKEWORD(2, 2), &wsa); +#endif + + struct sockaddr_in servaddr; + + listen_sock = socket(AF_INET, proto == SOCK_PROTO_TCP ? SOCK_STREAM : SOCK_DGRAM, 0); + if (listen_sock == -1) { + return SOCK_ERR_CREATE; + } + + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + + if (mode == SERVER_MODE_LOCAL) { + servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + } + else { // SERVER_MODE_ALL (accessable from the network) + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + } + + int val = 1; + setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(int)); + + int bind_succeeded = 0; + int p; + for (p = port; p < port + 10; p++) { + servaddr.sin_port = htons(p); + + if (bind(listen_sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0) { + bind_succeeded = 1; + break; + } + + if (search_port == 0) { + break; + } + } + + if (bind_succeeded == 0) { + return SOCK_ERR_BIND; + } + + if (proto == SOCK_PROTO_TCP) { + if ((listen(listen_sock, 1)) != 0) { + return SOCK_ERR_LISTEN; + } + } + + if (pthread_create(&listen_thread_detached, NULL, listen_thread_func, NULL) != 0) { + return 0; + } + + server_proto = proto; + + return p; +} + +void command_send_status_reply(status_packet_t *status_packet) +{ + if (server_proto == SOCK_PROTO_TCP) { + sock_send(conn_sock, (char *)status_packet, STATUS_PACKET_SIZE, COMMAND_TIMEOUT); + sock_send(conn_sock, status_packet->song, status_packet->song_len, COMMAND_TIMEOUT); + sock_send(conn_sock, status_packet->rec_path, status_packet->rec_path_len, COMMAND_TIMEOUT); + sock_close(conn_sock); + connection_established = 0; + } + else { + char *udp_buf = (char *)malloc(STATUS_PACKET_SIZE + status_packet->song_len + status_packet->rec_path_len); + memcpy(udp_buf, status_packet, STATUS_PACKET_SIZE); + memcpy(udp_buf + STATUS_PACKET_SIZE, status_packet->song, status_packet->song_len); + memcpy(udp_buf + STATUS_PACKET_SIZE + status_packet->song_len, status_packet->rec_path, status_packet->rec_path_len); + sock_sendto(conn_sock, udp_buf, STATUS_PACKET_SIZE + status_packet->song_len + status_packet->rec_path_len, &udp_conn, COMMAND_TIMEOUT); + connection_established = 0; + free(udp_buf); + } +} + +void command_stop_server(void) +{ + if (listen_sock != -1) { + sock_close(listen_sock); + } +} +#endif // ifndef BUILD_CLIENT + +int command_send_cmd(command_t command, char *addr, int port, sock_proto_t proto) +{ + int ret; + int server_response; + char send_buf[1024]; + + client_sock = sock_connect(addr, port, proto, COMMAND_TIMEOUT); + if (client_sock < 0) { + return CMD_ERR_CONNECT; + } + + memcpy(send_buf, &command, COMMAND_PACKET_SIZE); + memcpy(send_buf + COMMAND_PACKET_SIZE, (char *)command.param, command.param_size); + + ret = sock_send(client_sock, send_buf, COMMAND_PACKET_SIZE + command.param_size, COMMAND_TIMEOUT); + if (ret < 0) { + if (proto == SOCK_PROTO_TCP) { + sock_close(client_sock); + } + return CMD_ERR_SEND_CMD; + } + + if (command.cmd != CMD_GET_STATUS) { + ret = sock_recv(client_sock, (char *)&server_response, sizeof(server_response), COMMAND_TIMEOUT); + if (ret < 0) { + if (proto == SOCK_PROTO_TCP) { + sock_close(client_sock); + } + return CMD_ERR_RECV_RESPONSE; + } + if (proto == SOCK_PROTO_TCP) { + sock_close(client_sock); + } + return server_response; + } + + return 0; +} + +int command_recv_status_reply(status_packet_t *status_packet, sock_proto_t proto) +{ + int ret; + uint32_t is_extended_packet; + + if (proto == SOCK_PROTO_TCP) { + // Receive 32 bit status register + ret = sock_recv(client_sock, (char *)&status_packet->status, sizeof(status_packet->status), COMMAND_TIMEOUT); + if (ret < 0) { + sock_close(client_sock); + return ret; + } + + // Check if status is returned by an old server that returns only the bit status register + is_extended_packet = (status_packet->status & (1 << STATUS_EXTENDED_PACKET)) > 0; + if (is_extended_packet == 0) { + sock_close(client_sock); + return sizeof(status_packet->status); + } + + // Receive version and check status protocol version + ret = sock_recv(client_sock, (char *)&status_packet->version, sizeof(status_packet->version), COMMAND_TIMEOUT); + if (ret < 0) { + sock_close(client_sock); + return ret; + } + if (status_packet->version != STATUS_PACKET_VERSION) { + sock_close(client_sock); + return 0; // Version missmatch + } + + // Receive remaining fixed len status variables + ret = sock_recv(client_sock, ((char *)status_packet) + sizeof(status_packet->status) + sizeof(status_packet->version), + STATUS_PACKET_SIZE - sizeof(status_packet->status) - sizeof(status_packet->version), COMMAND_TIMEOUT); + if (ret < 0) { + sock_close(client_sock); + return ret; + } + + // Receive song title + status_packet->song = (char *)malloc(status_packet->song_len); // song_len includes trailing '\0' + ret = sock_recv(client_sock, status_packet->song, status_packet->song_len, COMMAND_TIMEOUT); + if (ret < 0) { + sock_close(client_sock); + return ret; + } + + // Receive file record path + status_packet->rec_path = (char *)malloc(status_packet->rec_path_len); + ret = sock_recv(client_sock, status_packet->rec_path, status_packet->rec_path_len, COMMAND_TIMEOUT); + if (ret < 0) { + sock_close(client_sock); + return ret; + } + + sock_close(client_sock); + } + else { + char *udp_buf = (char *)malloc(SOCK_MAX_DATAGRAM_SIZE); + + ret = sock_recv(client_sock, udp_buf, SOCK_MAX_DATAGRAM_SIZE, COMMAND_TIMEOUT); + if (ret < 0) { + free(udp_buf); + return CMD_ERR_RECV_STATUS; + } + + if (ret < (int)STATUS_PACKET_SIZE) { + int response = *((int *)udp_buf); + free(udp_buf); + return response; + } + + memcpy((char *)status_packet, udp_buf, STATUS_PACKET_SIZE); + if (status_packet->version != STATUS_PACKET_VERSION) { + free(udp_buf); + return 0; // Version missmatch + } + + // Copy song title + status_packet->song = (char *)malloc(status_packet->song_len); // song_len includes trailing '\0' + memcpy(status_packet->song, udp_buf + STATUS_PACKET_SIZE, status_packet->song_len); + + // Copy file record path + status_packet->rec_path = (char *)malloc(status_packet->rec_path_len); + memcpy(status_packet->rec_path, udp_buf + STATUS_PACKET_SIZE + status_packet->song_len, status_packet->rec_path_len); + + free(udp_buf); + } + + return STATUS_PACKET_SIZE; +} diff --git a/src/command.h b/src/command.h new file mode 100644 index 0000000..dd01c58 --- /dev/null +++ b/src/command.h @@ -0,0 +1,86 @@ +#ifndef COMMAND_H +#define COMMAND_H + +#include +#include "sockfuncs.h" + +#define COMMAND_TIMEOUT 2000 +#define COMMAND_FIFO_LEN 32 +#define COMMAND_PACKET_SIZE (sizeof(command_t) - sizeof(void *)) +#define COMMAND_MAX_PARAM_SIZE 1000 + +#define DEFAULT_PORT 1256 + +#define STATUS_CONNECTED 0 +#define STATUS_CONNECTING 1 +#define STATUS_RECORDING 2 +#define STATUS_SIGNAL_DETECTED 3 +#define STATUS_SILENCE_DETECTED 4 +#define STATUS_EXTENDED_PACKET 31 +#define STATUS_PACKET_VERSION 3 +#define STATUS_PACKET_SIZE (sizeof(status_packet_t) - 2 * sizeof(char *)) + +enum { + CMD_EMPTY = 0, + CMD_CONNECT = 1, + CMD_DISCONNECT = 2, + CMD_START_RECORDING = 3, + CMD_STOP_RECORDING = 4, + CMD_GET_STATUS = 5, + CMD_SPLIT_RECORDING = 6, + CMD_QUIT = 7, + CMD_UPDATE_SONGNAME = 8, + CMD_SET_STREAM_SIGNAL_THRESHOLD = 9, + CMD_SET_STREAM_SILENCE_THRESHOLD = 10, + CMD_SET_RECORD_SIGNAL_THRESHOLD = 11, + CMD_SET_RECORD_SILENCE_THRESHOLD = 12, +}; + +enum { + CMD_ERR_CONNECT = -1, + CMD_ERR_SEND_CMD = -2, + CMD_ERR_RECV_RESPONSE = -3, + CMD_ERR_RECV_STATUS = -4, + CMD_ERR_FIFO_EMPTY = -5, + CMD_ERR_FIFO_FULL = -6, +}; + +enum { + SERVER_MODE_OFF = 0, + SERVER_MODE_LOCAL = 1, + SERVER_MODE_ALL = 2, +}; + +typedef struct command { + uint32_t cmd; + uint32_t param_size; + uint8_t padding[8]; + void *param; +} __attribute__((packed)) command_t; + +typedef struct status_packet { + uint32_t status; + uint16_t version; + int16_t volume_left; + int16_t volume_right; + uint32_t stream_seconds; + uint32_t stream_kByte; + uint32_t record_seconds; + uint32_t record_kByte; + uint16_t song_len; + uint16_t rec_path_len; + int32_t listener_count; + char *song; + char *rec_path; +} __attribute__((packed)) status_packet_t; + +int command_start_server(int port, int search_port, int mode, sock_proto_t proto); +int command_add_cmd_to_fifo(command_t new_cmd); +int command_get_cmd_from_fifo(command_t *cmd); +int command_send_cmd(command_t command, char *addr, int port, sock_proto_t proto); +void command_get_last_cmd(command_t *command); +void command_send_status_reply(status_packet_t *status_packet); +int command_recv_status_reply(status_packet_t *status_packet, sock_proto_t proto); +void command_stop_server(void); + +#endif diff --git a/src/currentTrack.cpp b/src/currentTrack.cpp new file mode 100644 index 0000000..4e17f90 --- /dev/null +++ b/src/currentTrack.cpp @@ -0,0 +1,17 @@ +// +// currentTrack.cpp +// butt +// +// Created by Melchor Garau Madrigal on 22/7/15. +// Copyright (c) 2015 Daniel Nöthen. All rights reserved. +// + +#include "currentTrack.h" + +currentTrackFunction getCurrentTrackFunctionFromId(int i) +{ + switch (i) { + default: + return NULL; + } +} \ No newline at end of file diff --git a/src/currentTrack.h b/src/currentTrack.h new file mode 100644 index 0000000..8083886 --- /dev/null +++ b/src/currentTrack.h @@ -0,0 +1,15 @@ +// +// currentTrack.h +// butt +// +// Created by Melchor Garau Madrigal on 22/7/15. +// Copyright (c) 2015 Daniel Nöthen. All rights reserved. +// + +#ifndef __butt__currentTrack__ +#define __butt__currentTrack__ + +#include +typedef const char *(*currentTrackFunction)(int artist_title_order); + +#endif /* defined(__butt__currentTrack__) */ diff --git a/src/currentTrackLinux.cpp b/src/currentTrackLinux.cpp new file mode 100644 index 0000000..57cecce --- /dev/null +++ b/src/currentTrackLinux.cpp @@ -0,0 +1,260 @@ +#include +#include +#include +#include +#include +#include + +#include "currentTrack.h" + +static DBusError err; +static DBusConnection *conn = NULL; + +static bool dbus_init(void) +{ + if (conn == NULL) { + int ret; + dbus_error_init(&err); + conn = dbus_bus_get(DBUS_BUS_SESSION, &err); + if (dbus_error_is_set(&err)) { + printf("Connection Error: %s\n", err.message); + dbus_error_free(&err); + return false; + } + + ret = dbus_bus_request_name(conn, "me.melchor9000.butt", DBUS_NAME_FLAG_REPLACE_EXISTING, &err); + if (dbus_error_is_set(&err)) { + printf("Name error: %s\n", err.message); + dbus_error_free(&err); + } + if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + return false; + } + } + return true; +} + +struct DBusMethodCall { + const char *target; + const char *object; + const char *interface; + const char *method; + void (*arg_iter)(void *data, DBusMessageIter *args); + void *data; +}; + +static bool dbus_call_method(const struct DBusMethodCall *opt, unsigned n, ...) +{ + DBusMessage *msg; + DBusMessageIter args; + DBusPendingCall *pending; + + va_list va; + va_start(va, n); + + msg = dbus_message_new_method_call(opt->target, opt->object, opt->interface, opt->method); + if (msg == NULL) { + printf("Message Null\n"); + for (unsigned i = 0; i < n; i++) + va_arg(va, void *); + va_end(va); + return false; + } + + dbus_message_iter_init_append(msg, &args); + + for (unsigned i = 0; i < n; i++) { + const char *arg = va_arg(va, const char *); + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &arg); + } + + va_end(va); + dbus_connection_send_with_reply(conn, msg, &pending, -1); + if (pending == NULL) { + printf("Pending call null\n"); + return false; + } + + dbus_connection_flush(conn); + dbus_message_unref(msg); + + dbus_pending_call_block(pending); + msg = dbus_pending_call_steal_reply(pending); + if (msg == NULL) { + printf("Reply NULL\n"); + return false; + } + + dbus_pending_call_unref(pending); + + if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_ERROR) { + if (dbus_message_iter_init(msg, &args)) { + do { + if (opt->arg_iter) { + opt->arg_iter(opt->data, &args); + } + } while (dbus_message_iter_next(&args)); + } + + dbus_message_unref(msg); + return true; + } + else { + dbus_message_unref(msg); + return false; + } +} + +static void playbackstatus(void *data, DBusMessageIter *args) +{ + DBusMessageIter var; + char *str; + dbus_message_iter_recurse(args, &var); + dbus_message_iter_get_basic(&var, &str); + *((char **)data) = strdup(str); +} + +static void metadata(void *data, DBusMessageIter *args) +{ + DBusMessageIter var, arr, var2, var3, arr2; + char *str = NULL; + char **values = (char **)data; + dbus_message_iter_recurse(args, &var); + + dbus_message_iter_recurse(&var, &arr); + do { + dbus_message_iter_recurse(&arr, &var2); + dbus_message_iter_get_basic(&var2, &str); + dbus_message_iter_next(&var2); + if (values[1] == NULL && !strcmp("xesam:artist", str)) { + dbus_message_iter_recurse(&var2, &var3); + dbus_message_iter_recurse(&var3, &arr2); + values[1] = (char *)calloc(1, 1); + int s = 1, didFirst = 0; + do { + dbus_message_iter_get_basic(&arr2, &str); + if (strlen(str)) { + s += strlen(str) + (didFirst ? 2 : 0); + values[1] = (char *)realloc(values[1], s); + if (didFirst) { + strcat(values[1], ", "); + } + strcat(values[1], str); + if (!didFirst) { + didFirst = 1; + } + } + } while (dbus_message_iter_next(&arr2)); + } + else if (values[0] == NULL && !strcmp("xesam:title", str)) { + dbus_message_iter_recurse(&var2, &var3); + dbus_message_iter_get_basic(&var3, &str); + values[0] = strdup(str); + } + } while (dbus_message_iter_next(&arr)); +} + +static char *get_mpris(const char *target, int artist_title_order) +{ + char *playbackStatusValue = NULL; + char *returnString = NULL; + struct DBusMethodCall opt = {target, "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "Get", playbackstatus, &playbackStatusValue}; + + dbus_init(); + if (dbus_bus_name_has_owner(conn, target, &err)) { + dbus_call_method(&opt, 2, "org.mpris.MediaPlayer2.Player", "PlaybackStatus"); + if (playbackStatusValue != NULL && strcmp(playbackStatusValue, "Stopped")) { + int len; + char *values[2] = {NULL, NULL}; + opt.arg_iter = metadata; + opt.data = values; + dbus_call_method(&opt, 2, "org.mpris.MediaPlayer2.Player", "Metadata"); + + if (values[0] != NULL && values[1] != NULL) { + len = strlen(values[1]) + 3 + strlen(values[0]) + 1; + returnString = (char *)malloc(len); + if (artist_title_order == 1) { + snprintf(returnString, len, "%s - %s", values[0], values[1]); + } + else { + snprintf(returnString, len, "%s - %s", values[1], values[0]); + } + free(values[0]); + free(values[1]); + } + else if (values[0] != NULL) { + len = strlen(values[0]) + 1; + returnString = (char *)malloc(len); + snprintf(returnString, len, "%s", values[0]); + free(values[0]); + } + else if (values[1] != NULL) { + len = strlen(values[1]) + 1; + returnString = (char *)malloc(len); + snprintf(returnString, len, "%s", values[1]); + free(values[1]); + } + } + if (playbackStatusValue != NULL) { + free(playbackStatusValue); + } + } + return returnString; +} + +const char *getCurrentTrackRhythmbox(int artist_title_order) +{ + return get_mpris("org.gnome.Rhythmbox3", artist_title_order); +} + +const char *getCurrentTrackClementine(int artist_title_order) +{ + return get_mpris("org.mpris.MediaPlayer2.clementine", artist_title_order); +} + +const char *getCurrentTrackSpotify(int artist_title_order) +{ + return get_mpris("org.mpris.MediaPlayer2.spotify", artist_title_order); +} + +const char *getCurrentTrackCantata(int artist_title_order) +{ + return get_mpris("org.mpris.MediaPlayer2.cantata", artist_title_order); +} + +const char *getCurrentTrackBanshee(int artist_title_order) +{ + return get_mpris("org.mpris.MediaPlayer2.banshee", artist_title_order); +} + +const char *getCurrentTrackStrawberry(int artist_title_order) +{ + return get_mpris("org.mpris.MediaPlayer2.strawberry", artist_title_order); +} + +const char *getCurrentTrackPlexamp(int artist_title_order) +{ + return get_mpris("org.mpris.MediaPlayer2.Plexamp", artist_title_order); +} + +currentTrackFunction getCurrentTrackFunctionFromId(int i) +{ + switch (i) { + case 0: + return &getCurrentTrackRhythmbox; + case 1: + return &getCurrentTrackBanshee; + case 2: + return &getCurrentTrackClementine; + case 3: + return &getCurrentTrackSpotify; + case 4: + return &getCurrentTrackCantata; + case 5: + return &getCurrentTrackStrawberry; + case 6: + return &getCurrentTrackPlexamp; + default: + return NULL; + } +} diff --git a/src/dsp.cpp b/src/dsp.cpp new file mode 100644 index 0000000..9279fd4 --- /dev/null +++ b/src/dsp.cpp @@ -0,0 +1,329 @@ +// +// dsp.cpp +// butt +// +// Created by Melchor Garau Madrigal on 16/2/16. +// Copyright © 2016 Daniel Noethen. All rights reserved. +// + +#include "dsp.hpp" +#include +#include +#include +#include "Biquad.h" +#include "cfg.h" + +DSPEffects::DSPEffects(uint32_t frames, uint8_t channels, uint32_t sampleRate) : samplerate(sampleRate) +{ + chans = (channels == 2) ? 2 : 1; + dsp_size = frames * channels; + + eq_active = 0; + drc_active = 0; + + for (uint32_t i = 0; i < eq_band_count; i++) { + eq_bands_left[i] = new Biquad(bq_type_peak, eq_freqs[i] / double(samplerate), 2, cfg.dsp.eq_gain[i]); + eq_bands_right[i] = new Biquad(bq_type_peak, eq_freqs[i] / double(samplerate), 2, cfg.dsp.eq_gain[i]); + } +} + +bool DSPEffects::hasToProcessSamples() +{ + return cfg.main.gain != 1 || eq_active || drc_active; +} + +void DSPEffects::loadEQPreset(const char *preset) +{ + double *gain_vals; + + if (!strcmp(preset, "Acoustic")) { + gain_vals = eq_acoustic; + } + else if (!strcmp(preset, "Bass Booster")) { + gain_vals = eq_bass_booster; + } + else if (!strcmp(preset, "Bass Reducer")) { + gain_vals = eq_bass_reducer; + } + else if (!strcmp(preset, "Classical")) { + gain_vals = eq_classical; + } + else if (!strcmp(preset, "Dance")) { + gain_vals = eq_dance; + } + else if (!strcmp(preset, "Deep")) { + gain_vals = eq_deep; + } + else if (!strcmp(preset, "Electronic")) { + gain_vals = eq_electronic; + } + else if (!strcmp(preset, "Hip-Hop")) { + gain_vals = eq_hiphop; + } + else if (!strcmp(preset, "Jazz")) { + gain_vals = eq_jazz; + } + else if (!strcmp(preset, "Latin")) { + gain_vals = eq_latin; + } + else if (!strcmp(preset, "Loudness")) { + gain_vals = eq_loudness; + } + else if (!strcmp(preset, "Lounge")) { + gain_vals = eq_lounge; + } + else if (!strcmp(preset, "Piano")) { + gain_vals = eq_piano; + } + else if (!strcmp(preset, "RnB")) { + gain_vals = eq_r_n_b; + } + else if (!strcmp(preset, "Rock")) { + gain_vals = eq_rock; + } + else if (!strcmp(preset, "Speech")) { + gain_vals = eq_speech; + } + else if (!strcmp(preset, "Treble Booster")) { + gain_vals = eq_treble_booster; + } + else if (!strcmp(preset, "Treble Reducer")) { + gain_vals = eq_trebles_reducer; + } + else if (!strcmp(preset, "Vocal Booster")) { + gain_vals = eq_vocal_booster; + } + else { + return; + } + + for (uint32_t i = 0; i < eq_band_count; i++) { + setEQband(0, gain_vals[i]); + } +} + +void DSPEffects::setEQband(int band, double gain_val) +{ + eq_bands_left[band]->setPeakGain(gain_val); + eq_bands_right[band]->setPeakGain(gain_val); +} + +/* +double DSPEffects::getEQband(int band) +{ + // return eq_bands_left[band]; // left and right have always the same gain value +}*/ + +double DSPEffects::getEQbandFromPreset(int band, const char *preset) +{ + if (!strcmp(preset, "Acoustic")) { + return eq_acoustic[band]; + } + else if (!strcmp(preset, "Bass Booster")) { + return eq_bass_booster[band]; + } + else if (!strcmp(preset, "Bass Reducer")) { + return eq_bass_reducer[band]; + } + else if (!strcmp(preset, "Classical")) { + return eq_classical[band]; + } + else if (!strcmp(preset, "Dance")) { + return eq_dance[band]; + } + else if (!strcmp(preset, "Deep")) { + return eq_deep[band]; + } + else if (!strcmp(preset, "Electronic")) { + return eq_electronic[band]; + } + else if (!strcmp(preset, "Hip-Hop")) { + return eq_hiphop[band]; + } + else if (!strcmp(preset, "Jazz")) { + return eq_jazz[band]; + } + else if (!strcmp(preset, "Latin")) { + return eq_latin[band]; + } + else if (!strcmp(preset, "Loudness")) { + return eq_loudness[band]; + } + else if (!strcmp(preset, "Lounge")) { + return eq_lounge[band]; + } + else if (!strcmp(preset, "Piano")) { + return eq_piano[band]; + } + else if (!strcmp(preset, "RnB")) { + return eq_r_n_b[band]; + } + else if (!strcmp(preset, "Rock")) { + return eq_rock[band]; + } + else if (!strcmp(preset, "Speech")) { + return eq_speech[band]; + } + else if (!strcmp(preset, "Treble Booster")) { + return eq_treble_booster[band]; + } + else if (!strcmp(preset, "Treble Reducer")) { + return eq_trebles_reducer[band]; + } + else if (!strcmp(preset, "Vocal Booster")) { + return eq_vocal_booster[band]; + } + + return 0; +} + +void DSPEffects::processSamples(float *audio_buf) +{ + if (cfg.main.gain != 1) { + for (uint32_t i = 0; i < dsp_size; i += chans) { + audio_buf[i] *= cfg.main.gain; + + if (chans == 2) { + audio_buf[i + 1] *= cfg.main.gain; + } + } + } + + if (drc_active) { + attack_const = expf(-1.0f / (cfg.dsp.attack * samplerate)); + release_const = expf(-1.0f / (cfg.dsp.release * samplerate)); + + if (cfg.dsp.aggressive_mode == 1) { + lowpass_const = 0; + } + else { + float lowpass_time = std::min(cfg.dsp.attack, cfg.dsp.release); + lowpass_time = std::max(0.002f, lowpass_time); + lowpass_const = expf(-1.0f / (lowpass_time * samplerate)); + } + compress(audio_buf); + } + + if (eq_active) { + for (uint32_t i = 0; i < dsp_size; i += chans) { + float s = audio_buf[i]; + for (int32_t j = eq_band_count - 1; j >= 0; j--) { + s = eq_bands_left[j]->process(s); + } + audio_buf[i] = s; + + if (chans == 2) { + float s = audio_buf[i + 1]; + for (int32_t j = eq_band_count - 1; j >= 0; j--) { + s = eq_bands_right[j]->process(s); + } + audio_buf[i + 1] = s; + } + } + } + + // Clamp to -1.0 .. 1.0 range + for (uint32_t i = 0; i < dsp_size; i++) { + if (audio_buf[i] > 1.0) { + audio_buf[i] = 1.0; + continue; + } + if (audio_buf[i] < -1.0) { + audio_buf[i] = -1.0; + } + } +} + +DSPEffects::~DSPEffects() +{ + for (uint32_t i = 0; i < eq_band_count; i++) { + delete eq_bands_left[i]; + delete eq_bands_right[i]; + } +} + +// loosely based on https://openaudio.blogspot.com/2017/01/basic-dynamic-range-compressor.html +// https://github.com/chipaudette/OpenAudio_ArduinoLibrary/blob/master/AudioEffectCompressor_F32.h +void DSPEffects::compress(float *audio_buf) +{ + float one_minus_attack_const = 1.0f - attack_const; + float one_minus_release_const = 1.0f - release_const; + float c1 = lowpass_const, c2 = 1.0f - c1; + + float ratio = cfg.dsp.ratio; + + if (ratio < 0.001) { + ratio = 1.0f; + } + + is_compressing = false; + + for (uint32_t i = 0; i < dsp_size; i += chans) { + // calculate instantaneous signal power + // (square signal and average channels) + float power = audio_buf[i] * audio_buf[i]; + if (chans == 2) { + power += audio_buf[i + 1] * audio_buf[i + 1]; + power /= 2; + } + + // low-pass filter + power = c1 * prev_power + c2 * power; + prev_power = power; + + // Do not apply compression if signal power is nearly zero to prevent -inf results for log10 calculations + if (power < 1.0E-13) { + continue; + } + + // convert to dB + float power_dB = 10.0f * std::log10(power); + + // calculate instantaneous target gain + float above_threshold = power_dB - cfg.dsp.threshold; + float gain_dB = (above_threshold / ratio) - above_threshold; + + if (above_threshold > 0) { + is_compressing = true; + } + + if (gain_dB > 0.0f) { + gain_dB = 0.0f; + } + + // smooth gain by attack and release + if (std::isnan(prev_gain_dB)) { + prev_gain_dB = 0.0f; + } + + if (gain_dB < prev_gain_dB) { + // attack phase + gain_dB = attack_const * prev_gain_dB + one_minus_attack_const * gain_dB; + } + else { + // release phase + gain_dB = release_const * prev_gain_dB + one_minus_release_const * gain_dB; + } + prev_gain_dB = gain_dB; + + // convert to linear gain + float gain_linear = pow(10, (gain_dB + cfg.dsp.makeup_gain) / 20.0f); + + // apply gain to samples + audio_buf[i] *= gain_linear; + if (chans == 2) { + audio_buf[i + 1] *= gain_linear; + } + } + + // limit the amount that the state of the smoothing filter can go towards -inf + if (prev_power < (1.0E-13)) { + prev_power = 1.0E-13; // never go less than -130 dbFS + } +} + +void DSPEffects::reset_compressor() +{ + prev_power = 1.0; + prev_gain_dB = 0.0; +} diff --git a/src/dsp.hpp b/src/dsp.hpp new file mode 100644 index 0000000..21384e8 --- /dev/null +++ b/src/dsp.hpp @@ -0,0 +1,76 @@ +// +// dsp.hpp +// butt +// +// Created by Melchor Garau Madrigal on 16/2/16. +// Copyright © 2016 Daniel Nöthen. All rights reserved. +// + +#ifndef dsp_hpp +#define dsp_hpp + +#include + +#define EQ_BAND_COUNT (10) + +class DSPEffects { +private: + double eq_acoustic[10] = {5, 5, 4, 1.5, 2.5, 2, 3.5, 4, 3.5, 2.5}; + double eq_bass_booster[10] = {6, 4, 3.5, 3, 2, 0, 0, 0, 0, 0}; + double eq_bass_reducer[10] = {-6, -4, -3.5, -3, -2, 0, 0, 0, 0, 0}; + double eq_classical[10] = {4.5, 3.5, 3, 3, -2, -2, 0, 2.5, 3, 3.5}; + double eq_dance[10] = {3.5, 6.5, 5, 0, 2.5, 3.5, 6, 4.5, 4, 0}; + double eq_deep[10] = {5, 3.5, 2, 1, 3, 3, 2, -2.5, -3.5, 4}; + double eq_electronic[10] = {4, 3.8, 2, 0, -2.5, 2.5, 2.5, 2, 4, 4.5}; + double eq_hiphop[10] = {5, 4, 2, 3, -1, -1, 2, -0.5, 2.5, 3}; + double eq_jazz[10] = {4, 3, 2, 2.5, -2, -2, 0, 2, 3, 3.5}; + double eq_latin[10] = {4, 3, 0, 0, -2, -2, -2, 0, 3, 4}; + double eq_loudness[10] = {6.5, 4, 0, 0, -2, 0, -1, -5, 5, 1.5}; + double eq_lounge[10] = {-3, -2, 0, 1.5, 4, 3, 0, -1.5, 2, 1}; + double eq_piano[10] = {3, 2.5, 0, 3, 3, 2, 3.5, 4, 3, 3.5}; + double eq_pop[10] = {-1.5, -1, 0, 2.5, 4, 4, 2.5, 0, -1.5, -2}; + double eq_r_n_b[10] = {3, 7.5, 6, 2, -2.5, -2, 2.8, 2.9, 3, 3.5}; + double eq_rock[10] = {5.5, 4, 3, 2, -0.5, -1, 1, 2.5, 3.5, 4}; + double eq_small_speakers[10] = {6, 4, 3.5, 3, 2, 0, -2, -3, -3.5, -4}; + double eq_speech[10] = {-3.5, -0.5, 0, 0.5, 3.5, 4.5, 4.5, 4, 3, 0}; + double eq_treble_booster[10] = {0, 0, 0, 0, 0, 2, 3, 3.5, 4, 5.5}; + double eq_trebles_reducer[10] = {0, 0, 0, 0, 0, -2, -3, -3.5, -4, -5.5}; + double eq_vocal_booster[10] = {-2, -3, -3, 2, 4, 4, 3.5, 2, 0, -2}; + + + double eq_freqs[EQ_BAND_COUNT] = {32, 64, 125, 250, 500, 1000, 2000, 4000, 8000, 16000}; + + + uint32_t dsp_size; + uint32_t samplerate; + uint8_t chans; + class Biquad *eq_bands_left[EQ_BAND_COUNT]; + class Biquad *eq_bands_right[EQ_BAND_COUNT]; + + + float attack_const, release_const, lowpass_const; + float prev_power = 1.0; + float prev_gain_dB = 0.0; + + void compress(float *audio_buf); + +public: + DSPEffects(uint32_t frames, uint8_t channels, uint32_t sampleRate); + ~DSPEffects(); + + uint32_t eq_band_count = EQ_BAND_COUNT; + int eq_active; + int drc_active; + bool is_compressing; + bool hasToProcessSamples(); + void loadEQPreset(const char *preset); + void setEQband(int band, double gain_val); + double getEQband(int band); + double getEQbandFromPreset(int band, const char* preset); + + + void processSamples(float* audio_buf); + void reset_compressor(); +}; + +#endif /* dsp_hpp */ diff --git a/src/flac_encode.cpp b/src/flac_encode.cpp new file mode 100644 index 0000000..d3f9b09 --- /dev/null +++ b/src/flac_encode.cpp @@ -0,0 +1,352 @@ +// flac encoding functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include +#include +#include + +#include "flac_encode.h" + +#define INT24_MAX ((1 << 23) - 1) +#define INT24_MIN (-(1 << 23)) + +FLAC__uint64 g_bytes_written = 0; + +static void progress_callback(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, + unsigned total_frames_estimate, void *client_data); + +static FLAC__StreamEncoderWriteStatus ogg_stream_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, + unsigned current_frame, void *client_data); + +uint8_t *g_enc_p = NULL; +uint8_t *g_hdr_p; +uint8_t g_hdr[1024]; + +int g_hdr_written; +int g_hdr_size = 0; + +static bool set_settings(flac_enc *flac) +{ + FLAC__bool ret = true; + ret &= FLAC__stream_encoder_set_verify(flac->encoder, false); + ret &= FLAC__stream_encoder_set_compression_level(flac->encoder, 5); + ret &= FLAC__stream_encoder_set_channels(flac->encoder, flac->channel); + ret &= FLAC__stream_encoder_set_bits_per_sample(flac->encoder, flac->bit_depth); + ret &= FLAC__stream_encoder_set_sample_rate(flac->encoder, flac->samplerate); + ret &= FLAC__stream_encoder_set_total_samples_estimate(flac->encoder, 0); + ret &= FLAC__stream_encoder_set_ogg_serial_number(flac->encoder, rand()); + + return ret; +} + +static void inject_new_song_title(flac_enc *flac) +{ + int comment_len; + + if (flac->vorbis_comment.length > 0) { + for (uint32_t i = 0; i < flac->vorbis_comment.data.vorbis_comment.num_comments; i++) + free(flac->vorbis_comment.data.vorbis_comment.comments[i].entry); + + free(flac->vorbis_comment.data.vorbis_comment.comments); + memset(&flac->vorbis_comment, 0, sizeof(FLAC__StreamMetadata)); + } + + comment_len = strlen(flac->song_title); + + flac->vorbis_comment.is_last = true; + flac->vorbis_comment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT; + flac->vorbis_comment.length = 3 * sizeof(uint32_t) + comment_len; // size of data field with ".length" and ".num_comments" variables included + flac->vorbis_comment.data.vorbis_comment.vendor_string.length = 0; + flac->vorbis_comment.data.vorbis_comment.vendor_string.entry = 0; + flac->vorbis_comment.data.vorbis_comment.num_comments = 1; + + flac->vorbis_comment.data.vorbis_comment.comments = (FLAC__StreamMetadata_VorbisComment_Entry *)malloc( + flac->vorbis_comment.data.vorbis_comment.num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry)); + + flac->vorbis_comment.data.vorbis_comment.comments[0].length = comment_len; + flac->vorbis_comment.data.vorbis_comment.comments[0].entry = (FLAC__byte *)malloc(comment_len + 1); + + memcpy(flac->vorbis_comment.data.vorbis_comment.comments[0].entry, flac->song_title, comment_len + 1); +} + +int flac_enc_init(flac_enc *flac) +{ + FLAC__bool ret = true; + + if ((flac->encoder = FLAC__stream_encoder_new()) == NULL) { + fprintf(stderr, "ERROR: allocating encoder\n"); + return 1; + } + memset(&flac->vorbis_comment, 0, sizeof(FLAC__StreamMetadata)); + + if (flac->enc_type == FLAC_ENC_TYPE_STREAM) { + ret = flac_enc_init_ogg_stream(flac); + } + + if (ret == true) { + flac->state = FLAC_STATE_OK; + return 0; + } + else { + return 1; + } +} + +int flac_enc_init_FILE(flac_enc *flac, FILE *fout) +{ + FLAC__StreamEncoderInitStatus init_status; + + set_settings(flac); + + init_status = FLAC__stream_encoder_init_FILE(flac->encoder, fout, progress_callback, /*client_data=*/NULL); + if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { + fprintf(stderr, "ERROR: initializing encoder: %s\n", FLAC__StreamEncoderInitStatusString[init_status]); + + return 1; + } + + return 0; +} + +FLAC__bool flac_enc_init_ogg_stream(flac_enc *flac) +{ + FLAC__StreamEncoderInitStatus init_status; + + g_hdr_written = 0; + g_hdr_size = 0; + g_hdr_p = g_hdr; + + set_settings(flac); + + if (flac->state == FLAC_STATE_UPDATE_META_DATA) { + inject_new_song_title(flac); + FLAC__StreamMetadata *comment_pointer = &flac->vorbis_comment; + FLAC__stream_encoder_set_metadata(flac->encoder, &comment_pointer, 1); + flac->state = FLAC_STATE_OK; + } + + init_status = FLAC__stream_encoder_init_ogg_stream(flac->encoder, NULL, ogg_stream_callback, NULL, NULL, NULL, NULL); + if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { + fprintf(stderr, "ERROR: initializing encoder: %s\n", FLAC__StreamEncoderInitStatusString[init_status]); + return false; + } + + flac->state = FLAC_STATE_OK; + + return true; +} + +void flac_update_song_title(flac_enc *flac, char *song_title) +{ + snprintf(flac->song_title, sizeof(flac->song_title), "TITLE=%s", song_title); + flac->state = FLAC_STATE_NEW_SONG_AVAILABLE; +} + +void flac_set_initial_song_title(flac_enc *flac, char *song_title) +{ + snprintf(flac->song_title, sizeof(flac->song_title), "TITLE=%s", song_title); + flac->state = FLAC_STATE_UPDATE_META_DATA; + flac_enc_reinit(flac); +} + +int flac_enc_encode(flac_enc *flac, float *pcm_float, int samples_per_chan, int channel) +{ + int i; + int samples_left; + int chunk_size; + int32_t *pcm_int32; + + int samples_written = 0; + + chunk_size = 2048; + if (chunk_size > samples_per_chan) { + chunk_size = samples_per_chan; + } + + samples_left = samples_per_chan; + + pcm_int32 = (int32_t *)pcm_float; + while (samples_left > 0) { + for (i = 0; i < chunk_size * channel; i++) { + if (pcm_float[i] > 0) { + if (flac->bit_depth == 16) { + pcm_int32[i] = (int32_t)round(fmin(pcm_float[i + samples_written] * INT16_MAX, INT16_MAX)); + } + else { // 24 bit + pcm_int32[i] = (int32_t)round(fmin(pcm_float[i + samples_written] * INT24_MAX, INT24_MAX)); + } + } + else { + if (flac->bit_depth == 16) { + pcm_int32[i] = (int32_t)round(fmax(-pcm_float[i + samples_written] * INT16_MIN, INT16_MIN)); + } + else { // 24 bit + pcm_int32[i] = (int32_t)round(fmax(-pcm_float[i + samples_written] * INT24_MIN, INT24_MIN)); + } + } + } + + FLAC__stream_encoder_process_interleaved(flac->encoder, pcm_int32, chunk_size); + + samples_written += chunk_size * channel; + samples_left -= chunk_size; + + if (samples_left < chunk_size) { + chunk_size = samples_left; + } + } + + return 0; +} + +int flac_enc_encode_stream(flac_enc *flac, float *pcm_float, uint8_t *enc_buf, int samples_per_chan, int channel, int new_stream) +{ + int i; + int samples_left; + int chunk_size; + int bytes_written; + int32_t *pcm_int32; + + g_enc_p = enc_buf; + + if (g_hdr_written == 0) { + memcpy(g_enc_p, g_hdr, g_hdr_size); + g_enc_p += g_hdr_size; + g_hdr_written = 1; + } + + int samples_written = 0; + + chunk_size = 2048; + if (chunk_size > samples_per_chan) { + chunk_size = samples_per_chan; + } + + samples_left = samples_per_chan; + + pcm_int32 = (int32_t *)pcm_float; + float sum; + while (samples_left > 0) { + // Convert 16bit samples to 32bit samples + sum = 0; + for (i = 0; i < chunk_size * channel; i++) { + sum += abs(pcm_float[i + samples_written]); + + if (pcm_float[i + samples_written] > 0) { + if (flac->bit_depth == 16) { + pcm_int32[i] = (int32_t)round(fmin(pcm_float[i + samples_written] * INT16_MAX, INT16_MAX)); + } + else { // 24 bit + pcm_int32[i] = (int32_t)round(fmin(pcm_float[i + samples_written] * INT24_MAX, INT24_MAX)); + } + } + else { + if (flac->bit_depth == 16) { + pcm_int32[i] = (int32_t)round(fmax(-pcm_float[i + samples_written] * INT16_MIN, INT16_MIN)); + } + else { // 24 bit + pcm_int32[i] = (int32_t)round(fmax(-pcm_float[i + samples_written] * INT24_MIN, INT24_MIN)); + } + } + } + + // Add some noise with minimum volume in case the audio data is totaly silent. + // This makes sure the FLAC encoder returns encoded data. + // Otherwise, if the encoder receives 100 % silence, no encoded audio data + // would be send to the streaming server and thus would drop the connection. + if (sum == 0) { + for (i = 0; i < chunk_size * channel; i++) { + pcm_int32[i] = (rand() % 3) - 1; + } + } + + FLAC__stream_encoder_process_interleaved(flac->encoder, pcm_int32, chunk_size); + + samples_written += chunk_size * channel; + samples_left -= chunk_size; + + if (samples_left < chunk_size) { + chunk_size = samples_left; + } + } + + if (flac->state == FLAC_STATE_NEW_SONG_AVAILABLE) { + FLAC__stream_encoder_finish(flac->encoder); + flac->state = FLAC_STATE_UPDATE_META_DATA; + } + + bytes_written = (int)(g_enc_p - enc_buf); + + return bytes_written; +} + +int flac_enc_get_samplerate(flac_enc *flac) +{ + return FLAC__stream_encoder_get_sample_rate(flac->encoder); +} + +int flac_enc_reinit(flac_enc *flac) +{ + flac_enc_close(flac); + return flac_enc_init(flac); +} + +void flac_enc_close_file(flac_enc *flac) +{ + if (flac->encoder != NULL) { + FLAC__stream_encoder_finish(flac->encoder); + flac_enc_close(flac); + } +} + +void flac_enc_close(flac_enc *flac) +{ + if (flac->encoder != NULL) { + FLAC__stream_encoder_delete(flac->encoder); + } + + flac->encoder = NULL; +} + +void progress_callback(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, + unsigned total_frames_estimate, void *client_data) +{ + g_bytes_written = bytes_written; +} + +FLAC__StreamEncoderWriteStatus ogg_stream_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, + unsigned current_frame, void *client_data) +{ + if (current_frame == 0) { + // assemble header + memcpy(g_hdr_p, buffer, bytes); + g_hdr_p += bytes; + g_hdr_size += bytes; + return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; + } + + if (g_enc_p != NULL) { + memcpy(g_enc_p, buffer, bytes); + g_enc_p += bytes; + } + + return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; +} + +FLAC__uint64 flac_enc_get_bytes_written(void) +{ + return g_bytes_written; +} diff --git a/src/flac_encode.h b/src/flac_encode.h new file mode 100644 index 0000000..3fd4b16 --- /dev/null +++ b/src/flac_encode.h @@ -0,0 +1,55 @@ +// flac encoding functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef FLAC_ENCODE_H +#define FLAC_ENCODE_H + +#include + +#define FLAC_ENC_TYPE_REC 0 +#define FLAC_ENC_TYPE_STREAM 1 + +#define FLAC_STATE_OK 0 +#define FLAC_STATE_NEW_SONG_AVAILABLE 1 +#define FLAC_STATE_UPDATE_META_DATA 2 + +struct flac_enc { + FLAC__StreamEncoder *encoder; + int bitrate; + int samplerate; + int channel; + int enc_type; + char song_title[256]; + int state; + int bit_depth; + FLAC__StreamMetadata vorbis_comment; +}; + +int flac_enc_init(flac_enc *flac); +int flac_enc_init_FILE(flac_enc *flac, FILE *fout); +int flac_enc_encode(flac_enc *flac, float *pcm_buf, int samples_per_chan, int channel); +int flac_enc_encode_stream(flac_enc *flac, float *pcm_buf, uint8_t *enc_buf, int samples_per_chan, int channel, int new_stream); +FLAC__bool flac_enc_init_ogg_stream(flac_enc *flac); + +void flac_update_song_title(flac_enc *flac, char *song_title); +void flac_set_initial_song_title(flac_enc *flac, char *song_title); + +int flac_enc_get_samplerate(flac_enc *flac); +int flac_enc_reinit(flac_enc *flac); +FLAC__uint64 flac_enc_get_bytes_written(void); +void flac_enc_close(flac_enc *flac); +void flac_enc_close_file(flac_enc *flac); + +#endif diff --git a/src/icecast.cpp b/src/icecast.cpp new file mode 100644 index 0000000..a899bb2 --- /dev/null +++ b/src/icecast.cpp @@ -0,0 +1,766 @@ +// icecast functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include +#include + +#ifdef WIN32 +#include +#define usleep(us) Sleep(us / 1000) +// #define close(s) closesocket(s) +#else +#include +#include +#include +#include //defines IPPROTO_TCP on BSD +#include +#endif + +#include + +#include "config.h" +#include "gettext.h" +#include "cfg.h" +#include "butt.h" +#include "util.h" +#include "timer.h" +#include "icecast.h" +#include "strfuncs.h" +#include "sockfuncs.h" +#include "parseconfig.h" +#include "fl_funcs.h" +#include "url.h" +#include "flgui.h" +#include "cJSON.h" +#include "uri_encode.h" + +#ifdef HAVE_LIBSSL +#include "tls.h" +#endif + +#ifdef HAVE_LIBSSL +tls_t stream_tls; +#endif + +int server_type = IC_TYPE_UNKNOWN; + +int ic_recv(char *buf, int buf_len); + +int ic_connect(void) +{ + int ret; + int retval; + int tries = 2; + int opus_supported = 0; + char auth[150]; + char b64_auth[200]; + char recv_buf[1000]; + char send_buf[2048]; + char msg[256]; + char *b64_enc; + char *http_retval; + static bool error_printed = 0; + + server_type = IC_TYPE_UNKNOWN; + memset(recv_buf, 0, sizeof(recv_buf)); + + for (int try_cnt = 0; try_cnt < tries; try_cnt++) { + if (cfg.srv[cfg.selected_srv]->icecast_protocol == ICECAST_PROTOCOL_SOURCE) { + try_cnt++; // Start with SOURCE method and skip PUT try + } + stream_socket = sock_connect(cfg.srv[cfg.selected_srv]->addr, cfg.srv[cfg.selected_srv]->port, SOCK_PROTO_TCP, CONN_TIMEOUT); + + if (stream_socket < 0) { + switch (stream_socket) { + case SOCK_ERR_CREATE: + if (!error_printed) { + print_info(_("\nconnect: Could not create network socket"), 1); + error_printed = 1; + } + if (cfg.main.force_reconnecting == 1) { + ret = IC_RETRY; + } + else { + ret = IC_ABORT; + } + break; + case SOCK_ERR_RESOLVE: + if (!error_printed) { + print_info(_("\nconnect: Error resolving server address"), 1); + error_printed = 1; + } + ret = IC_RETRY; + break; + case SOCK_TIMEOUT: + case SOCK_INVALID: + ret = IC_RETRY; + break; + default: + if (cfg.main.force_reconnecting == 1) { + ret = IC_RETRY; + } + else { + ret = IC_ABORT; + } + break; + } + + return ret; + } + +#ifdef HAVE_LIBSSL + if (cfg.srv[cfg.selected_srv]->tls == 1) { + stream_tls.host = cfg.srv[cfg.selected_srv]->addr; + stream_tls.socket = stream_socket; + stream_tls.cert_file = cfg.tls.cert_file; + stream_tls.cert_dir = cfg.tls.cert_dir; + + if ((ret = tls_setup(&stream_tls)) != TLS_OK) { + // Check if the user wants to ignore a certificate verification error + int ignore_verfication_error; + if ((cfg.srv[cfg.selected_srv]->cert_hash != NULL) && (!strcmp(stream_tls.sha256, cfg.srv[cfg.selected_srv]->cert_hash))) { + ignore_verfication_error = 1; + } + else { + ignore_verfication_error = 0; + } + + if (ret == TLS_TIMEOUT) { + print_info(_("\nconnect: SSL connection timed out. Trying again..."), 1); + ic_disconnect(); + return IC_RETRY; + } + else if ((ret == TLS_CHECK_CERT) || (ret == TLS_CHECK_HOST)) { + if (ignore_verfication_error == 0) { + snprintf(msg, sizeof(msg), + _("SSL/TLS certificate verification failed\nReason: %s\n\n" + "Do you still want to trust this certificate?\n" + "Trusting will be permanent and can be revoked\n" + "in the server settings."), + stream_tls.last_err); + + ask_user_set_msg(msg); + ask_user_set_hash(stream_tls.sha256); + ic_disconnect(); + return IC_ASK; + } + } + else { + if (!error_printed) { + snprintf(msg, sizeof(msg), + _("\nconnect: SSL connection failed\n" + "Reason: %s"), + stream_tls.last_err); + print_info(msg, 1); + } + ic_disconnect(); + if (cfg.main.force_reconnecting == 1) { + error_printed = 1; + return IC_RETRY; + } + else { + return IC_ABORT; + } + } + } + } +#endif // HAVE_LIBSSL + if (try_cnt == 0) { + // Try PUT method first. Supported since icecast 2.4.0 + if (cfg.srv[cfg.selected_srv]->mount[0] != '/') { + snprintf(send_buf, sizeof(send_buf), "PUT /%s HTTP/1.1\r\n", cfg.srv[cfg.selected_srv]->mount); + } + else { + snprintf(send_buf, sizeof(send_buf), "PUT %s HTTP/1.1\r\n", cfg.srv[cfg.selected_srv]->mount); + } + + opus_supported = 1; + } + else { + if (cfg.srv[cfg.selected_srv]->mount[0] != '/') { + snprintf(send_buf, sizeof(send_buf), "SOURCE /%s HTTP/1.0\r\n", cfg.srv[cfg.selected_srv]->mount); + } + else { + snprintf(send_buf, sizeof(send_buf), "SOURCE %s HTTP/1.0\r\n", cfg.srv[cfg.selected_srv]->mount); + } + } + + snprintf(auth, sizeof(auth), "%s:%s", cfg.srv[cfg.selected_srv]->usr, cfg.srv[cfg.selected_srv]->pwd); + b64_enc = util_base64_enc(auth); + snprintf(b64_auth, sizeof(b64_auth), "%s", b64_enc); + free(b64_enc); + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "Authorization: Basic %s\r\n", b64_auth); + + // Make butt compatible to proxies/load balancers. Thanks to boyska + if (cfg.srv[cfg.selected_srv]->port == 80) { + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "Host: %s\r\n", cfg.srv[cfg.selected_srv]->addr); + } + else { + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "Host: %s:%d\r\n", cfg.srv[cfg.selected_srv]->addr, + cfg.srv[cfg.selected_srv]->port); + } + + // ic_send(send_buf, (int)strlen(send_buf)); + + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "User-Agent: %s\r\n", PACKAGE_STRING); + // ic_send(send_buf, (int)strlen(send_buf)); + + if (!strcmp(cfg.audio.codec, "mp3")) { + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "Content-Type: audio/mpeg\r\n"); + } + else if (!strcmp(cfg.audio.codec, "aac")) { + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "Content-Type: audio/aac\r\n"); + } + else { + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "Content-Type: audio/ogg\r\n"); + } + + // Do not send bitrate information if flac is used + if (strcmp(cfg.audio.codec, "flac")) { + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "ice-bitrate: %d\r\n", cfg.audio.bitrate); + } + + if (cfg.main.num_of_icy > 0) { + char *icy_name = strdup(cfg.icy[cfg.selected_icy]->name); + if (cfg.icy[cfg.selected_icy]->expand_variables == 1) { + expand_string(&icy_name); + strrpl(&icy_name, (char *)"%N", cfg.srv[cfg.selected_srv]->name, MODE_ALL); + } + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "ice-name: %s\r\n", icy_name); + free(icy_name); + } + else { + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "ice-name: no name\r\n"); + } + + if (cfg.main.num_of_icy > 0) { + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "ice-public: %s\r\n", cfg.icy[cfg.selected_icy]->pub); + } + else { + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "ice-public: 0\r\n"); + } + + if (cfg.main.num_of_icy > 0) { + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "ice-url: %s\r\n", cfg.icy[cfg.selected_icy]->url); + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "ice-genre: %s\r\n", cfg.icy[cfg.selected_icy]->genre); + + if (cfg.icy[cfg.selected_icy]->desc != NULL && strlen(cfg.icy[cfg.selected_icy]->desc) > 0) { + char *icy_desc = strdup(cfg.icy[cfg.selected_icy]->desc); + if (cfg.icy[cfg.selected_icy]->expand_variables == 1) { + expand_string(&icy_desc); + strrpl(&icy_desc, (char *)"%N", cfg.srv[cfg.selected_srv]->name, MODE_ALL); + } + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "ice-description: %s\r\n", icy_desc); + free(icy_desc); + } + } + + // Send audio settings + if (!strcmp(cfg.audio.codec, "flac")) { // Do not send bitrate information if flac is used + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), + "ice-audio-info: " + "ice-channels=%d;" + "ice-samplerate=%d" + "\r\n", + cfg.audio.channel, strcmp(cfg.audio.codec, "opus") == 0 ? 48000 : cfg.audio.samplerate); + } + else { + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), + "ice-audio-info: " + "ice-bitrate=%d;" + "ice-channels=%d;" + "ice-samplerate=%d" + "\r\n", + cfg.audio.bitrate, cfg.audio.channel, strcmp(cfg.audio.codec, "opus") == 0 ? 48000 : cfg.audio.samplerate); + } + + // ic_send(send_buf, (int)strlen(send_buf)); + + if (try_cnt == 0) // PUT + { + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "Expect: 100-continue\r\n"); + // ic_send(send_buf, (int)strlen(send_buf)); + } + + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "\r\n"); + + ic_send(send_buf, (int)strlen(send_buf)); + + ret = ic_recv(recv_buf, sizeof(recv_buf) - 1); + + // MARK: DEBUG + // sprintf(recv_buf, "FOOHTTP/1.1 100 Continue\nContent-Length: 0\r\n\r\n"); + // print_info(recv_buf, 1); + + if (ret == SOCK_ERR_RECV) { + if (try_cnt == 0) { + ic_disconnect(); + continue; // try SOURCE method if PUT method did not work + } + else { + usleep(100 * 1000); + ic_disconnect(); + return IC_RETRY; + } + } + if (ret == SOCK_TIMEOUT) { + print_info(_("\nconnect: connection timed out. Trying again..."), 1); + usleep(100 * 1000); + ic_disconnect(); + return IC_RETRY; + } + if (ret < 0) { + // print_info("\nconnect: error while receiving server response\nThe server might require SSL/TLS", 1); + usleep(100 * 1000); + ic_disconnect(); + return IC_RETRY; + } + + char *temp = strdup(recv_buf); + // We need to extract the HTTP return value from the HTTP response + // to see if the login was successfull (HTTP/1.0 200 OK) + http_retval = strchr(temp, ' '); + if (http_retval == NULL) { + usleep(100 * 1000); + ic_disconnect(); + free(temp); + return IC_RETRY; + } + // point to the beginning of the HTTP return value + http_retval++; + http_retval[3] = '\0'; + + retval = atoi(http_retval); + free(temp); + + // Workaround for liquidsoap, icecast-kh and AIS Streaming Server (used by iHeart.com) + if (retval == 100) { + if (strstr(recv_buf, " 401 ") != NULL) { // Wrong password + retval = 401; + } + + if (strstr(recv_buf, " 403 ") != NULL) { // Mounpoint in use (Needed since kh14) + retval = 403; + } + + if (strstr(recv_buf, " 400 ") != NULL) { // AIS Streaming Server always answers with code 400 when PUT method is used + retval = 400; + } + } + + if (retval != 200 && retval != 100) { + switch (retval) { + case 400: + if (try_cnt == 0) { + ic_disconnect(); // This brings compatibility wit AIS Streaming Server. Because they don't understand the PUT method they answer with an 400 + opus_supported = 1; + usleep(100000); + continue; // Let's try the SOURCE method then... + } + print_info(_("\nconnect: server answered with 400!\n"), 1); + ic_disconnect(); + return IC_ABORT; + break; + case 401: + if (!error_printed) { + print_info(_("\nconnect: invalid user/password!\n"), 1); + } + ic_disconnect(); + if (cfg.main.force_reconnecting == 1) { + error_printed = 1; + return IC_RETRY; + } + else { + return IC_ABORT; + } + break; + case 403: // mountpoint already in use + usleep(100000); + ic_disconnect(); + return IC_RETRY; + break; + case 404: + if (try_cnt == 0) { + ic_disconnect(); // This brings compatibility to airtime server. Because they don't understand the PUT method they answer with an 404 + opus_supported = 1; // Airtimes supports Opus + usleep(100000); + continue; // Let's try the SOURCE method then... + } + print_info(_("\nconnect: server answered with 404!\n"), 1); + + ic_disconnect(); + return IC_ABORT; + break; + default: + if (!error_printed) { + snprintf(msg, sizeof(msg), _("\nconnect: server answered with %d!\n"), retval); + print_info(msg, 1); + } + ic_disconnect(); + if (cfg.main.force_reconnecting == 1) { + error_printed = 1; + return IC_RETRY; + } + else { + return IC_ABORT; + } + } + } + + // At this point the connection has been established and encoded data + // can be send to the server + + // In case Opus is selected we need to verifiy if it is supported by + // the server + if (!strcmp(cfg.audio.codec, "opus")) { + if (opus_supported == 1) // The server has at least version 2.4.0 (PUT method worked) or it is an airtime server -> opus is supported. + { + break; + } + else { + print_info(_("\nERROR: Opus is not supported by your\nIcecast server (>=1.4.0 required)!\n"), 1); + ic_disconnect(); + return IC_ABORT; + } + } + + break; + } + + connected = 1; + error_printed = 0; + + timer_init(&stream_timer, 1); // starts the "online" timer + timer_start(&stream_timer); + + return IC_OK; +} + +int ic_send(char *buf, int buf_len) +{ + int ret; + if (cfg.srv[cfg.selected_srv]->tls == 1) { +#ifdef HAVE_LIBSSL + ret = tls_send(&stream_tls, buf, buf_len, SEND_TIMEOUT); + if (ret == TLS_SENDERR) +#endif + ret = -1; + } + else { + ret = sock_send(stream_socket, buf, buf_len, SEND_TIMEOUT); + if (ret == SOCK_TIMEOUT) { + ret = -1; + } + } + + return ret; +} + +int ic_recv(char *buf, int buf_len) +{ + int ret; + if (cfg.srv[cfg.selected_srv]->tls == 1) { +#ifdef HAVE_LIBSSL + ret = tls_recv(&stream_tls, buf, buf_len, 5 * RECV_TIMEOUT); + if (ret != TLS_TIMEOUT) + return ret; + else +#endif + return SOCK_TIMEOUT; + } + else { + return sock_recv(stream_socket, buf, buf_len, 5 * RECV_TIMEOUT); + } +} + +int ic_update_song(char *song_name) +{ + int ret; + int web_socket; + char send_buf[1024]; + char auth[150]; + char *song_buf; + char *mount; + char *b64_enc; +#ifdef HAVE_LIBSSL + tls_t web_tls; +#endif + + web_socket = sock_connect(cfg.srv[cfg.selected_srv]->addr, cfg.srv[cfg.selected_srv]->port, SOCK_PROTO_TCP, CONN_TIMEOUT); + + if (web_socket < 0) { + switch (web_socket) { + case SOCK_ERR_CREATE: + print_info(_("\nupdate_song: could not create network socket"), 1); + ret = IC_ABORT; + break; + case SOCK_ERR_RESOLVE: + print_info(_("\nupdate_song: error resolving server address"), 1); + ret = IC_ABORT; + break; + case SOCK_TIMEOUT: + case SOCK_INVALID: + ret = IC_RETRY; + break; + default: + ret = IC_ABORT; + } + + return ret; + } + +#ifdef HAVE_LIBSSL + if (cfg.srv[cfg.selected_srv]->tls == 1) { + web_tls.host = cfg.srv[cfg.selected_srv]->addr; + web_tls.socket = web_socket; + web_tls.cert_file = cfg.tls.cert_file; + web_tls.cert_dir = cfg.tls.cert_dir; + web_tls.skip_verification = 0; + + if ((cfg.srv[cfg.selected_srv]->cert_hash != NULL) && (!strcmp(stream_tls.sha256, cfg.srv[cfg.selected_srv]->cert_hash))) { + web_tls.skip_verification = 1; + } + + if (tls_setup(&web_tls) != TLS_OK) { + sock_close(web_socket); + return IC_ABORT; + } + } +#endif + + song_buf = (char *)malloc(strlen(song_name) * 3 + 1); + uri_encode(song_name, strlen(song_name), song_buf); + + mount = (char *)malloc(strlen(cfg.srv[cfg.selected_srv]->mount) + 2); + + if (cfg.srv[cfg.selected_srv]->mount[0] != '/') { + sprintf(mount, "/%s", cfg.srv[cfg.selected_srv]->mount); + } + else { + strcpy(mount, cfg.srv[cfg.selected_srv]->mount); + } + + snprintf(auth, sizeof(auth), "%s:%s", cfg.srv[cfg.selected_srv]->usr, cfg.srv[cfg.selected_srv]->pwd); + b64_enc = util_base64_enc(auth); + if (cfg.main.ic_charset != NULL) { + snprintf(send_buf, sizeof(send_buf), + "GET /admin/metadata?mode=updinfo&mount=%s&charset=%s&song=%s " + "HTTP/1.0\r\n" + "User-Agent: %s\r\n" + "Authorization: Basic %s\r\n", + mount, cfg.main.ic_charset, song_buf, PACKAGE_STRING, b64_enc); + } + else { + snprintf(send_buf, sizeof(send_buf), + "GET /admin/metadata?mode=updinfo&mount=%s&song=%s " + "HTTP/1.0\r\n" + "User-Agent: %s\r\n" + "Authorization: Basic %s\r\n", + mount, song_buf, PACKAGE_STRING, b64_enc); + } + free(b64_enc); + + if (cfg.srv[cfg.selected_srv]->port == 80) { + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "Host: %s\r\n\r\n", cfg.srv[cfg.selected_srv]->addr); + } + else { + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "Host: %s:%d\r\n\r\n", cfg.srv[cfg.selected_srv]->addr, + cfg.srv[cfg.selected_srv]->port); + } + + if (cfg.srv[cfg.selected_srv]->tls == 1) { +#ifdef HAVE_LIBSSL + tls_send(&web_tls, send_buf, (int)strlen(send_buf), SEND_TIMEOUT); + tls_close(&web_tls); +#endif + } + else { + sock_send(web_socket, send_buf, (int)strlen(send_buf), SEND_TIMEOUT); + } + + sock_close(web_socket); + + free(song_buf); + free(mount); + + return IC_OK; +} + +void ic_disconnect(void) +{ +#ifdef HAVE_LIBSSL + if (cfg.srv[cfg.selected_srv]->tls == 1) { + tls_close(&stream_tls); + } +#endif + + sock_close(stream_socket); +} + +int ic_parse_7_xsl_response(char *response) +{ + char *p = response; + int num_fields = 0; + while (*(p++)) { + if (*p == ',') { + num_fields++; + } + } + if (num_fields == 6) { + p = strchr(response, '>'); // Point to end of the HTML part + if (p != NULL) { + p++; // Point to the listener number + char *p2 = strchr(p, ','); // Point to the first delimiter + if (p2 != NULL) { + *p2 = '\0'; // Null terminate the listener number string + } + server_type = IC_TYPE_KH; + return atoi(p); + } + } + return -1; +} + +int ic_parse_json_xsl_response(char *response, char *mount) +{ + cJSON *answer_obj = cJSON_Parse(response); + + if (answer_obj != NULL) { + cJSON *icestats = cJSON_GetObjectItemCaseSensitive(answer_obj, "icestats"); + cJSON *sources = cJSON_GetObjectItemCaseSensitive(icestats, "source"); + + // There is more than one source connected to the icecast server, + // so we have to find the correct listeners entry by searching for our mountpoint + if (cJSON_IsArray(sources) == true) { + char tmp_mount[128]; + if (mount != NULL) { + if (strrchr(mount, '/') != NULL) { + mount++; + } + snprintf(tmp_mount, sizeof(tmp_mount), "%s", mount); + } + else { + snprintf(tmp_mount, sizeof(tmp_mount), "%s", "stream"); + } + cJSON *source; + cJSON_ArrayForEach(source, sources) + { + cJSON *listen_url = cJSON_GetObjectItemCaseSensitive(source, "listenurl"); + if (cJSON_IsString(listen_url) == true) { + char *json_mount = strrchr(cJSON_GetStringValue(listen_url), '/'); + if (json_mount != NULL) { + json_mount++; + + if (strcmp(json_mount, tmp_mount) == 0) { + cJSON *listeners = cJSON_GetObjectItemCaseSensitive(source, "listeners"); + if (cJSON_IsNumber(listeners) == true) { + int num = listeners->valueint; + cJSON_Delete(answer_obj); + return num; + } + } + } + } + } + } + else { // There is only one source is connected to the server + cJSON *listeners = cJSON_GetObjectItemCaseSensitive(sources, "listeners"); + if (cJSON_IsNumber(listeners) == true) { + int num = listeners->valueint; + cJSON_Delete(answer_obj); + return num; + } + } + } + return -1; +} + +int ic_get_listener_count_from_url(char *url, char *mount) +{ + uint32_t data_size; + char recv_buf[100 * 1024]; + + if (strstr(url, "/status-json.xsl") != NULL) { + data_size = url_get_listener_count(url, recv_buf, sizeof(recv_buf)); + if (data_size > 0) { + return ic_parse_json_xsl_response(recv_buf, mount); + } + } + else if (strstr(url, "/7.xsl") != NULL) { + data_size = url_get_listener_count(url, recv_buf, sizeof(recv_buf)); + if (data_size > 0) { + return ic_parse_7_xsl_response(recv_buf); + } + } + + return -1; +} + +int ic_get_listener_count(void) +{ + uint32_t data_size; + char url[256]; + char proto[8]; + char recv_buf[100 * 1024]; + + if (cfg.srv[cfg.selected_srv]->tls == 1) { + strncpy(proto, "https", sizeof(proto)); + } + else { + strncpy(proto, "http", sizeof(proto)); + } + + if (server_type == IC_TYPE_UNKNOWN || server_type == IC_TYPE_VANILLA) { + snprintf(url, sizeof(url), "%s://%s:%d/status-json.xsl", proto, cfg.srv[cfg.selected_srv]->addr, cfg.srv[cfg.selected_srv]->port); + data_size = url_get_listener_count(url, recv_buf, sizeof(recv_buf)); + + if (data_size > 0) { + char *mount; + if (cfg.srv[cfg.selected_srv]->custom_listener_mount != NULL && strlen(cfg.srv[cfg.selected_srv]->custom_listener_mount) > 0) { + mount = cfg.srv[cfg.selected_srv]->custom_listener_mount; + } + else { + mount = cfg.srv[cfg.selected_srv]->mount; + } + int listener = ic_parse_json_xsl_response(recv_buf, mount); + if (listener != -1) { + server_type = IC_TYPE_VANILLA; + } + return listener; + } + } + + // status-json.xsl not available (probably a icecast-kh server), try 7.xsl + // 7.xls format (first number of comma seperated string is the listeners number): + /* + + 0,1,0,unlimited,0,, + */ + + if (server_type == IC_TYPE_UNKNOWN || server_type == IC_TYPE_KH) { + snprintf(url, sizeof(url), "%s://%s:%d/7.xsl", proto, cfg.srv[cfg.selected_srv]->addr, cfg.srv[cfg.selected_srv]->port); + data_size = url_get_listener_count(url, recv_buf, sizeof(recv_buf)); + + if (data_size > 0) { + int listener = ic_parse_7_xsl_response(recv_buf); + if (listener != -1) { + server_type = IC_TYPE_KH; + } + return listener; + } + } + return -1; +} diff --git a/src/icecast.h b/src/icecast.h new file mode 100644 index 0000000..95b9e10 --- /dev/null +++ b/src/icecast.h @@ -0,0 +1,40 @@ +// icecast functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef ICECAST_H +#define ICECAST_H + +enum { + IC_OK = 0, + IC_RETRY = 1, + IC_ABORT = 2, + IC_ASK = 3, +}; + +enum { + IC_TYPE_UNKNOWN = -1, + IC_TYPE_KH = 0, + IC_TYPE_VANILLA = 1, +}; + +int ic_init(void); +int ic_connect(void); +int ic_send(char *buf, int buf_len); +int ic_update_song(char *song_name); +int ic_get_listener_count(void); +int ic_get_listener_count_from_url(char *url, char *mount); +void ic_disconnect(void); + +#endif diff --git a/src/lame_encode.cpp b/src/lame_encode.cpp new file mode 100644 index 0000000..6fd165f --- /dev/null +++ b/src/lame_encode.cpp @@ -0,0 +1,168 @@ +// lame encoding functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include + +#include "gettext.h" +#include "lame_encode.h" +#include "fl_funcs.h" + +int lame_enc_init(lame_enc *lame) +{ + int rc; + char info_buf[256]; + + lame->gfp = lame_init(); + + lame_set_num_channels(lame->gfp, lame->channel); + lame_set_in_samplerate(lame->gfp, lame->samplerate_in); + lame_set_out_samplerate(lame->gfp, lame->samplerate_out); + lame_set_brate(lame->gfp, lame->bitrate); + lame_set_quality(lame->gfp, lame->enc_quality); + lame_set_VBR_q(lame->gfp, lame->vbr_quality); + lame_set_VBR_min_bitrate_kbps(lame->gfp, lame->vbr_min_bitrate); + lame_set_VBR_mean_bitrate_kbps(lame->gfp, lame->bitrate); + lame_set_VBR_max_bitrate_kbps(lame->gfp, lame->vbr_max_bitrate); + lame_set_VBR_hard_min(lame->gfp, lame->vbr_force_min_bitrate); + + if (lame->stereo_mode > -1) { + lame_set_mode(lame->gfp, (MPEG_mode)lame->stereo_mode); + } + + if (lame->bitrate_mode == 0) { // CBR + lame_set_VBR(lame->gfp, vbr_off); + } + + if (lame->bitrate_mode == 1) { // VBR + lame_set_VBR(lame->gfp, vbr_default); + } + + if (lame->bitrate_mode == 2) { // ABR + lame_set_VBR(lame->gfp, vbr_abr); + } + + if (lame->lowpass_freq > 0) { + lame_set_lowpassfreq(lame->gfp, lame->lowpass_freq * 1000); + } + + if (lame->lowpass_width > 0) { + lame_set_lowpasswidth(lame->gfp, lame->lowpass_width * 1000); + } + + if (lame->highpass_freq > 0) { + lame_set_highpassfreq(lame->gfp, lame->highpass_freq * 1000); + } + + if (lame->highpass_width > 0) { + lame_set_highpasswidth(lame->gfp, lame->highpass_width * 1000); + } + + if ((rc = lame_init_params(lame->gfp)) < 0) { + snprintf(info_buf, sizeof(info_buf), _("unable to init lame params %d"), rc); + + print_info(info_buf, 1); + return 1; + } + + /* + printf("MP3 Quality: %d\n", lame_get_quality(lame->gfp)); + printf("MP3 Stereo Mode: %d\n", lame_get_mode(lame->gfp)); + printf("MP3 Bitrate Mode: %d\n", lame_get_VBR(lame->gfp)); + printf("MP3 vbr: %d\n", lame_get_VBR(lame->gfp)); + printf("MP3 vbr quality: %d\n", lame_get_VBR_q(lame->gfp)); + printf("MP3 vbr mean bitrate: %d\n", lame_get_VBR_mean_bitrate_kbps(lame->gfp)); + printf("MP3 vbr min bitrate: %d\n", lame_get_VBR_min_bitrate_kbps(lame->gfp)); + printf("MP3 vbr max bitrate: %d\n", lame_get_VBR_max_bitrate_kbps(lame->gfp)); + printf("MP3 lowpass freq: %d\n", lame_get_lowpassfreq(lame->gfp)); + printf("MP3 lowpass width: %d\n", lame_get_lowpasswidth(lame->gfp)); + printf("MP3 highpass freq: %d\n", lame_get_highpassfreq(lame->gfp)); + printf("MP3 highpass width: %d\n", lame_get_highpasswidth(lame->gfp)); + printf("MP3 output sample rate: %d\n", lame_get_out_samplerate(lame->gfp)); + printf("MP3 vbr force min br: %d\n", lame_get_VBR_hard_min(lame->gfp)); + printf("\n"); + */ + + // printf("MP3 bitrate: %d\n", lame->bitrate); + + lame->state = LAME_READY; + return 0; +} + +int lame_enc_reinit(lame_enc *lame) +{ + if (lame != NULL) { + lame_enc_close(lame); + return lame_enc_init(lame); + } + return 1; +} + +int lame_enc_get_samplerate(lame_enc *lame) +{ + return lame_get_out_samplerate(lame->gfp); +} + +int lame_enc_flush_file(lame_enc *lame, FILE *file) +{ + int bytes_flushed; + unsigned char buf[8192]; + + lame->state = LAME_BUSY; + bytes_flushed = lame_encode_flush(lame->gfp, (unsigned char *)buf, sizeof(buf)); + + if (bytes_flushed > 0) { + fwrite(buf, 1, bytes_flushed, file); + // lame_mp3_tags_fid(lame->gfp, file); + // lame_init_bitstream(lame->gfp); + } + + lame->state = LAME_READY; + return bytes_flushed; +} + +void lame_enc_close(lame_enc *lame) +{ + while (lame->state == LAME_BUSY) + ; + + if (lame->gfp != NULL) { + lame_close(lame->gfp); + } + + lame->gfp = NULL; +} + +int lame_enc_encode(lame_enc *lame, float *pcm_buf, char *enc_buf, int samples, int buf_size) +{ + int rc; + + if (samples == 0 || lame->gfp == NULL) { + return 0; + } + + lame->state = LAME_BUSY; + + if (lame->channel == 2) { // stereo + rc = lame_encode_buffer_interleaved_ieee_float(lame->gfp, pcm_buf, samples, (unsigned char *)enc_buf, buf_size); + } + else { // mono + rc = lame_encode_buffer_ieee_float(lame->gfp, pcm_buf, pcm_buf, samples, (unsigned char *)enc_buf, buf_size); + } + + lame->state = LAME_READY; + + return rc; +} diff --git a/src/lame_encode.h b/src/lame_encode.h new file mode 100644 index 0000000..0a3c0b4 --- /dev/null +++ b/src/lame_encode.h @@ -0,0 +1,56 @@ +// lame encoding functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef LAME_ENCODE_H +#define LAME_ENCODE_H + +#include +#include + +struct lame_enc { + lame_global_flags *gfp; + int bitrate; + int samplerate_in; + int samplerate_out; + int channel; + volatile int state; + + int enc_quality; + int stereo_mode; + int bitrate_mode; + int vbr_quality; + int vbr_min_bitrate; + int vbr_max_bitrate; + int vbr_force_min_bitrate; + + float lowpass_freq; + float lowpass_width; + float highpass_freq; + float highpass_width; +}; + +enum { + LAME_READY = 0, + LAME_BUSY = 1, +}; + +int lame_enc_init(lame_enc *lame); +int lame_enc_get_samplerate(lame_enc *lame); +int lame_enc_encode(lame_enc *lame, float *pcm_buf, char *enc_buf, int samples, int buf_size); +int lame_enc_flush_file(lame_enc *lame, FILE *file); +int lame_enc_reinit(lame_enc *lame); +void lame_enc_close(lame_enc *lame); + +#endif diff --git a/src/logos.h b/src/logos.h new file mode 100644 index 0000000..d944614 --- /dev/null +++ b/src/logos.h @@ -0,0 +1,1955 @@ +static const unsigned char radio_co_logo[] = { + 0, 0, 0, 0, 255, 255, 255, 19, 255, 255, 255, 68, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, + 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, + 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, + 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, + 255, 255, 255, 66, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, + 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, + 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, + 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 66, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, + 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, + 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, + 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, + 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 66, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, + 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, + 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, + 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 67, 255, + 255, 255, 67, 255, 255, 255, 67, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 67, 255, 255, 255, 66, 255, 255, 255, 12, 0, 0, 0, 0, + 255, 255, 255, 62, 255, 255, 255, 242, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 230, 255, 255, 255, 45, + 255, 255, 255, 223, 255, 255, 255, 255, 255, 255, 255, 249, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, + 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, + 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, + 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, + 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, + 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, + 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, + 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, + 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, + 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, + 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, + 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, + 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, + 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, + 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, + 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 248, 255, 255, 255, 255, 255, 255, 255, 194, + 255, 255, 255, 255, 255, 255, 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 254, 255, 255, 255, 254, 255, 255, + 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 254, 255, 255, 255, 254, 255, 255, + 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 254, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 233, + 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 231, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 254, 254, 254, 255, 253, 253, 253, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, + 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, + 241, 241, 241, 255, 210, 210, 210, 255, 234, 234, 234, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 254, 254, 254, 255, 222, 222, 222, 255, 247, 247, 247, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 243, 243, 243, 255, 225, + 225, 225, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 221, 221, 221, 255, + 35, 35, 35, 255, 102, 102, 102, 255, 38, 38, 38, 255, 212, 212, 212, 255, 255, 255, 255, 255, 252, 252, 252, 255, 254, 254, 254, 255, 255, 255, 255, + 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, 253, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, + 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 254, 254, 254, 255, + 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 253, 253, 253, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, 253, 255, 255, 255, + 255, 255, 251, 251, 251, 255, 66, 66, 66, 255, 226, 226, 226, 255, 255, 255, 255, 255, 252, 252, 252, 255, 255, 255, 255, 255, 208, 208, 208, 255, 98, + 98, 98, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 116, 116, 116, 255, + 174, 174, 174, 255, 255, 255, 255, 255, 237, 237, 237, 255, 245, 245, 245, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 102, 102, 102, 255, 227, 227, 227, 255, 255, 255, 255, 255, 252, 252, 252, 255, 255, 255, 255, 255, 210, 210, 210, 255, 125, + 125, 125, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 174, 174, 174, 255, + 81, 81, 81, 255, 229, 229, 229, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 252, 252, 255, 166, 166, 166, 255, 148, 148, 148, 255, 105, 105, 105, + 255, 131, 131, 131, 255, 237, 237, 237, 255, 255, 255, 255, 255, 252, 252, 252, 255, 168, 168, 168, 255, 97, 97, 97, 255, 127, 127, 127, 255, 230, 230, + 230, 255, 255, 255, 255, 255, 212, 212, 212, 255, 143, 143, 143, 255, 133, 133, 133, 255, 97, 97, 97, 255, 207, 207, 207, 255, 255, 255, 255, 255, 253, + 253, 253, 255, 178, 178, 178, 255, 103, 103, 103, 255, 137, 137, 137, 255, 244, 244, 244, 255, 255, 255, 255, 255, 201, 201, 201, 255, 105, 105, 105, 255, + 106, 106, 106, 255, 202, 202, 202, 255, 255, 255, 255, 255, 239, 239, 239, 255, 158, 158, 158, 255, 139, 139, 139, 255, 155, 155, 155, 255, 255, 255, 255, + 255, 185, 185, 185, 255, 110, 110, 110, 255, 132, 132, 132, 255, 232, 232, 232, 255, 255, 255, 255, 255, 251, 251, 251, 255, 163, 163, 163, 255, 95, 95, + 95, 255, 144, 144, 144, 255, 68, 68, 68, 255, 229, 229, 229, 255, 255, 255, 255, 255, 252, 252, 252, 255, 255, 255, 255, 255, 214, 214, 214, 255, 71, + 71, 71, 255, 143, 143, 143, 255, 91, 91, 91, 255, 178, 178, 178, 255, 255, 255, 255, 255, 180, 180, 180, 255, 196, 196, 196, 255, 255, 255, 255, 255, + 253, 253, 253, 255, 154, 154, 154, 255, 227, 227, 227, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 253, 253, 253, 255, + 174, 174, 174, 255, 34, 34, 34, 255, 123, 123, 123, 255, 243, 243, 243, 255, 255, 255, 255, 255, 61, 61, 61, 255, 142, 142, 142, 255, 233, 233, 233, + 255, 158, 158, 158, 255, 87, 87, 87, 255, 255, 255, 255, 255, 164, 164, 164, 255, 94, 94, 94, 255, 231, 231, 231, 255, 173, 173, 173, 255, 53, 53, + 53, 255, 255, 255, 255, 255, 194, 194, 194, 255, 0, 0, 0, 255, 215, 215, 215, 255, 208, 208, 208, 255, 0, 0, 0, 255, 239, 239, 239, 255, 223, + 223, 223, 255, 0, 0, 0, 255, 233, 233, 233, 255, 219, 219, 219, 255, 255, 255, 255, 255, 218, 218, 218, 255, 0, 0, 0, 255, 212, 212, 212, 255, + 212, 212, 212, 255, 0, 0, 0, 255, 222, 222, 222, 255, 244, 244, 244, 255, 0, 0, 0, 255, 170, 170, 170, 255, 245, 245, 245, 255, 201, 201, 201, + 255, 58, 58, 58, 255, 231, 231, 231, 255, 182, 182, 182, 255, 72, 72, 72, 255, 255, 255, 255, 255, 163, 163, 163, 255, 98, 98, 98, 255, 230, 230, + 230, 255, 186, 186, 186, 255, 0, 0, 0, 255, 232, 232, 232, 255, 255, 255, 255, 255, 252, 252, 252, 255, 255, 255, 255, 255, 217, 217, 217, 255, 0, + 0, 0, 255, 201, 201, 201, 255, 224, 224, 224, 255, 48, 48, 48, 255, 197, 197, 197, 255, 225, 225, 225, 255, 19, 19, 19, 255, 255, 255, 255, 255, + 217, 217, 217, 255, 62, 62, 62, 255, 252, 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 250, 250, 250, 255, 138, 138, 138, 255, 131, 131, 131, 255, 255, 255, 255, 255, 101, 101, 101, 255, 238, 238, 238, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 86, 86, 86, 255, 221, 221, 221, 255, 105, 105, 105, 255, 230, 230, 230, 255, 255, 255, 255, 255, 255, 255, 255, 255, 99, 99, + 99, 255, 225, 225, 225, 255, 200, 200, 200, 255, 146, 146, 146, 255, 255, 255, 255, 255, 255, 255, 255, 255, 137, 137, 137, 255, 193, 193, 193, 255, 254, + 254, 254, 255, 116, 116, 116, 255, 110, 110, 110, 255, 199, 199, 199, 255, 255, 255, 255, 255, 151, 151, 151, 255, 176, 176, 176, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 175, 175, 175, 255, 161, 161, 161, 255, 246, 246, 246, 255, 85, 85, 85, 255, 254, 254, 254, 255, 255, 255, 255, 255, 145, 145, 145, + 255, 93, 93, 93, 255, 145, 145, 145, 255, 134, 134, 134, 255, 85, 85, 85, 255, 229, 229, 229, 255, 98, 98, 98, 255, 231, 231, 231, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 98, 98, 98, 255, 227, 227, 227, 255, 255, 255, 255, 255, 252, 252, 252, 255, 255, 255, 255, 255, 210, 210, 210, 255, 123, + 123, 123, 255, 255, 255, 255, 255, 255, 255, 255, 255, 216, 216, 216, 255, 98, 98, 98, 255, 255, 255, 255, 255, 114, 114, 114, 255, 199, 199, 199, 255, + 147, 147, 147, 255, 185, 185, 185, 255, 255, 255, 255, 255, 252, 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 200, 200, 200, 255, + 237, 237, 237, 255, 255, 255, 255, 255, 211, 211, 211, 255, 73, 73, 73, 255, 255, 255, 255, 255, 94, 94, 94, 255, 217, 217, 217, 255, 255, 255, 255, + 255, 235, 235, 235, 255, 35, 35, 35, 255, 239, 239, 239, 255, 114, 114, 114, 255, 195, 195, 195, 255, 255, 255, 255, 255, 245, 245, 245, 255, 38, 38, + 38, 255, 238, 238, 238, 255, 198, 198, 198, 255, 139, 139, 139, 255, 255, 255, 255, 255, 255, 255, 255, 255, 149, 149, 149, 255, 190, 190, 190, 255, 255, + 255, 255, 255, 249, 249, 249, 255, 233, 233, 233, 255, 44, 44, 44, 255, 206, 206, 206, 255, 189, 189, 189, 255, 125, 125, 125, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 127, 127, 127, 255, 183, 183, 183, 255, 245, 245, 245, 255, 85, 85, 85, 255, 244, 244, 244, 255, 255, 255, 255, 255, 158, 158, 158, + 255, 146, 146, 146, 255, 255, 255, 255, 255, 246, 246, 246, 255, 233, 233, 233, 255, 255, 255, 255, 255, 99, 99, 99, 255, 196, 196, 196, 255, 255, 255, + 255, 255, 247, 247, 247, 255, 76, 76, 76, 255, 229, 229, 229, 255, 255, 255, 255, 255, 252, 252, 252, 255, 255, 255, 255, 255, 213, 213, 213, 255, 99, + 99, 99, 255, 255, 255, 255, 255, 255, 255, 255, 255, 174, 174, 174, 255, 125, 125, 125, 255, 255, 255, 255, 255, 217, 217, 217, 255, 0, 0, 0, 255, + 90, 90, 90, 255, 245, 245, 245, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 146, 146, 146, 255, + 46, 46, 46, 255, 136, 136, 136, 255, 0, 0, 0, 255, 195, 195, 195, 255, 255, 255, 255, 255, 95, 95, 95, 255, 67, 67, 67, 255, 151, 151, 151, + 255, 43, 43, 43, 255, 169, 169, 169, 255, 255, 255, 255, 255, 214, 214, 214, 255, 17, 17, 17, 255, 147, 147, 147, 255, 74, 74, 74, 255, 152, 152, + 152, 255, 255, 255, 255, 255, 182, 182, 182, 255, 131, 131, 131, 255, 255, 255, 255, 255, 255, 255, 255, 255, 132, 132, 132, 255, 194, 194, 194, 255, 234, + 234, 234, 255, 92, 92, 92, 255, 181, 181, 181, 255, 79, 79, 79, 255, 216, 216, 216, 255, 252, 252, 252, 255, 84, 84, 84, 255, 122, 122, 122, 255, + 122, 122, 122, 255, 89, 89, 89, 255, 251, 251, 251, 255, 236, 236, 236, 255, 57, 57, 57, 255, 247, 247, 247, 255, 255, 255, 255, 255, 239, 239, 239, + 255, 90, 90, 90, 255, 156, 156, 156, 255, 144, 144, 144, 255, 133, 133, 133, 255, 255, 255, 255, 255, 214, 214, 214, 255, 0, 0, 0, 255, 143, 143, + 143, 255, 111, 111, 111, 255, 0, 0, 0, 255, 230, 230, 230, 255, 255, 255, 255, 255, 252, 252, 252, 255, 255, 255, 255, 255, 215, 215, 215, 255, 0, + 0, 0, 255, 126, 126, 126, 255, 134, 134, 134, 255, 34, 34, 34, 255, 228, 228, 228, 255, 255, 255, 255, 255, 255, 255, 255, 255, 97, 97, 97, 255, + 164, 164, 164, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 221, 221, 221, 255, 190, 190, 190, 255, 223, 223, 223, 255, 255, 255, 255, 255, 253, 253, 253, 255, 110, 110, 110, 255, 205, 205, 205, 255, 198, 198, 198, + 255, 217, 217, 217, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 235, 235, 235, 255, 190, 190, 190, 255, 215, 215, 215, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 236, 236, 236, 255, 227, 227, 227, 255, 255, 255, 255, 255, 255, 255, 255, 255, 228, 228, 228, 255, 237, 237, 237, 255, 255, + 255, 255, 255, 219, 219, 219, 255, 185, 185, 185, 255, 225, 225, 225, 255, 255, 255, 255, 255, 255, 255, 255, 255, 249, 249, 249, 255, 199, 199, 199, 255, + 199, 199, 199, 255, 249, 249, 249, 255, 255, 255, 255, 255, 248, 248, 248, 255, 221, 221, 221, 255, 253, 253, 253, 255, 254, 254, 254, 255, 255, 255, 255, + 255, 246, 246, 246, 255, 195, 195, 195, 255, 199, 199, 199, 255, 245, 245, 245, 255, 255, 255, 255, 255, 255, 255, 255, 255, 234, 234, 234, 255, 190, 190, + 190, 255, 219, 219, 219, 255, 222, 222, 222, 255, 246, 246, 246, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 243, 243, 243, 255, 223, + 223, 223, 255, 214, 214, 214, 255, 191, 191, 191, 255, 241, 241, 241, 255, 255, 255, 255, 255, 255, 255, 255, 255, 247, 247, 247, 255, 81, 81, 81, 255, + 233, 233, 233, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 80, 80, 80, 255, 232, 232, 232, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 251, 251, 251, 255, 255, 255, 255, 255, 175, 175, 175, 255, 124, 124, 124, 255, + 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 254, 254, 255, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 255, 255, 255, 255, 254, 254, 254, 255, 145, 145, 145, 255, 232, 232, 232, 255, 255, 255, 255, + 255, 252, 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, 253, 255, 253, 253, 253, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, + 255, 255, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, 253, 255, + 253, 253, 253, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 254, 254, 254, 255, 253, 253, 253, 255, 253, 253, 253, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, + 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, + 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 142, 142, 142, 255, 220, 220, 220, 255, + 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, + 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 252, 243, 243, 255, 253, 248, 248, 255, 255, 255, 255, 255, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 254, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 241, + 197, 197, 255, 224, 87, 87, 255, 226, 110, 110, 255, 245, 218, 218, 255, 255, 255, 255, 255, 255, 254, 254, 255, 254, 253, 253, 255, 255, 254, 254, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 254, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 243, 243, 255, 222, + 71, 71, 255, 222, 77, 77, 255, 220, 44, 44, 255, 228, 124, 124, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 254, 253, 253, 255, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 254, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 247, 225, 225, 255, 237, 181, 181, 255, 255, 255, 255, 255, 252, 244, 244, 255, 224, + 97, 97, 255, 223, 84, 84, 255, 222, 70, 70, 255, 229, 132, 132, 255, 255, 255, 255, 255, 251, 241, 241, 255, 237, 178, 178, 255, 251, 240, 240, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 252, 243, 243, 255, 235, 172, 172, 255, 221, 55, 55, 255, 223, 74, 74, 255, 254, 249, 249, 255, 252, 246, 246, 255, 224, + 91, 91, 255, 223, 82, 82, 255, 222, 65, 65, 255, 228, 129, 129, 255, 255, 255, 255, 255, 248, 229, 229, 255, 219, 0, 0, 255, 224, 93, 93, 255, + 240, 192, 192, 255, 254, 252, 252, 255, 255, 255, 255, 255, 255, 254, 254, 255, 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 255, 255, 255, 255, 254, 253, + 253, 255, 240, 195, 195, 255, 224, 93, 93, 255, 221, 43, 43, 255, 222, 78, 78, 255, 226, 107, 107, 255, 254, 250, 250, 255, 252, 245, 245, 255, 224, + 91, 91, 255, 223, 83, 83, 255, 222, 65, 65, 255, 228, 129, 129, 255, 255, 255, 255, 255, 248, 231, 231, 255, 222, 75, 75, 255, 223, 81, 81, 255, + 220, 31, 31, 255, 227, 119, 119, 255, 244, 213, 213, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, 253, 255, 254, 254, 254, 255, 255, 255, 255, + 255, 253, 253, 253, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 245, 217, 217, 255, 227, 122, + 122, 255, 220, 31, 31, 255, 222, 78, 78, 255, 224, 92, 92, 255, 222, 75, 75, 255, 225, 101, 101, 255, 254, 250, 250, 255, 252, 246, 246, 255, 224, + 91, 91, 255, 223, 83, 83, 255, 222, 65, 65, 255, 228, 129, 129, 255, 255, 255, 255, 255, 248, 230, 230, 255, 221, 63, 63, 255, 223, 86, 86, 255, + 224, 91, 91, 255, 222, 68, 68, 255, 221, 42, 42, 255, 231, 147, 147, 255, 249, 233, 233, 255, 255, 255, 255, 255, 255, 254, 254, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 255, 255, 255, 255, 255, 241, 200, 200, 255, 219, 0, 0, 255, 222, 70, + 70, 255, 224, 90, 90, 255, 223, 84, 84, 255, 223, 83, 83, 255, 222, 74, 74, 255, 225, 103, 103, 255, 254, 250, 250, 255, 252, 245, 245, 255, 224, + 91, 91, 255, 223, 83, 83, 255, 222, 65, 65, 255, 228, 129, 129, 255, 255, 255, 255, 255, 248, 231, 231, 255, 222, 65, 65, 255, 223, 84, 84, 255, + 223, 81, 81, 255, 223, 86, 86, 255, 223, 89, 89, 255, 221, 53, 53, 255, 222, 63, 63, 255, 248, 227, 227, 255, 255, 255, 255, 255, 255, 254, 254, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 250, 250, 255, 231, 232, 232, 255, 230, 230, 230, 255, 242, 242, 242, 255, 255, 255, 255, + 255, 212, 212, 213, 255, 233, 233, 233, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 229, 132, 132, 255, 221, 63, 63, 255, 224, 91, + 91, 255, 223, 81, 81, 255, 223, 82, 82, 255, 223, 84, 84, 255, 223, 81, 81, 255, 225, 97, 97, 255, 253, 249, 249, 255, 252, 245, 245, 255, 224, + 90, 90, 255, 223, 83, 83, 255, 222, 66, 66, 255, 228, 128, 128, 255, 255, 255, 255, 255, 248, 229, 229, 255, 221, 61, 61, 255, 224, 90, 90, 255, + 223, 81, 81, 255, 223, 82, 82, 255, 223, 81, 81, 255, 224, 96, 96, 255, 220, 31, 31, 255, 236, 174, 174, 255, 255, 255, 255, 255, 254, 253, 253, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 253, 253, + 253, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 254, + 254, 254, 255, 254, 254, 254, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, + 253, 253, 253, 255, 252, 252, 252, 255, 255, 255, 255, 255, 228, 228, 228, 255, 0, 0, 0, 255, 0, 0, 0, 255, 172, 172, 172, 255, 193, 193, 193, + 255, 0, 0, 0, 255, 47, 48, 50, 255, 239, 239, 239, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 253, 253, 253, 255, 253, 253, + 253, 255, 253, 253, 253, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 254, 254, 254, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 253, 253, 253, + 255, 253, 253, 253, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 229, 136, 136, 255, 221, 63, 63, 255, 223, 86, + 86, 255, 223, 82, 82, 255, 223, 82, 82, 255, 223, 86, 86, 255, 220, 27, 27, 255, 227, 118, 118, 255, 254, 252, 252, 255, 252, 246, 246, 255, 224, + 94, 94, 255, 223, 82, 82, 255, 222, 64, 64, 255, 229, 133, 133, 255, 255, 255, 255, 255, 249, 235, 235, 255, 222, 70, 70, 255, 221, 59, 59, 255, + 223, 86, 86, 255, 223, 81, 81, 255, 223, 82, 82, 255, 223, 88, 88, 255, 221, 46, 46, 255, 236, 172, 172, 255, 255, 255, 255, 255, 254, 254, 254, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, 253, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 227, 227, 227, 255, 0, 0, 0, 255, 0, 0, 0, 255, 175, 175, 175, 255, 184, 184, 184, + 255, 0, 0, 0, 255, 0, 0, 0, 255, 234, 234, 235, 255, 255, 255, 255, 255, 252, 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 229, 135, 135, 255, 221, 61, 61, 255, 223, 87, + 87, 255, 223, 82, 82, 255, 223, 86, 86, 255, 222, 67, 67, 255, 234, 167, 167, 255, 252, 245, 245, 255, 255, 255, 255, 255, 249, 231, 231, 255, 222, + 73, 73, 255, 223, 87, 87, 255, 222, 72, 72, 255, 226, 114, 114, 255, 254, 251, 251, 255, 255, 255, 255, 255, 249, 234, 234, 255, 229, 138, 138, 255, + 222, 68, 68, 255, 223, 86, 86, 255, 223, 81, 81, 255, 224, 89, 89, 255, 220, 41, 41, 255, 236, 173, 173, 255, 255, 255, 255, 255, 254, 253, 253, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 250, 250, 255, 246, 246, 246, 255, 247, 247, 247, 255, 255, 255, 255, 255, 221, 221, + 221, 255, 236, 236, 236, 255, 255, 255, 255, 255, 255, 255, 255, 255, 247, 247, 247, 255, 217, 217, 217, 255, 208, 208, 208, 255, 218, 218, 219, 255, 252, + 252, 252, 255, 252, 252, 252, 255, 245, 245, 245, 255, 247, 247, 247, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 239, 239, 239, 255, + 214, 214, 214, 255, 211, 211, 211, 255, 243, 243, 243, 255, 235, 235, 235, 255, 0, 0, 0, 255, 0, 0, 0, 255, 166, 166, 166, 255, 251, 251, 252, + 255, 170, 170, 170, 255, 206, 206, 206, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 253, 253, 253, 255, 224, 224, 224, 255, 212, 212, + 212, 255, 216, 216, 216, 255, 242, 242, 242, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 251, 251, 251, 255, 221, 221, 221, 255, 211, 212, 212, 255, 220, 220, 220, 255, 248, 248, 248, 255, + 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 232, 233, 233, 255, 213, 213, 213, + 255, 213, 213, 214, 255, 232, 232, 232, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 229, 135, 135, 255, 221, 61, 61, 255, 223, 87, + 87, 255, 223, 83, 83, 255, 223, 80, 80, 255, 224, 85, 85, 255, 253, 245, 245, 255, 255, 255, 255, 255, 244, 211, 211, 255, 226, 110, 110, 255, 222, + 74, 74, 255, 223, 84, 84, 255, 223, 85, 85, 255, 222, 70, 70, 255, 229, 135, 135, 255, 247, 227, 227, 255, 255, 255, 255, 255, 246, 222, 222, 255, + 221, 44, 44, 255, 223, 88, 88, 255, 223, 81, 81, 255, 224, 89, 89, 255, 220, 41, 41, 255, 236, 172, 172, 255, 255, 255, 255, 255, 254, 253, 253, + 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 176, 176, 176, 255, 0, 0, 0, 255, 94, 95, 95, 255, 145, 146, 146, 255, 0, 0, + 0, 255, 191, 191, 191, 255, 255, 255, 255, 255, 198, 198, 198, 255, 61, 62, 63, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 124, + 124, 125, 255, 126, 127, 128, 255, 30, 31, 32, 255, 98, 99, 99, 255, 247, 247, 247, 255, 255, 255, 255, 255, 172, 172, 173, 255, 0, 0, 3, 255, + 0, 0, 0, 255, 0, 0, 0, 255, 57, 58, 59, 255, 146, 147, 147, 255, 47, 48, 49, 255, 0, 0, 0, 255, 171, 171, 172, 255, 176, 177, 177, + 255, 76, 77, 77, 255, 86, 87, 88, 255, 223, 223, 223, 255, 255, 255, 255, 255, 215, 215, 215, 255, 96, 97, 98, 255, 0, 0, 0, 255, 0, 0, + 0, 255, 0, 0, 0, 255, 44, 45, 47, 255, 175, 175, 175, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 254, + 254, 254, 255, 255, 255, 255, 255, 210, 210, 211, 255, 84, 85, 86, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 71, 72, 73, 255, + 197, 197, 197, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 241, 241, 241, 255, 136, 137, 137, 255, 0, 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, 0, 0, 255, 135, 135, 135, 255, 240, 240, 240, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 229, 135, 135, 255, 221, 61, 61, 255, 223, 87, + 87, 255, 223, 83, 83, 255, 223, 79, 79, 255, 224, 90, 90, 255, 252, 243, 243, 255, 253, 246, 246, 255, 222, 69, 69, 255, 221, 62, 62, 255, 223, + 87, 87, 255, 223, 81, 81, 255, 223, 81, 81, 255, 224, 90, 90, 255, 220, 8, 8, 255, 228, 126, 126, 255, 255, 255, 255, 255, 246, 220, 220, 255, + 221, 52, 52, 255, 223, 87, 87, 255, 223, 81, 81, 255, 224, 89, 89, 255, 220, 41, 41, 255, 236, 172, 172, 255, 255, 255, 255, 255, 254, 253, 253, + 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 167, 167, 167, 255, 0, 0, 0, 255, 6, 10, 14, 255, 0, 0, 0, 255, 0, 0, + 0, 255, 202, 202, 202, 255, 215, 215, 215, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, + 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 52, 53, 55, 255, 252, 252, 252, 255, 172, 172, 172, 255, 0, 0, 0, 255, 22, 24, 25, 255, + 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 42, 44, 45, 255, 0, 0, 0, 255, 173, 173, 173, 255, 163, 163, 163, + 255, 0, 0, 0, 255, 0, 0, 0, 255, 230, 230, 231, 255, 224, 224, 224, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, + 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 154, 154, 155, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, 253, 255, 255, + 255, 255, 255, 208, 208, 208, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, + 0, 0, 0, 255, 189, 189, 189, 255, 255, 255, 255, 255, 243, 243, 244, 255, 82, 83, 84, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 77, 78, 79, 255, 244, 244, 244, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 229, 135, 135, 255, 221, 61, 61, 255, 223, 87, + 87, 255, 223, 83, 83, 255, 223, 79, 79, 255, 224, 88, 88, 255, 252, 245, 245, 255, 253, 246, 246, 255, 224, 95, 95, 255, 223, 82, 82, 255, 223, + 83, 83, 255, 223, 82, 82, 255, 223, 82, 82, 255, 223, 87, 87, 255, 222, 68, 68, 255, 229, 134, 134, 255, 255, 255, 255, 255, 246, 221, 221, 255, + 221, 50, 50, 255, 223, 87, 87, 255, 223, 81, 81, 255, 224, 89, 89, 255, 220, 41, 41, 255, 236, 172, 172, 255, 255, 255, 255, 255, 254, 253, 253, + 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 169, 169, 170, 255, 0, 0, 0, 255, 29, 31, 32, 255, 57, 58, 59, 255, 153, 154, + 154, 255, 221, 221, 221, 255, 92, 93, 94, 255, 0, 0, 0, 255, 0, 0, 0, 255, 131, 131, 131, 255, 210, 210, 210, 255, 191, 192, 192, 255, 71, + 72, 73, 255, 0, 0, 0, 255, 0, 0, 0, 255, 95, 96, 96, 255, 219, 219, 219, 255, 0, 0, 0, 255, 30, 32, 33, 255, 0, 0, 0, 255, + 158, 159, 159, 255, 213, 213, 213, 255, 179, 179, 180, 255, 35, 36, 38, 255, 25, 27, 29, 255, 0, 0, 0, 255, 172, 172, 173, 255, 166, 167, 167, + 255, 0, 0, 0, 255, 0, 0, 0, 255, 220, 220, 221, 255, 111, 111, 112, 255, 0, 0, 0, 255, 0, 0, 0, 255, 135, 135, 136, 255, 211, 211, + 212, 255, 180, 180, 180, 255, 11, 15, 18, 255, 39, 40, 41, 255, 0, 0, 0, 255, 214, 214, 214, 255, 255, 255, 255, 255, 255, 255, 255, 255, 248, + 248, 248, 255, 69, 70, 71, 255, 0, 0, 0, 255, 0, 0, 0, 255, 148, 148, 148, 255, 213, 213, 213, 255, 176, 176, 176, 255, 0, 0, 0, 255, + 0, 0, 0, 255, 0, 0, 0, 255, 238, 238, 239, 255, 175, 175, 175, 255, 0, 0, 0, 255, 17, 20, 22, 255, 85, 85, 86, 255, 200, 200, 200, + 255, 201, 201, 202, 255, 88, 89, 89, 255, 12, 15, 18, 255, 0, 0, 0, 255, 162, 162, 162, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 229, 135, 135, 255, 221, 61, 61, 255, 223, 87, + 87, 255, 223, 83, 83, 255, 223, 79, 79, 255, 224, 88, 88, 255, 252, 245, 245, 255, 253, 247, 247, 255, 224, 95, 95, 255, 222, 77, 77, 255, 223, + 84, 84, 255, 223, 82, 82, 255, 223, 82, 82, 255, 223, 87, 87, 255, 221, 61, 61, 255, 229, 136, 136, 255, 255, 255, 255, 255, 246, 221, 221, 255, + 221, 51, 51, 255, 223, 87, 87, 255, 223, 81, 81, 255, 224, 89, 89, 255, 220, 41, 41, 255, 236, 172, 172, 255, 255, 255, 255, 255, 254, 253, 253, + 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 169, 169, 169, 255, 0, 0, 0, 255, 0, 0, 0, 255, 196, 197, 197, 255, 255, 255, + 255, 255, 223, 223, 223, 255, 0, 0, 0, 255, 0, 0, 0, 255, 115, 116, 116, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 222, + 222, 222, 255, 0, 0, 0, 255, 0, 0, 0, 255, 105, 105, 106, 255, 172, 172, 173, 255, 0, 0, 0, 255, 0, 0, 0, 255, 165, 165, 165, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 200, 200, 200, 255, 0, 0, 0, 255, 0, 0, 0, 255, 172, 172, 173, 255, 166, 166, 167, + 255, 0, 0, 0, 255, 52, 53, 55, 255, 182, 182, 183, 255, 38, 40, 41, 255, 0, 0, 0, 255, 120, 120, 121, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 193, 194, 194, 255, 0, 0, 0, 255, 0, 0, 0, 255, 157, 157, 158, 255, 255, 255, 255, 255, 255, 255, 255, 255, 212, + 212, 212, 255, 0, 0, 0, 255, 0, 0, 0, 255, 136, 137, 137, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 204, 204, 204, 255, + 151, 152, 152, 255, 154, 154, 154, 255, 211, 212, 212, 255, 108, 109, 109, 255, 0, 0, 0, 255, 29, 31, 33, 255, 233, 233, 233, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 234, 234, 234, 255, 35, 37, 39, 255, 0, 0, 0, 255, 82, 83, 84, 255, 249, 249, 249, 255, 255, 255, 255, 255, 254, 254, + 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 229, 135, 135, 255, 221, 61, 61, 255, 223, 87, + 87, 255, 223, 83, 83, 255, 223, 79, 79, 255, 224, 88, 88, 255, 252, 244, 244, 255, 252, 245, 245, 255, 223, 72, 72, 255, 223, 84, 84, 255, 223, + 88, 88, 255, 223, 81, 81, 255, 223, 81, 81, 255, 224, 93, 93, 255, 221, 61, 61, 255, 227, 122, 122, 255, 255, 255, 255, 255, 246, 220, 220, 255, + 221, 51, 51, 255, 223, 87, 87, 255, 223, 81, 81, 255, 224, 89, 89, 255, 220, 41, 41, 255, 236, 172, 172, 255, 255, 255, 255, 255, 254, 253, 253, + 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 169, 169, 169, 255, 0, 0, 0, 255, 0, 0, 0, 255, 225, 225, 225, 255, 255, 255, + 255, 255, 200, 200, 201, 255, 0, 0, 0, 255, 0, 0, 0, 255, 184, 185, 185, 255, 255, 255, 255, 255, 249, 249, 249, 255, 252, 252, 252, 255, 254, + 254, 254, 255, 100, 101, 102, 255, 0, 0, 0, 255, 104, 104, 105, 255, 147, 148, 148, 255, 0, 0, 0, 255, 0, 0, 0, 255, 220, 221, 221, 255, + 255, 255, 255, 255, 249, 249, 249, 255, 255, 255, 255, 255, 244, 244, 244, 255, 62, 63, 64, 255, 0, 0, 0, 255, 173, 174, 174, 255, 166, 167, 167, + 255, 0, 0, 0, 255, 63, 64, 65, 255, 157, 158, 158, 255, 20, 22, 24, 255, 0, 0, 0, 255, 187, 187, 187, 255, 255, 255, 255, 255, 248, 248, + 248, 255, 255, 255, 255, 255, 240, 240, 240, 255, 33, 35, 37, 255, 0, 0, 0, 255, 133, 134, 134, 255, 255, 255, 255, 255, 255, 255, 255, 255, 196, + 196, 196, 255, 0, 0, 0, 255, 0, 0, 0, 255, 201, 201, 201, 255, 255, 255, 255, 255, 249, 249, 249, 255, 251, 251, 251, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 247, 247, 247, 255, 45, 46, 48, 255, 0, 0, 0, 255, 125, 125, 125, 255, 255, 255, 255, 255, 251, 251, 251, + 255, 250, 250, 250, 255, 255, 255, 255, 255, 127, 127, 128, 255, 0, 0, 0, 255, 46, 48, 49, 255, 238, 238, 238, 255, 255, 255, 255, 255, 254, 254, + 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 229, 135, 135, 255, 221, 61, 61, 255, 223, 87, + 87, 255, 223, 83, 83, 255, 222, 78, 78, 255, 224, 91, 91, 255, 253, 246, 246, 255, 255, 254, 254, 255, 232, 149, 149, 255, 220, 26, 26, 255, 222, + 71, 71, 255, 224, 91, 91, 255, 223, 89, 89, 255, 221, 61, 61, 255, 221, 42, 42, 255, 237, 180, 180, 255, 255, 255, 255, 255, 247, 224, 224, 255, + 221, 50, 50, 255, 223, 88, 88, 255, 223, 81, 81, 255, 224, 89, 89, 255, 220, 41, 41, 255, 236, 172, 172, 255, 255, 255, 255, 255, 254, 253, 253, + 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 169, 169, 169, 255, 0, 0, 0, 255, 0, 0, 0, 255, 222, 222, 222, 255, 255, 255, + 255, 255, 209, 209, 209, 255, 0, 0, 0, 255, 0, 0, 0, 255, 154, 154, 155, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 244, + 244, 244, 255, 57, 59, 60, 255, 0, 0, 0, 255, 105, 105, 106, 255, 160, 160, 161, 255, 0, 0, 0, 255, 0, 0, 0, 255, 198, 198, 198, 255, + 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 227, 227, 227, 255, 0, 0, 0, 255, 0, 0, 0, 255, 173, 173, 173, 255, 166, 167, 167, + 255, 0, 0, 0, 255, 60, 61, 62, 255, 167, 167, 168, 255, 26, 28, 30, 255, 0, 0, 0, 255, 158, 159, 159, 255, 255, 255, 255, 255, 254, 254, + 254, 255, 255, 255, 255, 255, 224, 224, 224, 255, 0, 0, 0, 255, 0, 0, 0, 255, 142, 142, 142, 255, 255, 255, 255, 255, 255, 255, 255, 255, 203, + 203, 203, 255, 0, 0, 0, 255, 0, 0, 0, 255, 176, 176, 176, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 241, 241, 241, 255, + 215, 215, 216, 255, 221, 221, 221, 255, 224, 225, 225, 255, 80, 81, 82, 255, 0, 0, 0, 255, 86, 87, 88, 255, 252, 252, 252, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 254, 254, 254, 255, 92, 93, 93, 255, 0, 0, 0, 255, 64, 65, 66, 255, 243, 243, 243, 255, 255, 255, 255, 255, 254, 254, + 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 229, 135, 135, 255, 221, 61, 61, 255, 223, 87, + 87, 255, 223, 82, 82, 255, 223, 85, 85, 255, 222, 70, 70, 255, 245, 215, 215, 255, 255, 255, 255, 255, 255, 255, 255, 255, 243, 208, 208, 255, 226, + 113, 113, 255, 220, 32, 32, 255, 221, 44, 44, 255, 230, 138, 138, 255, 247, 225, 225, 255, 255, 255, 255, 255, 255, 255, 255, 255, 238, 187, 187, 255, + 221, 52, 52, 255, 223, 88, 88, 255, 223, 81, 81, 255, 224, 89, 89, 255, 220, 41, 41, 255, 236, 172, 172, 255, 255, 255, 255, 255, 254, 253, 253, + 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 169, 169, 169, 255, 0, 0, 0, 255, 0, 0, 0, 255, 224, 224, 224, 255, 255, 255, + 255, 255, 235, 235, 235, 255, 0, 0, 0, 255, 24, 25, 27, 255, 0, 0, 0, 255, 196, 196, 196, 255, 249, 249, 249, 255, 241, 241, 242, 255, 146, + 146, 146, 255, 0, 0, 0, 255, 0, 0, 0, 255, 100, 101, 101, 255, 200, 200, 200, 255, 0, 0, 0, 255, 7, 11, 14, 255, 67, 68, 69, 255, + 220, 220, 221, 255, 250, 250, 250, 255, 233, 233, 233, 255, 114, 114, 115, 255, 0, 0, 0, 255, 0, 0, 0, 255, 172, 172, 172, 255, 166, 166, 166, + 255, 0, 0, 0, 255, 24, 26, 29, 255, 204, 204, 204, 255, 67, 67, 68, 255, 0, 0, 0, 255, 0, 0, 0, 255, 201, 202, 202, 255, 251, 251, + 251, 255, 234, 235, 235, 255, 110, 110, 111, 255, 0, 0, 0, 255, 0, 0, 0, 255, 196, 196, 196, 255, 248, 248, 248, 255, 229, 229, 229, 255, 239, + 239, 239, 255, 0, 0, 0, 255, 0, 0, 3, 255, 41, 43, 44, 255, 213, 213, 213, 255, 251, 251, 251, 255, 230, 231, 231, 255, 96, 97, 98, 255, + 0, 0, 0, 255, 0, 0, 0, 255, 214, 214, 214, 255, 144, 144, 144, 255, 0, 0, 0, 255, 0, 0, 0, 255, 160, 161, 161, 255, 245, 245, 246, + 255, 246, 246, 247, 255, 166, 166, 166, 255, 0, 0, 0, 255, 0, 0, 0, 255, 127, 127, 128, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 230, 136, 136, 255, 221, 60, 60, 255, 223, 87, + 87, 255, 223, 82, 82, 255, 223, 83, 83, 255, 223, 79, 79, 255, 222, 74, 74, 255, 236, 174, 174, 255, 252, 244, 244, 255, 255, 255, 255, 255, 254, + 251, 251, 255, 238, 186, 186, 255, 242, 201, 201, 255, 255, 255, 255, 255, 255, 255, 255, 255, 249, 232, 232, 255, 232, 150, 150, 255, 221, 62, 62, 255, + 223, 84, 84, 255, 223, 82, 82, 255, 223, 82, 82, 255, 223, 89, 89, 255, 220, 41, 41, 255, 236, 173, 173, 255, 255, 255, 255, 255, 254, 253, 253, + 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 171, 171, 171, 255, 0, 0, 0, 255, 0, 0, 0, 255, 226, 226, 226, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 155, 155, 155, 255, 0, 0, 0, 255, 46, 47, 48, 255, 0, 0, 0, 255, 77, 78, 79, 255, 54, 55, 56, 255, 0, + 0, 0, 255, 33, 34, 35, 255, 0, 0, 2, 255, 82, 83, 83, 255, 245, 245, 245, 255, 113, 113, 114, 255, 0, 0, 0, 255, 27, 29, 30, 255, + 0, 0, 0, 255, 85, 86, 87, 255, 23, 26, 28, 255, 0, 0, 0, 255, 53, 54, 55, 255, 0, 0, 0, 255, 174, 174, 174, 255, 168, 168, 169, + 255, 0, 0, 0, 255, 0, 0, 0, 255, 232, 232, 232, 255, 179, 179, 180, 255, 0, 0, 0, 255, 37, 38, 40, 255, 0, 0, 0, 255, 81, 81, + 82, 255, 29, 31, 33, 255, 0, 0, 0, 255, 0, 0, 0, 255, 92, 92, 93, 255, 232, 232, 232, 255, 86, 86, 87, 255, 0, 0, 0, 255, 209, + 209, 209, 255, 179, 179, 179, 255, 0, 0, 0, 255, 27, 29, 30, 255, 0, 0, 0, 255, 84, 85, 86, 255, 12, 16, 19, 255, 0, 0, 1, 255, + 0, 0, 0, 255, 127, 128, 128, 255, 255, 255, 255, 255, 217, 218, 218, 255, 0, 0, 0, 255, 11, 14, 16, 255, 0, 0, 0, 255, 62, 63, 64, + 255, 65, 66, 67, 255, 0, 0, 0, 255, 8, 12, 14, 255, 0, 0, 0, 255, 218, 218, 218, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 229, 132, 132, 255, 222, 69, 69, 255, 223, 86, + 86, 255, 223, 82, 82, 255, 223, 82, 82, 255, 223, 83, 83, 255, 223, 83, 83, 255, 220, 39, 39, 255, 224, 96, 96, 255, 240, 195, 195, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 246, 246, 255, 236, 175, 175, 255, 222, 71, 71, 255, 221, 52, 52, 255, 223, 86, 86, 255, + 223, 82, 82, 255, 223, 82, 82, 255, 223, 81, 81, 255, 224, 90, 90, 255, 221, 51, 51, 255, 235, 170, 170, 255, 255, 255, 255, 255, 254, 253, 253, + 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 160, 160, 161, 255, 0, 0, 0, 255, 0, 0, 0, 255, 223, 223, 223, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 249, 249, 249, 255, 127, 128, 128, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 19, + 22, 25, 255, 28, 31, 34, 255, 0, 0, 0, 255, 0, 0, 0, 255, 250, 250, 250, 255, 239, 239, 239, 255, 81, 82, 83, 255, 0, 0, 0, 255, + 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 93, 94, 94, 255, 0, 0, 0, 255, 0, 0, 0, 255, 165, 165, 165, 255, 157, 157, 158, + 255, 0, 0, 0, 255, 0, 0, 0, 255, 222, 222, 222, 255, 255, 255, 255, 255, 150, 151, 151, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, + 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 76, 77, 78, 255, 239, 239, 239, 255, 232, 232, 232, 255, 0, 0, 0, 255, 0, 0, 0, 255, 170, + 171, 171, 255, 255, 255, 255, 255, 150, 150, 151, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, + 124, 124, 125, 255, 246, 246, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255, 199, 200, 200, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 199, 199, 199, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 255, 255, 255, 255, 234, 162, 162, 255, 219, 0, 0, 255, 224, 93, + 93, 255, 223, 86, 86, 255, 223, 81, 81, 255, 223, 82, 82, 255, 223, 83, 83, 255, 224, 90, 90, 255, 222, 76, 76, 255, 220, 29, 29, 255, 228, + 125, 125, 255, 244, 213, 213, 255, 241, 200, 200, 255, 225, 98, 98, 255, 220, 35, 35, 255, 223, 83, 83, 255, 223, 89, 89, 255, 223, 82, 82, 255, + 223, 82, 82, 255, 223, 82, 82, 255, 223, 88, 88, 255, 223, 89, 89, 255, 218, 0, 0, 255, 241, 200, 200, 255, 255, 255, 255, 255, 254, 253, 253, + 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 223, 224, 224, 255, 194, 195, 195, 255, 197, 197, 198, 255, 243, 243, 243, 255, 255, 255, + 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 204, 204, 205, 255, 156, 156, 156, 255, 142, 143, 143, 255, 158, 158, 159, 255, 223, + 223, 223, 255, 219, 219, 219, 255, 193, 193, 193, 255, 204, 205, 205, 255, 250, 250, 250, 255, 255, 255, 255, 255, 248, 248, 248, 255, 191, 191, 191, 255, + 149, 149, 149, 255, 143, 143, 144, 255, 184, 184, 184, 255, 242, 242, 242, 255, 206, 206, 206, 255, 191, 191, 192, 255, 225, 225, 225, 255, 223, 223, 223, + 255, 194, 194, 194, 255, 197, 198, 198, 255, 241, 242, 242, 255, 255, 255, 255, 255, 255, 255, 255, 255, 218, 218, 219, 255, 166, 166, 167, 255, 143, 144, + 144, 255, 152, 152, 153, 255, 195, 195, 195, 255, 249, 249, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 199, 200, 200, 255, 168, 168, 168, 255, 245, + 245, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255, 217, 217, 218, 255, 164, 164, 164, 255, 142, 142, 143, 255, 157, 158, 158, 255, 206, 207, 207, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 235, 235, 235, 255, 179, 179, 180, 255, 146, 147, 147, + 255, 147, 147, 147, 255, 178, 178, 179, 255, 234, 235, 235, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 255, 255, 255, 255, 252, 245, 245, 255, 232, 152, 152, 255, 221, 44, + 44, 255, 222, 65, 65, 255, 224, 90, 90, 255, 223, 84, 84, 255, 223, 82, 82, 255, 223, 81, 81, 255, 223, 85, 85, 255, 224, 90, 90, 255, 222, + 64, 64, 255, 221, 47, 47, 255, 221, 45, 45, 255, 222, 73, 73, 255, 224, 90, 90, 255, 223, 83, 83, 255, 223, 81, 81, 255, 223, 82, 82, 255, + 223, 86, 86, 255, 223, 89, 89, 255, 221, 53, 53, 255, 222, 64, 64, 255, 237, 180, 180, 255, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, + 254, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 245, 216, + 216, 255, 228, 124, 124, 255, 220, 30, 30, 255, 222, 77, 77, 255, 224, 90, 90, 255, 223, 82, 82, 255, 223, 82, 82, 255, 223, 81, 81, 255, 223, + 86, 86, 255, 223, 88, 88, 255, 223, 88, 88, 255, 223, 85, 85, 255, 223, 82, 82, 255, 223, 81, 81, 255, 223, 84, 84, 255, 224, 90, 90, 255, + 222, 67, 67, 255, 221, 41, 41, 255, 231, 148, 148, 255, 249, 231, 231, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, 253, 255, 253, 253, 253, 255, 254, 254, 254, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 253, 253, 253, 255, 254, 254, 254, 255, 253, 253, 253, 255, 253, + 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, 253, 255, + 254, 254, 254, 255, 254, 254, 254, 255, 253, 253, 253, 255, 254, 254, 254, 255, 253, 253, 253, 255, 253, 253, 253, 255, 254, 254, 254, 255, 254, 254, 254, + 255, 253, 253, 253, 255, 253, 253, 253, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 253, 253, 253, 255, 254, 254, + 254, 255, 254, 254, 254, 255, 253, 253, 253, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 253, 253, 253, 255, 254, + 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 253, 253, 253, 255, 254, 254, 254, 255, 253, 253, 253, 255, 253, 253, 253, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 253, 253, 253, 255, 254, 254, 254, + 255, 254, 254, 254, 255, 253, 253, 253, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 255, 254, 254, 255, 255, 255, + 255, 255, 255, 253, 253, 255, 240, 196, 196, 255, 224, 95, 95, 255, 220, 38, 38, 255, 223, 85, 85, 255, 223, 88, 88, 255, 223, 82, 82, 255, 223, + 81, 81, 255, 223, 82, 82, 255, 223, 82, 82, 255, 223, 81, 81, 255, 223, 83, 83, 255, 224, 90, 90, 255, 222, 78, 78, 255, 220, 30, 30, 255, + 227, 120, 120, 255, 245, 214, 214, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, + 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 243, 243, 255, 235, 172, 172, 255, 222, 65, 65, 255, 221, 54, 54, 255, 223, 89, 89, 255, 223, + 86, 86, 255, 223, 81, 81, 255, 223, 81, 81, 255, 223, 88, 88, 255, 223, 85, 85, 255, 220, 38, 38, 255, 224, 91, 91, 255, 240, 193, 193, 255, + 254, 252, 252, 255, 255, 255, 255, 255, 255, 254, 254, 255, 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 254, 254, 255, 254, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 248, 230, 230, 255, 231, 145, 145, 255, 221, 41, 41, 255, 222, + 68, 68, 255, 224, 90, 90, 255, 223, 89, 89, 255, 221, 56, 56, 255, 222, 63, 63, 255, 235, 170, 170, 255, 252, 242, 242, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 254, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 255, 254, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 244, 212, 212, 255, 227, + 118, 118, 255, 220, 37, 37, 255, 221, 47, 47, 255, 230, 142, 142, 255, 248, 228, 228, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 255, + 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 255, 255, 254, 254, 255, 255, 255, 255, 255, 254, + 250, 250, 255, 244, 212, 212, 255, 246, 220, 220, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 255, 255, 254, 254, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 254, 253, 253, 255, 254, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 232, + 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 231, + 255, 255, 255, 255, 255, 255, 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 233, + 255, 255, 255, 223, 255, 255, 255, 255, 255, 255, 255, 249, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, 255, 252, 255, 255, 255, + 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, + 255, 253, 255, 255, 255, 252, 255, 255, 255, 252, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, + 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, 255, 253, + 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, + 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, + 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, + 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, + 255, 255, 255, 252, 255, 255, 255, 252, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, 255, + 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, + 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, + 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, 255, 252, 255, 255, 255, 253, + 255, 255, 255, 252, 255, 255, 255, 252, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, 255, + 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, + 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, 255, 252, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 253, 255, + 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 255, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 248, 255, 255, 255, 255, 255, 255, 255, 194, + 255, 255, 255, 62, 255, 255, 255, 242, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 230, 255, 255, 255, 45, + 0, 0, 0, 0, 255, 255, 255, 20, 255, 255, 255, 68, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, + 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, + 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, + 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, + 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, + 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, + 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, + 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, + 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, + 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, + 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, + 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, + 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, + 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, + 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, + 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 66, 255, 255, 255, 13, 0, 0, 0, 0}; + +static const unsigned char live365_logo[] = { + 218, 240, 246, 255, 221, 241, 247, 255, 225, 243, 248, 255, 228, 245, 249, 255, 231, 246, 250, 255, 234, 247, 251, 255, 236, 248, 251, 255, 239, 249, 252, + 255, 241, 250, 252, 255, 243, 251, 252, 255, 245, 251, 253, 255, 246, 252, 254, 255, 247, 252, 253, 255, 248, 253, 254, 255, 249, 253, 254, 255, 250, 253, + 254, 255, 251, 254, 254, 255, 251, 253, 254, 255, 251, 253, 254, 255, 252, 254, 254, 255, 252, 254, 254, 255, 253, 254, 255, 255, 253, 254, 255, 255, 252, + 254, 254, 255, 253, 254, 254, 255, 253, 255, 255, 255, 253, 254, 254, 255, 253, 254, 255, 255, 253, 254, 255, 255, 252, 253, 254, 255, 252, 253, 253, 255, + 252, 253, 253, 255, 252, 254, 254, 255, 252, 253, 254, 255, 251, 254, 255, 255, 251, 254, 254, 255, 250, 253, 254, 255, 250, 254, 255, 255, 249, 253, 254, + 255, 247, 253, 254, 255, 247, 253, 254, 255, 245, 252, 254, 255, 243, 252, 254, 255, 241, 251, 254, 255, 239, 250, 253, 255, 236, 250, 253, 255, 233, 249, + 253, 255, 230, 248, 252, 255, 226, 247, 252, 255, 221, 241, 247, 255, 218, 230, 239, 255, 214, 236, 244, 255, 209, 241, 249, 255, 205, 241, 249, 255, 201, + 239, 248, 255, 197, 238, 247, 255, 193, 236, 246, 255, 189, 235, 245, 255, 185, 233, 245, 255, 183, 230, 242, 255, 182, 230, 243, 255, 180, 229, 243, 255, + 179, 227, 241, 255, 191, 198, 216, 255, 183, 220, 238, 255, 176, 225, 241, 255, 175, 224, 241, 255, 174, 223, 241, 255, 172, 222, 240, 255, 170, 221, 239, + 255, 171, 221, 239, 255, 171, 220, 239, 255, 172, 220, 239, 255, 172, 220, 239, 255, 172, 220, 239, 255, 173, 219, 239, 255, 173, 219, 239, 255, 173, 218, + 239, 255, 218, 222, 231, 255, 234, 222, 224, 255, 231, 218, 221, 255, 224, 210, 217, 255, 212, 198, 211, 255, 198, 184, 206, 255, 185, 179, 206, 255, 180, + 180, 207, 255, 181, 180, 207, 255, 181, 181, 208, 255, 191, 188, 211, 255, 186, 185, 212, 255, 184, 189, 217, 255, 185, 186, 214, 255, 186, 201, 228, 255, + 187, 194, 220, 255, 187, 202, 227, 255, 187, 216, 240, 255, 187, 211, 236, 255, 188, 207, 233, 255, 188, 203, 228, 255, 189, 192, 219, 255, 195, 182, 213, + 255, 202, 179, 211, 255, 195, 186, 215, 255, 192, 193, 220, 255, 190, 213, 236, 255, 192, 190, 218, 255, 208, 201, 227, 255, 197, 204, 229, 255, 190, 202, + 226, 255, 191, 202, 226, 255, 190, 201, 226, 255, 190, 201, 225, 255, 191, 201, 225, 255, 191, 202, 225, 255, 192, 202, 225, 255, 192, 202, 225, 255, 191, + 202, 225, 255, 191, 202, 225, 255, 190, 201, 224, 255, 190, 200, 223, 255, 189, 198, 220, 255, 188, 197, 219, 255, 187, 200, 223, 255, 186, 201, 224, 255, + 219, 240, 245, 255, 223, 242, 247, 255, 226, 244, 248, 255, 230, 245, 249, 255, 233, 247, 251, 255, 236, 249, 252, 255, 238, 249, 252, 255, 240, 250, 253, + 255, 242, 251, 253, 255, 244, 252, 253, 255, 246, 252, 253, 255, 247, 253, 254, 255, 248, 253, 254, 255, 249, 254, 254, 255, 250, 253, 254, 255, 251, 254, + 255, 255, 252, 254, 254, 255, 252, 254, 254, 255, 252, 254, 254, 255, 253, 254, 255, 255, 253, 254, 254, 255, 253, 254, 254, 255, 253, 254, 254, 255, 253, + 254, 254, 255, 254, 255, 255, 255, 254, 255, 255, 255, 253, 254, 254, 255, 253, 254, 254, 255, 253, 254, 254, 255, 253, 254, 254, 255, 252, 253, 253, 255, + 252, 253, 253, 255, 252, 254, 255, 255, 252, 254, 255, 255, 251, 254, 254, 255, 251, 254, 255, 255, 250, 253, 254, 255, 249, 253, 254, 255, 248, 253, 254, + 255, 247, 253, 254, 255, 246, 252, 254, 255, 244, 252, 254, 255, 243, 252, 254, 255, 241, 251, 253, 255, 238, 250, 253, 255, 236, 250, 253, 255, 233, 249, + 253, 255, 231, 249, 252, 255, 228, 242, 248, 255, 222, 233, 241, 255, 221, 244, 250, 255, 218, 245, 251, 255, 215, 244, 251, 255, 210, 244, 251, 255, 206, + 242, 250, 255, 202, 242, 250, 255, 197, 241, 250, 255, 192, 239, 249, 255, 187, 238, 249, 255, 184, 236, 247, 255, 182, 236, 248, 255, 180, 235, 248, 255, + 178, 233, 247, 255, 202, 205, 218, 255, 193, 208, 226, 255, 175, 230, 245, 255, 174, 228, 244, 255, 174, 227, 244, 255, 171, 225, 242, 255, 169, 223, 241, + 255, 169, 221, 240, 255, 170, 220, 239, 255, 170, 219, 238, 255, 170, 218, 238, 255, 170, 218, 237, 255, 170, 217, 237, 255, 170, 216, 236, 255, 185, 217, + 234, 255, 236, 226, 227, 255, 234, 225, 226, 255, 230, 219, 223, 255, 219, 205, 215, 255, 205, 192, 209, 255, 193, 182, 205, 255, 184, 178, 204, 255, 181, + 175, 204, 255, 178, 174, 204, 255, 178, 174, 205, 255, 186, 182, 207, 255, 191, 177, 205, 255, 187, 173, 204, 255, 184, 176, 207, 255, 182, 195, 221, 255, + 183, 192, 218, 255, 184, 200, 226, 255, 184, 204, 230, 255, 184, 214, 238, 255, 184, 215, 239, 255, 184, 206, 231, 255, 185, 194, 220, 255, 190, 176, 208, + 255, 196, 175, 208, 255, 190, 185, 214, 255, 187, 200, 224, 255, 188, 217, 238, 255, 187, 191, 218, 255, 194, 194, 220, 255, 206, 206, 231, 255, 188, 203, + 227, 255, 187, 203, 227, 255, 187, 203, 226, 255, 187, 203, 227, 255, 188, 203, 226, 255, 188, 203, 226, 255, 189, 203, 226, 255, 189, 203, 226, 255, 189, + 203, 226, 255, 189, 203, 226, 255, 189, 203, 225, 255, 188, 202, 224, 255, 187, 199, 221, 255, 187, 197, 219, 255, 186, 201, 224, 255, 185, 204, 226, 255, + 220, 242, 247, 255, 224, 244, 248, 255, 228, 245, 249, 255, 231, 246, 250, 255, 234, 248, 251, 255, 237, 249, 252, 255, 239, 250, 252, 255, 242, 251, 253, + 255, 244, 251, 253, 255, 245, 251, 253, 255, 247, 252, 253, 255, 248, 253, 254, 255, 249, 253, 254, 255, 250, 253, 254, 255, 251, 254, 254, 255, 251, 254, + 254, 255, 252, 254, 255, 255, 252, 254, 255, 255, 253, 254, 255, 255, 253, 254, 255, 255, 253, 254, 254, 255, 253, 254, 255, 255, 253, 254, 254, 255, 254, + 255, 255, 255, 254, 254, 255, 255, 253, 254, 254, 255, 254, 255, 255, 255, 253, 254, 254, 255, 253, 254, 254, 255, 253, 253, 254, 255, 253, 254, 254, 255, + 253, 254, 254, 255, 253, 254, 254, 255, 253, 254, 255, 255, 252, 254, 255, 255, 252, 254, 254, 255, 251, 254, 255, 255, 251, 254, 254, 255, 250, 254, 255, + 255, 250, 253, 254, 255, 249, 253, 255, 255, 247, 253, 254, 255, 246, 253, 255, 255, 245, 252, 254, 255, 243, 252, 254, 255, 240, 251, 254, 255, 238, 251, + 254, 255, 233, 244, 249, 255, 230, 239, 245, 255, 230, 248, 252, 255, 226, 248, 253, 255, 223, 247, 252, 255, 219, 246, 252, 255, 215, 244, 252, 255, 210, + 243, 251, 255, 205, 242, 250, 255, 200, 240, 249, 255, 195, 238, 248, 255, 190, 236, 247, 255, 184, 233, 245, 255, 182, 233, 245, 255, 180, 231, 244, 255, + 181, 230, 243, 255, 216, 214, 225, 255, 195, 204, 224, 255, 174, 225, 241, 255, 173, 224, 239, 255, 172, 222, 239, 255, 169, 220, 238, 255, 167, 218, 237, + 255, 168, 217, 236, 255, 168, 216, 236, 255, 168, 216, 235, 255, 168, 215, 235, 255, 168, 215, 235, 255, 168, 215, 235, 255, 168, 214, 235, 255, 209, 223, + 232, 255, 236, 227, 228, 255, 234, 226, 227, 255, 228, 217, 223, 255, 213, 200, 212, 255, 199, 187, 206, 255, 188, 178, 203, 255, 181, 171, 202, 255, 177, + 168, 201, 255, 175, 169, 201, 255, 175, 171, 203, 255, 181, 175, 204, 255, 200, 191, 210, 255, 184, 173, 204, 255, 179, 184, 212, 255, 179, 196, 222, 255, + 179, 182, 209, 255, 180, 185, 212, 255, 180, 194, 219, 255, 180, 207, 232, 255, 180, 215, 239, 255, 181, 209, 234, 255, 182, 195, 222, 255, 185, 175, 207, + 255, 189, 173, 206, 255, 185, 185, 213, 255, 184, 207, 230, 255, 184, 215, 236, 255, 184, 190, 216, 255, 185, 193, 217, 255, 204, 203, 228, 255, 191, 203, + 227, 255, 186, 201, 225, 255, 185, 201, 224, 255, 184, 201, 224, 255, 185, 201, 224, 255, 186, 200, 223, 255, 186, 201, 223, 255, 187, 201, 223, 255, 187, + 201, 223, 255, 187, 201, 223, 255, 187, 200, 222, 255, 187, 199, 221, 255, 186, 197, 218, 255, 185, 195, 217, 255, 185, 199, 222, 255, 184, 202, 224, 255, + 222, 240, 245, 255, 226, 242, 247, 255, 229, 244, 248, 255, 230, 244, 247, 255, 215, 226, 229, 255, 214, 223, 226, 255, 216, 224, 227, 255, 218, 225, 227, + 255, 219, 226, 228, 255, 221, 226, 228, 255, 223, 227, 228, 255, 223, 227, 228, 255, 224, 228, 228, 255, 225, 228, 228, 255, 226, 228, 228, 255, 226, 228, + 229, 255, 227, 228, 229, 255, 227, 229, 229, 255, 228, 229, 229, 255, 228, 229, 229, 255, 228, 229, 229, 255, 228, 228, 229, 255, 228, 229, 229, 255, 228, + 229, 229, 255, 228, 228, 228, 255, 228, 228, 228, 255, 228, 228, 229, 255, 228, 228, 228, 255, 228, 228, 228, 255, 227, 228, 228, 255, 227, 228, 228, 255, + 227, 228, 228, 255, 227, 229, 229, 255, 227, 228, 228, 255, 227, 228, 229, 255, 227, 228, 229, 255, 226, 228, 229, 255, 226, 228, 228, 255, 225, 227, 228, + 255, 224, 227, 228, 255, 223, 227, 228, 255, 222, 227, 228, 255, 220, 227, 228, 255, 219, 227, 228, 255, 217, 226, 227, 255, 214, 225, 227, 255, 211, 221, + 225, 255, 208, 216, 220, 255, 206, 222, 226, 255, 203, 222, 226, 255, 200, 221, 226, 255, 196, 220, 226, 255, 193, 219, 225, 255, 190, 219, 225, 255, 198, + 231, 238, 255, 203, 240, 249, 255, 200, 240, 249, 255, 195, 238, 248, 255, 190, 237, 247, 255, 185, 234, 246, 255, 182, 234, 246, 255, 180, 233, 246, 255, + 185, 234, 245, 255, 219, 217, 228, 255, 194, 199, 218, 255, 173, 230, 245, 255, 172, 229, 244, 255, 171, 228, 244, 255, 168, 226, 243, 255, 166, 225, 242, + 255, 166, 224, 242, 255, 166, 223, 241, 255, 166, 222, 241, 255, 166, 222, 241, 255, 166, 221, 240, 255, 165, 221, 240, 255, 166, 220, 239, 255, 228, 227, + 229, 255, 235, 226, 227, 255, 232, 224, 226, 255, 223, 212, 219, 255, 211, 198, 210, 255, 198, 185, 205, 255, 189, 179, 203, 255, 184, 174, 202, 255, 179, + 168, 200, 255, 180, 170, 201, 255, 181, 172, 201, 255, 181, 167, 200, 255, 182, 170, 202, 255, 178, 171, 204, 255, 175, 185, 213, 255, 176, 194, 220, 255, + 177, 186, 214, 255, 176, 181, 209, 255, 177, 187, 213, 255, 177, 201, 226, 255, 177, 209, 233, 255, 178, 210, 235, 255, 179, 200, 225, 255, 180, 176, 207, + 255, 185, 171, 204, 255, 181, 186, 212, 255, 181, 216, 237, 255, 182, 215, 236, 255, 182, 193, 217, 255, 182, 197, 220, 255, 197, 209, 232, 255, 191, 201, + 225, 255, 188, 200, 223, 255, 182, 199, 222, 255, 182, 199, 222, 255, 182, 199, 222, 255, 183, 199, 222, 255, 183, 199, 222, 255, 184, 200, 222, 255, 185, + 200, 222, 255, 185, 200, 222, 255, 185, 200, 222, 255, 185, 199, 221, 255, 185, 197, 219, 255, 184, 196, 217, 255, 184, 200, 222, 255, 183, 203, 225, 255, + 223, 244, 249, 255, 227, 246, 250, 255, 230, 247, 251, 255, 140, 149, 151, 255, 14, 15, 15, 255, 7, 7, 7, 255, 7, 7, 7, 255, 7, 7, 7, + 255, 7, 7, 7, 255, 7, 7, 7, 255, 7, 7, 7, 255, 7, 7, 7, 255, 7, 7, 7, 255, 7, 7, 7, 255, 7, 7, 7, 255, 7, 7, + 7, 255, 7, 7, 7, 255, 7, 7, 7, 255, 7, 7, 7, 255, 7, 7, 7, 255, 7, 7, 7, 255, 7, 7, 7, 255, 7, 7, 7, 255, 7, + 7, 7, 255, 7, 7, 7, 255, 7, 7, 7, 255, 7, 7, 7, 255, 6, 6, 6, 255, 6, 6, 6, 255, 6, 6, 6, 255, 6, 6, 6, 255, + 6, 6, 6, 255, 6, 6, 6, 255, 6, 6, 6, 255, 6, 6, 6, 255, 6, 6, 6, 255, 6, 6, 6, 255, 6, 6, 6, 255, 6, 6, 6, + 255, 6, 6, 6, 255, 6, 6, 6, 255, 6, 6, 6, 255, 6, 6, 6, 255, 6, 6, 6, 255, 6, 6, 6, 255, 6, 6, 6, 255, 6, 6, + 6, 255, 6, 6, 6, 255, 6, 6, 6, 255, 5, 6, 6, 255, 5, 6, 6, 255, 5, 6, 6, 255, 5, 6, 6, 255, 6, 6, 7, 255, 41, + 46, 48, 255, 200, 232, 239, 255, 206, 243, 252, 255, 202, 242, 251, 255, 196, 240, 250, 255, 187, 238, 249, 255, 187, 238, 249, 255, 182, 236, 248, 255, + 181, 233, 245, 255, 218, 218, 228, 255, 195, 197, 215, 255, 172, 230, 245, 255, 172, 229, 244, 255, 170, 227, 243, 255, 166, 224, 241, 255, 164, 222, 240, + 255, 164, 221, 239, 255, 164, 219, 238, 255, 164, 219, 237, 255, 163, 217, 237, 255, 163, 217, 236, 255, 163, 215, 235, 255, 174, 217, 235, 255, 234, 227, + 227, 255, 224, 215, 220, 255, 217, 207, 216, 255, 209, 198, 210, 255, 203, 191, 207, 255, 194, 183, 203, 255, 190, 177, 201, 255, 193, 180, 201, 255, 188, + 178, 201, 255, 185, 177, 202, 255, 178, 163, 198, 255, 176, 164, 199, 255, 174, 173, 203, 255, 171, 173, 204, 255, 172, 177, 206, 255, 173, 185, 213, 255, + 174, 189, 216, 255, 175, 187, 215, 255, 174, 183, 210, 255, 174, 190, 215, 255, 174, 203, 228, 255, 175, 206, 230, 255, 176, 192, 218, 255, 178, 174, 204, + 255, 182, 168, 203, 255, 179, 187, 212, 255, 178, 217, 238, 255, 179, 214, 235, 255, 179, 193, 217, 255, 179, 201, 223, 255, 193, 217, 238, 255, 189, 204, + 227, 255, 182, 203, 225, 255, 180, 202, 224, 255, 180, 201, 224, 255, 180, 201, 223, 255, 180, 201, 223, 255, 181, 201, 223, 255, 182, 202, 223, 255, 182, + 202, 223, 255, 183, 201, 223, 255, 183, 201, 223, 255, 183, 200, 221, 255, 183, 198, 219, 255, 183, 196, 217, 255, 183, 200, 222, 255, 182, 204, 227, 255, + 224, 242, 247, 255, 228, 244, 248, 255, 231, 245, 249, 255, 143, 151, 152, 255, 81, 85, 86, 255, 84, 87, 88, 255, 86, 89, 89, 255, 86, 89, 89, + 255, 87, 89, 89, 255, 87, 89, 89, 255, 88, 89, 89, 255, 88, 89, 90, 255, 89, 89, 90, 255, 89, 89, 90, 255, 89, 90, 90, 255, 89, 90, + 90, 255, 89, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 90, + 90, 90, 255, 90, 90, 90, 255, 90, 90, 90, 255, 82, 82, 82, 255, 14, 14, 14, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, + 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 1, 1, 1, 255, 1, 1, 1, 255, 9, 9, 9, 255, 8, 8, 8, 255, 1, 1, 1, 255, 0, 0, 0, 255, 0, 0, + 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 4, + 4, 4, 255, 184, 216, 222, 255, 203, 241, 249, 255, 198, 240, 249, 255, 193, 238, 248, 255, 187, 235, 245, 255, 184, 235, 246, 255, 180, 233, 246, 255, + 179, 230, 242, 255, 207, 208, 223, 255, 197, 192, 211, 255, 173, 225, 241, 255, 170, 227, 242, 255, 169, 225, 241, 255, 165, 223, 240, 255, 162, 221, 239, + 255, 162, 221, 239, 255, 162, 220, 239, 255, 162, 220, 239, 255, 161, 220, 238, 255, 161, 219, 238, 255, 160, 219, 238, 255, 185, 221, 235, 255, 212, 200, + 210, 255, 223, 213, 218, 255, 223, 213, 219, 255, 202, 191, 206, 255, 193, 181, 201, 255, 189, 177, 199, 255, 191, 178, 200, 255, 193, 180, 200, 255, 192, + 188, 205, 255, 179, 167, 198, 255, 177, 166, 198, 255, 174, 168, 199, 255, 169, 165, 199, 255, 170, 164, 199, 255, 172, 164, 199, 255, 172, 166, 201, 255, + 171, 177, 207, 255, 172, 193, 220, 255, 176, 193, 220, 255, 171, 188, 214, 255, 172, 197, 221, 255, 173, 199, 223, 255, 173, 183, 210, 255, 176, 169, 202, + 255, 179, 166, 201, 255, 176, 187, 213, 255, 176, 218, 239, 255, 177, 208, 230, 255, 177, 193, 216, 255, 177, 201, 224, 255, 187, 219, 239, 255, 199, 204, + 227, 255, 183, 200, 223, 255, 181, 199, 221, 255, 178, 199, 221, 255, 178, 198, 220, 255, 178, 198, 220, 255, 179, 198, 221, 255, 179, 198, 220, 255, 180, + 198, 220, 255, 181, 199, 220, 255, 181, 198, 220, 255, 182, 198, 219, 255, 182, 196, 217, 255, 182, 194, 215, 255, 181, 198, 219, 255, 181, 202, 224, 255, + 225, 243, 248, 255, 229, 245, 249, 255, 232, 247, 250, 255, 204, 215, 218, 255, 184, 193, 195, 255, 232, 241, 244, 255, 242, 250, 252, 255, 244, 251, 252, + 255, 245, 251, 252, 255, 246, 251, 252, 255, 248, 252, 253, 255, 250, 253, 253, 255, 250, 252, 253, 255, 250, 252, 252, 255, 251, 253, 253, 255, 251, 252, + 252, 255, 252, 253, 253, 255, 253, 254, 254, 255, 252, 253, 253, 255, 252, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 252, + 252, 252, 255, 253, 253, 253, 255, 254, 254, 254, 255, 252, 252, 252, 255, 82, 82, 82, 255, 1, 1, 1, 255, 0, 0, 0, 255, 1, 1, 1, 255, + 1, 1, 1, 255, 15, 15, 15, 255, 21, 21, 21, 255, 5, 5, 5, 255, 1, 1, 1, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, + 255, 1, 1, 1, 255, 19, 20, 20, 255, 111, 113, 114, 255, 192, 196, 198, 255, 117, 120, 121, 255, 1, 1, 1, 255, 0, 0, 0, 255, 1, 1, + 1, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 0, 1, 1, 255, 0, 0, 0, 255, 0, 0, 0, 255, 4, + 4, 4, 255, 189, 217, 223, 255, 209, 243, 251, 255, 205, 242, 251, 255, 200, 241, 250, 255, 190, 238, 249, 255, 192, 239, 250, 255, 187, 236, 248, 255, + 181, 202, 222, 255, 184, 181, 209, 255, 180, 173, 204, 255, 190, 189, 215, 255, 185, 232, 246, 255, 168, 231, 246, 255, 163, 229, 245, 255, 160, 227, 244, + 255, 160, 226, 243, 255, 160, 225, 243, 255, 159, 224, 241, 255, 159, 223, 241, 255, 158, 222, 241, 255, 158, 221, 240, 255, 174, 222, 237, 255, 222, 210, + 214, 255, 202, 190, 204, 255, 199, 189, 205, 255, 202, 189, 203, 255, 206, 193, 205, 255, 198, 185, 201, 255, 195, 183, 201, 255, 193, 182, 201, 255, 190, + 185, 204, 255, 176, 166, 197, 255, 183, 179, 201, 255, 165, 163, 199, 255, 165, 166, 200, 255, 167, 165, 200, 255, 169, 163, 199, 255, 173, 160, 197, 255, + 171, 165, 200, 255, 170, 184, 213, 255, 173, 199, 224, 255, 170, 189, 215, 255, 169, 191, 215, 255, 170, 192, 217, 255, 171, 176, 205, 255, 175, 162, 199, + 255, 176, 168, 202, 255, 174, 195, 218, 255, 174, 216, 237, 255, 175, 196, 219, 255, 175, 199, 221, 255, 175, 202, 224, 255, 181, 220, 239, 255, 208, 206, + 230, 255, 183, 200, 222, 255, 176, 199, 220, 255, 176, 198, 220, 255, 176, 198, 220, 255, 176, 198, 220, 255, 176, 198, 220, 255, 177, 199, 220, 255, 178, + 199, 220, 255, 179, 200, 221, 255, 179, 200, 220, 255, 180, 199, 219, 255, 180, 197, 218, 255, 180, 194, 215, 255, 180, 199, 220, 255, 180, 204, 225, 255, + 226, 244, 249, 255, 230, 246, 250, 255, 233, 247, 250, 255, 99, 104, 105, 255, 7, 7, 7, 255, 206, 214, 216, 255, 242, 250, 252, 255, 245, 251, 253, + 255, 180, 183, 184, 255, 172, 175, 176, 255, 249, 252, 253, 255, 251, 253, 254, 255, 239, 241, 241, 255, 140, 141, 141, 255, 218, 219, 220, 255, 146, 147, + 147, 255, 230, 231, 231, 255, 248, 249, 249, 255, 154, 154, 154, 255, 204, 204, 204, 255, 163, 163, 163, 255, 145, 145, 145, 255, 145, 145, 145, 255, 167, + 167, 167, 255, 250, 250, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 86, 86, 86, 255, 1, 1, 1, 255, 2, 2, 2, 255, 70, 70, 70, 255, + 181, 181, 181, 255, 227, 227, 227, 255, 231, 231, 231, 255, 206, 207, 207, 255, 94, 95, 95, 255, 3, 3, 3, 255, 0, 0, 0, 255, 1, 1, 1, + 255, 65, 66, 66, 255, 213, 215, 216, 255, 248, 251, 252, 255, 244, 248, 248, 255, 143, 145, 146, 255, 4, 4, 4, 255, 8, 8, 8, 255, 141, 142, + 145, 255, 163, 166, 169, 255, 163, 167, 171, 255, 164, 172, 175, 255, 163, 173, 176, 255, 47, 50, 51, 255, 0, 0, 0, 255, 0, 0, 0, 255, 4, + 4, 4, 255, 192, 218, 224, 255, 211, 243, 251, 255, 206, 242, 251, 255, 201, 240, 250, 255, 192, 237, 248, 255, 191, 237, 248, 255, 184, 220, 233, 255, + 195, 197, 213, 255, 179, 175, 204, 255, 176, 172, 202, 255, 184, 171, 203, 255, 180, 184, 212, 255, 175, 204, 225, 255, 162, 224, 241, 255, 158, 221, 239, + 255, 158, 220, 239, 255, 158, 219, 238, 255, 158, 218, 237, 255, 158, 217, 237, 255, 158, 217, 236, 255, 158, 216, 236, 255, 160, 216, 236, 255, 221, 216, + 220, 255, 209, 198, 208, 255, 203, 197, 210, 255, 205, 192, 204, 255, 221, 209, 214, 255, 206, 194, 205, 255, 192, 180, 199, 255, 192, 185, 202, 255, 188, + 181, 203, 255, 181, 173, 199, 255, 180, 179, 204, 255, 161, 166, 201, 255, 162, 166, 201, 255, 162, 166, 201, 255, 164, 166, 201, 255, 166, 164, 199, 255, + 171, 158, 195, 255, 168, 168, 201, 255, 168, 193, 220, 255, 168, 188, 215, 255, 167, 189, 214, 255, 168, 188, 213, 255, 171, 165, 200, 255, 174, 159, 198, + 255, 173, 170, 202, 255, 171, 197, 219, 255, 172, 209, 231, 255, 173, 189, 213, 255, 173, 205, 226, 255, 173, 203, 224, 255, 174, 217, 236, 255, 198, 205, + 227, 255, 180, 201, 223, 255, 174, 200, 221, 255, 174, 200, 221, 255, 174, 200, 221, 255, 174, 200, 221, 255, 175, 199, 221, 255, 175, 199, 221, 255, 176, + 200, 221, 255, 177, 200, 221, 255, 177, 200, 221, 255, 178, 199, 219, 255, 179, 197, 217, 255, 179, 194, 215, 255, 179, 198, 219, 255, 179, 204, 225, 255, + 227, 243, 247, 255, 230, 245, 249, 255, 233, 246, 250, 255, 96, 101, 102, 255, 1, 1, 1, 255, 206, 213, 215, 255, 243, 250, 252, 255, 245, 250, 251, + 255, 104, 106, 107, 255, 84, 86, 86, 255, 249, 252, 252, 255, 250, 253, 253, 255, 222, 224, 225, 255, 9, 9, 9, 255, 189, 190, 190, 255, 38, 38, + 38, 255, 170, 171, 171, 255, 236, 237, 237, 255, 22, 22, 22, 255, 184, 184, 184, 255, 50, 50, 50, 255, 44, 44, 44, 255, 77, 77, 77, 255, 114, + 114, 114, 255, 246, 246, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255, 85, 85, 85, 255, 1, 1, 1, 255, 4, 4, 4, 255, 153, 153, 153, 255, + 251, 251, 251, 255, 236, 237, 237, 255, 241, 242, 242, 255, 252, 253, 253, 255, 246, 247, 247, 255, 63, 64, 64, 255, 2, 2, 2, 255, 64, 65, 65, + 255, 234, 236, 236, 255, 248, 250, 252, 255, 184, 186, 187, 255, 49, 49, 50, 255, 1, 1, 1, 255, 0, 0, 0, 255, 12, 12, 12, 255, 209, 210, + 214, 255, 233, 234, 239, 255, 231, 231, 238, 255, 228, 229, 237, 255, 212, 217, 223, 255, 39, 40, 42, 255, 1, 1, 1, 255, 0, 0, 0, 255, 4, + 4, 4, 255, 185, 209, 217, 255, 205, 241, 249, 255, 201, 238, 247, 255, 197, 237, 247, 255, 191, 234, 245, 255, 190, 225, 237, 255, 190, 202, 218, 255, + 203, 203, 217, 255, 181, 177, 205, 255, 179, 175, 203, 255, 182, 173, 203, 255, 177, 177, 207, 255, 169, 210, 230, 255, 165, 214, 233, 255, 160, 225, 242, + 255, 160, 226, 243, 255, 161, 225, 242, 255, 161, 225, 242, 255, 161, 225, 241, 255, 161, 224, 241, 255, 161, 224, 242, 255, 165, 224, 241, 255, 220, 213, + 218, 255, 222, 210, 215, 255, 226, 214, 218, 255, 230, 220, 221, 255, 223, 211, 215, 255, 203, 190, 204, 255, 188, 175, 198, 255, 192, 186, 205, 255, 194, + 192, 208, 255, 190, 186, 205, 255, 179, 178, 205, 255, 166, 175, 206, 255, 166, 171, 204, 255, 166, 171, 204, 255, 167, 171, 204, 255, 168, 171, 204, 255, + 174, 165, 199, 255, 171, 168, 201, 255, 169, 189, 216, 255, 169, 192, 218, 255, 169, 188, 212, 255, 171, 183, 210, 255, 175, 166, 201, 255, 177, 163, 199, + 255, 176, 175, 205, 255, 174, 202, 223, 255, 175, 199, 223, 255, 175, 190, 214, 255, 175, 207, 228, 255, 175, 212, 232, 255, 175, 214, 232, 255, 185, 203, + 224, 255, 183, 202, 222, 255, 179, 200, 221, 255, 175, 199, 220, 255, 174, 198, 219, 255, 175, 198, 219, 255, 175, 198, 219, 255, 175, 199, 219, 255, 176, + 198, 219, 255, 176, 198, 218, 255, 177, 199, 218, 255, 178, 197, 218, 255, 178, 196, 216, 255, 178, 193, 213, 255, 179, 197, 217, 255, 178, 203, 223, 255, + 227, 246, 251, 255, 231, 248, 251, 255, 234, 248, 251, 255, 96, 101, 103, 255, 1, 1, 1, 255, 207, 214, 216, 255, 243, 251, 252, 255, 245, 251, 253, + 255, 105, 107, 107, 255, 82, 83, 84, 255, 249, 252, 252, 255, 251, 253, 254, 255, 223, 225, 225, 255, 9, 9, 9, 255, 207, 207, 208, 255, 76, 76, + 76, 255, 130, 130, 130, 255, 211, 212, 212, 255, 23, 23, 23, 255, 218, 218, 218, 255, 51, 51, 51, 255, 143, 143, 143, 255, 254, 254, 254, 255, 254, + 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 85, 85, 85, 255, 1, 1, 1, 255, 1, 1, 1, 255, 30, 30, 30, 255, + 110, 110, 110, 255, 40, 40, 40, 255, 73, 73, 73, 255, 254, 254, 254, 255, 253, 253, 253, 255, 122, 122, 122, 255, 14, 14, 14, 255, 207, 207, 208, + 255, 249, 250, 251, 255, 196, 196, 197, 255, 50, 51, 51, 255, 28, 28, 28, 255, 2, 2, 2, 255, 1, 1, 1, 255, 15, 15, 15, 255, 224, 228, + 231, 255, 235, 235, 240, 255, 130, 130, 133, 255, 81, 81, 84, 255, 72, 72, 74, 255, 10, 10, 10, 255, 0, 0, 0, 255, 0, 0, 0, 255, 5, + 5, 5, 255, 182, 184, 198, 255, 204, 215, 229, 255, 203, 219, 232, 255, 201, 221, 235, 255, 192, 219, 232, 255, 198, 229, 241, 255, 191, 202, 218, 255, + 200, 201, 214, 255, 179, 177, 204, 255, 178, 174, 202, 255, 179, 173, 202, 255, 178, 176, 205, 255, 171, 204, 225, 255, 169, 191, 217, 255, 167, 205, 227, + 255, 162, 227, 243, 255, 162, 226, 242, 255, 163, 225, 242, 255, 163, 224, 241, 255, 163, 223, 240, 255, 163, 222, 240, 255, 188, 222, 235, 255, 221, 207, + 212, 255, 227, 214, 218, 255, 236, 228, 228, 255, 231, 222, 223, 255, 217, 205, 212, 255, 197, 185, 201, 255, 187, 172, 198, 255, 187, 179, 201, 255, 185, + 181, 203, 255, 183, 179, 202, 255, 176, 176, 203, 255, 170, 184, 213, 255, 169, 174, 206, 255, 169, 173, 205, 255, 169, 173, 205, 255, 170, 173, 205, 255, + 174, 168, 200, 255, 172, 170, 202, 255, 170, 187, 214, 255, 171, 186, 212, 255, 171, 186, 210, 255, 171, 180, 207, 255, 177, 167, 201, 255, 179, 167, 201, + 255, 175, 183, 208, 255, 174, 206, 226, 255, 175, 187, 212, 255, 176, 197, 218, 255, 175, 202, 223, 255, 175, 214, 233, 255, 176, 212, 231, 255, 183, 204, + 225, 255, 185, 204, 224, 255, 177, 201, 221, 255, 175, 201, 221, 255, 175, 200, 220, 255, 175, 200, 220, 255, 175, 200, 220, 255, 175, 200, 220, 255, 175, + 200, 220, 255, 175, 200, 220, 255, 176, 200, 220, 255, 176, 199, 219, 255, 177, 197, 218, 255, 177, 195, 214, 255, 177, 198, 218, 255, 177, 205, 225, 255, + 227, 243, 248, 255, 231, 245, 249, 255, 234, 247, 250, 255, 96, 101, 102, 255, 1, 1, 1, 255, 207, 214, 215, 255, 243, 250, 252, 255, 245, 250, 252, + 255, 104, 107, 107, 255, 79, 80, 80, 255, 249, 252, 252, 255, 251, 253, 253, 255, 223, 224, 225, 255, 9, 9, 9, 255, 210, 211, 212, 255, 125, 125, + 126, 255, 83, 83, 83, 255, 172, 172, 172, 255, 48, 48, 48, 255, 244, 244, 244, 255, 51, 51, 51, 255, 141, 141, 141, 255, 248, 248, 248, 255, 251, + 251, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 85, 85, 85, 255, 1, 1, 1, 255, 0, 0, 0, 255, 1, 1, 1, 255, + 48, 48, 48, 255, 101, 101, 101, 255, 161, 162, 162, 255, 253, 254, 254, 255, 250, 251, 251, 255, 77, 77, 78, 255, 77, 77, 77, 255, 250, 250, 251, + 255, 251, 251, 252, 255, 245, 246, 247, 255, 241, 243, 243, 255, 237, 240, 240, 255, 147, 149, 150, 255, 11, 11, 11, 255, 25, 25, 26, 255, 237, 242, + 245, 255, 236, 236, 241, 255, 131, 131, 135, 255, 79, 80, 82, 255, 15, 16, 16, 255, 0, 0, 0, 255, 1, 1, 1, 255, 1, 1, 1, 255, 5, + 5, 5, 255, 185, 189, 201, 255, 202, 203, 221, 255, 197, 198, 217, 255, 194, 194, 214, 255, 192, 192, 213, 255, 195, 207, 222, 255, 190, 202, 219, 255, + 184, 183, 207, 255, 179, 177, 204, 255, 177, 174, 202, 255, 178, 172, 201, 255, 179, 173, 202, 255, 182, 192, 215, 255, 182, 183, 208, 255, 179, 200, 221, + 255, 163, 223, 240, 255, 163, 223, 240, 255, 163, 223, 239, 255, 164, 222, 239, 255, 164, 222, 239, 255, 166, 221, 239, 255, 215, 220, 225, 255, 218, 204, + 210, 255, 228, 218, 220, 255, 238, 231, 231, 255, 228, 220, 222, 255, 210, 198, 207, 255, 195, 182, 200, 255, 187, 171, 197, 255, 185, 170, 198, 255, 182, + 177, 201, 255, 177, 173, 200, 255, 177, 176, 202, 255, 171, 183, 211, 255, 170, 180, 209, 255, 170, 174, 205, 255, 170, 174, 205, 255, 171, 173, 204, 255, + 174, 170, 201, 255, 170, 175, 205, 255, 170, 187, 213, 255, 170, 183, 210, 255, 171, 182, 208, 255, 176, 173, 204, 255, 179, 169, 201, 255, 181, 169, 202, + 255, 173, 192, 214, 255, 174, 203, 223, 255, 176, 181, 208, 255, 175, 199, 219, 255, 176, 196, 217, 255, 176, 215, 233, 255, 176, 216, 234, 255, 181, 204, + 224, 255, 191, 206, 226, 255, 175, 202, 221, 255, 174, 202, 221, 255, 175, 201, 221, 255, 174, 201, 220, 255, 174, 201, 220, 255, 174, 200, 220, 255, 174, + 200, 220, 255, 174, 200, 220, 255, 174, 200, 219, 255, 174, 199, 218, 255, 175, 197, 217, 255, 176, 193, 213, 255, 176, 196, 216, 255, 176, 203, 224, 255, + 227, 246, 250, 255, 231, 247, 251, 255, 234, 248, 251, 255, 97, 102, 103, 255, 1, 1, 1, 255, 207, 215, 216, 255, 244, 251, 253, 255, 246, 251, 252, + 255, 105, 107, 107, 255, 76, 77, 77, 255, 250, 252, 253, 255, 251, 253, 254, 255, 223, 224, 225, 255, 9, 9, 9, 255, 210, 211, 211, 255, 175, 176, + 176, 255, 49, 49, 49, 255, 133, 133, 133, 255, 95, 95, 95, 255, 253, 253, 253, 255, 50, 50, 50, 255, 22, 22, 22, 255, 38, 38, 38, 255, 141, + 141, 141, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 85, 85, 85, 255, 1, 1, 1, 255, 0, 0, 0, 255, 1, 1, 1, 255, + 120, 120, 120, 255, 252, 252, 252, 255, 253, 253, 253, 255, 253, 253, 253, 255, 179, 179, 180, 255, 11, 11, 11, 255, 135, 135, 135, 255, 252, 253, 253, + 255, 251, 253, 254, 255, 211, 214, 214, 255, 193, 196, 196, 255, 244, 249, 250, 255, 246, 251, 252, 255, 102, 104, 105, 255, 41, 41, 42, 255, 239, 240, + 244, 255, 235, 235, 241, 255, 233, 238, 243, 255, 232, 247, 251, 255, 189, 203, 206, 255, 31, 33, 34, 255, 2, 2, 2, 255, 1, 1, 1, 255, 6, + 6, 6, 255, 191, 216, 222, 255, 208, 237, 246, 255, 199, 222, 235, 255, 196, 214, 228, 255, 195, 212, 226, 255, 193, 204, 221, 255, 187, 193, 214, 255, + 181, 181, 207, 255, 178, 178, 204, 255, 177, 175, 202, 255, 181, 174, 202, 255, 180, 174, 202, 255, 203, 211, 219, 255, 191, 202, 215, 255, 187, 224, 233, + 255, 164, 230, 245, 255, 164, 229, 244, 255, 165, 228, 244, 255, 165, 227, 244, 255, 166, 227, 243, 255, 185, 226, 238, 255, 223, 210, 213, 255, 213, 199, + 207, 255, 211, 196, 205, 255, 234, 226, 226, 255, 226, 214, 218, 255, 209, 195, 205, 255, 195, 182, 200, 255, 189, 174, 198, 255, 187, 171, 198, 255, 183, + 176, 200, 255, 176, 172, 199, 255, 178, 174, 200, 255, 175, 172, 202, 255, 172, 176, 206, 255, 171, 177, 207, 255, 171, 175, 205, 255, 172, 173, 203, 255, + 171, 174, 204, 255, 171, 184, 209, 255, 172, 183, 210, 255, 170, 182, 208, 255, 174, 176, 205, 255, 180, 171, 202, 255, 182, 173, 203, 255, 180, 176, 204, + 255, 174, 191, 212, 255, 176, 197, 218, 255, 177, 181, 208, 255, 175, 193, 214, 255, 175, 197, 218, 255, 176, 214, 232, 255, 177, 221, 238, 255, 176, 207, + 226, 255, 192, 207, 227, 255, 175, 200, 219, 255, 174, 199, 218, 255, 174, 199, 218, 255, 174, 199, 218, 255, 174, 199, 218, 255, 173, 199, 218, 255, 174, + 198, 218, 255, 174, 198, 218, 255, 174, 197, 217, 255, 174, 196, 216, 255, 174, 195, 214, 255, 174, 193, 212, 255, 175, 195, 214, 255, 175, 202, 222, 255, + 227, 245, 249, 255, 231, 246, 250, 255, 234, 248, 251, 255, 97, 101, 102, 255, 1, 1, 1, 255, 207, 214, 216, 255, 244, 250, 252, 255, 245, 250, 251, + 255, 104, 107, 107, 255, 72, 73, 73, 255, 249, 252, 252, 255, 251, 253, 253, 255, 223, 224, 225, 255, 9, 9, 9, 255, 209, 210, 210, 255, 214, 215, + 215, 255, 32, 32, 32, 255, 68, 69, 69, 255, 149, 149, 149, 255, 253, 253, 253, 255, 51, 51, 51, 255, 114, 114, 114, 255, 201, 201, 201, 255, 226, + 226, 226, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 84, 84, 84, 255, 1, 1, 1, 255, 0, 0, 0, 255, 1, 1, 1, 255, + 61, 61, 61, 255, 118, 118, 118, 255, 167, 168, 168, 255, 253, 254, 254, 255, 249, 250, 250, 255, 109, 109, 109, 255, 148, 148, 149, 255, 253, 254, 254, + 255, 245, 247, 247, 255, 43, 43, 43, 255, 12, 12, 12, 255, 193, 194, 195, 255, 245, 246, 248, 255, 161, 162, 164, 255, 31, 31, 32, 255, 109, 111, + 112, 255, 89, 91, 92, 255, 142, 147, 148, 255, 240, 251, 254, 255, 237, 249, 252, 255, 120, 127, 130, 255, 3, 3, 3, 255, 2, 2, 2, 255, 6, + 7, 7, 255, 198, 219, 225, 255, 218, 245, 253, 255, 214, 244, 252, 255, 209, 243, 251, 255, 198, 236, 246, 255, 193, 212, 228, 255, 188, 199, 217, 255, + 189, 189, 210, 255, 179, 178, 204, 255, 178, 176, 202, 255, 181, 174, 202, 255, 182, 173, 202, 255, 173, 217, 233, 255, 168, 202, 223, 255, 166, 222, 239, + 255, 165, 225, 241, 255, 166, 224, 240, 255, 166, 224, 240, 255, 167, 223, 239, 255, 167, 222, 239, 255, 187, 222, 233, 255, 212, 195, 206, 255, 204, 186, + 201, 255, 207, 190, 203, 255, 230, 221, 223, 255, 226, 215, 217, 255, 213, 198, 207, 255, 206, 192, 204, 255, 195, 180, 200, 255, 191, 175, 199, 255, 189, + 174, 200, 255, 182, 175, 200, 255, 177, 173, 200, 255, 178, 172, 200, 255, 179, 172, 202, 255, 176, 173, 203, 255, 176, 173, 204, 255, 176, 175, 205, 255, + 174, 181, 207, 255, 173, 182, 208, 255, 173, 180, 208, 255, 174, 177, 205, 255, 176, 179, 206, 255, 179, 180, 207, 255, 181, 176, 204, 255, 179, 180, 207, + 255, 175, 190, 211, 255, 184, 193, 214, 255, 177, 183, 209, 255, 176, 186, 210, 255, 175, 195, 216, 255, 176, 211, 230, 255, 176, 219, 236, 255, 175, 214, + 231, 255, 191, 212, 230, 255, 176, 203, 221, 255, 174, 201, 220, 255, 174, 201, 220, 255, 174, 201, 220, 255, 174, 201, 220, 255, 173, 201, 220, 255, 173, + 201, 220, 255, 173, 201, 220, 255, 173, 200, 220, 255, 173, 199, 218, 255, 173, 197, 216, 255, 173, 194, 213, 255, 174, 197, 215, 255, 173, 205, 224, 255, + 227, 244, 248, 255, 231, 246, 250, 255, 233, 247, 250, 255, 97, 101, 102, 255, 1, 1, 1, 255, 207, 214, 216, 255, 244, 250, 252, 255, 246, 251, 252, + 255, 105, 107, 107, 255, 69, 70, 70, 255, 249, 251, 252, 255, 250, 252, 253, 255, 223, 224, 225, 255, 9, 9, 9, 255, 210, 210, 211, 255, 246, 247, + 247, 255, 39, 39, 39, 255, 12, 12, 12, 255, 199, 199, 199, 255, 253, 253, 253, 255, 51, 51, 51, 255, 142, 142, 142, 255, 253, 253, 253, 255, 254, + 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 84, 84, 84, 255, 1, 1, 1, 255, 0, 0, 0, 255, 0, 0, 0, 255, + 1, 1, 1, 255, 3, 3, 3, 255, 34, 34, 34, 255, 251, 252, 252, 255, 253, 254, 254, 255, 182, 182, 182, 255, 109, 109, 110, 255, 251, 252, 253, + 255, 248, 249, 250, 255, 63, 63, 63, 255, 19, 19, 19, 255, 203, 205, 206, 255, 247, 250, 252, 255, 146, 149, 150, 255, 2, 2, 2, 255, 3, 3, + 3, 255, 3, 3, 3, 255, 7, 7, 7, 255, 222, 236, 239, 255, 231, 248, 252, 255, 136, 147, 150, 255, 3, 3, 3, 255, 2, 2, 2, 255, 7, + 7, 7, 255, 190, 217, 224, 255, 209, 243, 251, 255, 205, 242, 250, 255, 201, 240, 249, 255, 194, 237, 247, 255, 191, 229, 241, 255, 190, 211, 226, 255, + 193, 197, 213, 255, 180, 179, 204, 255, 177, 176, 202, 255, 182, 175, 201, 255, 176, 174, 202, 255, 177, 190, 213, 255, 169, 219, 236, 255, 166, 228, 243, + 255, 167, 227, 243, 255, 167, 227, 242, 255, 168, 227, 242, 255, 169, 226, 242, 255, 169, 226, 241, 255, 171, 226, 241, 255, 182, 216, 232, 255, 195, 205, + 220, 255, 231, 223, 223, 255, 231, 223, 223, 255, 225, 212, 215, 255, 215, 200, 208, 255, 220, 207, 212, 255, 204, 190, 204, 255, 197, 180, 200, 255, 196, + 179, 201, 255, 194, 178, 201, 255, 186, 177, 202, 255, 181, 176, 202, 255, 184, 176, 202, 255, 184, 176, 201, 255, 184, 177, 203, 255, 181, 179, 206, 255, + 176, 185, 210, 255, 175, 191, 212, 255, 175, 180, 207, 255, 175, 179, 207, 255, 177, 184, 209, 255, 176, 189, 213, 255, 177, 185, 210, 255, 183, 182, 207, + 255, 177, 194, 213, 255, 186, 185, 209, 255, 179, 185, 208, 255, 181, 181, 206, 255, 178, 189, 211, 255, 175, 207, 225, 255, 176, 211, 229, 255, 176, 216, + 232, 255, 189, 215, 233, 255, 176, 203, 221, 255, 174, 203, 220, 255, 174, 202, 220, 255, 174, 202, 219, 255, 173, 201, 219, 255, 173, 200, 219, 255, 173, + 200, 219, 255, 173, 200, 218, 255, 172, 198, 217, 255, 172, 197, 216, 255, 172, 196, 215, 255, 172, 193, 212, 255, 172, 194, 214, 255, 173, 203, 222, 255, + 227, 246, 251, 255, 231, 248, 252, 255, 234, 249, 252, 255, 96, 102, 103, 255, 1, 1, 1, 255, 207, 215, 216, 255, 244, 251, 253, 255, 246, 251, 252, + 255, 105, 107, 108, 255, 42, 42, 42, 255, 150, 151, 151, 255, 152, 153, 154, 255, 212, 214, 215, 255, 9, 9, 9, 255, 210, 211, 211, 255, 251, 252, + 252, 255, 87, 87, 87, 255, 22, 22, 22, 255, 240, 240, 240, 255, 253, 253, 253, 255, 51, 51, 51, 255, 86, 86, 86, 255, 150, 150, 150, 255, 171, + 171, 171, 255, 250, 250, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 84, 84, 84, 255, 1, 1, 1, 255, 2, 2, 2, 255, 34, 34, 34, 255, + 39, 39, 39, 255, 65, 65, 65, 255, 180, 181, 181, 255, 253, 254, 254, 255, 252, 253, 253, 255, 129, 129, 129, 255, 30, 30, 30, 255, 223, 224, 225, + 255, 250, 251, 252, 255, 223, 225, 226, 255, 203, 206, 207, 255, 248, 252, 253, 255, 232, 237, 238, 255, 54, 55, 55, 255, 14, 15, 15, 255, 12, 12, + 12, 255, 18, 20, 20, 255, 106, 111, 113, 255, 238, 250, 253, 255, 232, 245, 249, 255, 87, 92, 93, 255, 4, 4, 4, 255, 3, 3, 3, 255, 8, + 8, 8, 255, 199, 220, 225, 255, 221, 246, 253, 255, 218, 244, 252, 255, 213, 244, 252, 255, 203, 242, 251, 255, 206, 242, 252, 255, 194, 225, 239, 255, + 205, 213, 221, 255, 182, 181, 205, 255, 178, 177, 202, 255, 182, 175, 202, 255, 179, 182, 208, 255, 186, 229, 243, 255, 171, 233, 247, 255, 168, 232, 246, + 255, 169, 231, 246, 255, 170, 230, 245, 255, 170, 229, 245, 255, 170, 229, 243, 255, 171, 228, 243, 255, 172, 228, 243, 255, 172, 227, 243, 255, 179, 225, + 241, 255, 225, 213, 218, 255, 217, 202, 210, 255, 207, 187, 200, 255, 223, 209, 214, 255, 224, 213, 216, 255, 211, 197, 207, 255, 201, 184, 202, 255, 202, + 185, 203, 255, 202, 186, 203, 255, 202, 186, 204, 255, 199, 186, 205, 255, 193, 182, 204, 255, 188, 181, 205, 255, 184, 187, 210, 255, 180, 203, 224, 255, + 177, 209, 226, 255, 177, 195, 215, 255, 178, 185, 210, 255, 177, 197, 214, 255, 177, 204, 219, 255, 180, 194, 215, 255, 179, 195, 216, 255, 186, 183, 207, + 255, 183, 195, 214, 255, 187, 185, 209, 255, 184, 185, 208, 255, 186, 182, 207, 255, 184, 187, 209, 255, 177, 204, 222, 255, 177, 203, 220, 255, 176, 208, + 225, 255, 180, 209, 227, 255, 176, 203, 220, 255, 175, 202, 219, 255, 174, 201, 219, 255, 174, 200, 218, 255, 174, 200, 218, 255, 173, 200, 218, 255, 173, + 199, 218, 255, 172, 199, 218, 255, 172, 198, 217, 255, 172, 197, 216, 255, 171, 196, 215, 255, 172, 193, 211, 255, 172, 194, 213, 255, 171, 202, 221, 255, + 226, 244, 248, 255, 230, 245, 249, 255, 233, 247, 250, 255, 96, 101, 102, 255, 1, 1, 1, 255, 206, 214, 216, 255, 243, 250, 252, 255, 245, 251, 252, + 255, 136, 138, 139, 255, 59, 60, 60, 255, 59, 60, 60, 255, 65, 66, 66, 255, 208, 210, 211, 255, 62, 62, 62, 255, 218, 219, 220, 255, 252, 253, + 253, 255, 162, 163, 163, 255, 102, 102, 102, 255, 253, 254, 254, 255, 254, 254, 254, 255, 91, 91, 91, 255, 56, 56, 56, 255, 55, 55, 55, 255, 95, + 95, 95, 255, 246, 246, 246, 255, 255, 255, 255, 255, 254, 254, 254, 255, 83, 83, 83, 255, 1, 1, 1, 255, 9, 9, 9, 255, 191, 191, 191, 255, + 237, 237, 237, 255, 246, 246, 246, 255, 252, 252, 252, 255, 251, 251, 252, 255, 168, 168, 168, 255, 16, 16, 16, 255, 1, 1, 1, 255, 46, 46, 46, + 255, 171, 172, 172, 255, 232, 234, 234, 255, 236, 238, 238, 255, 183, 186, 186, 255, 61, 62, 62, 255, 4, 4, 4, 255, 98, 100, 101, 255, 218, 224, + 225, 255, 220, 227, 229, 255, 236, 245, 248, 255, 238, 249, 252, 255, 155, 165, 167, 255, 12, 13, 13, 255, 4, 4, 4, 255, 4, 4, 4, 255, 9, + 9, 9, 255, 196, 219, 224, 255, 215, 244, 252, 255, 211, 243, 251, 255, 206, 242, 250, 255, 198, 239, 248, 255, 198, 239, 248, 255, 191, 221, 233, 255, + 192, 195, 212, 255, 184, 183, 206, 255, 179, 178, 203, 255, 178, 176, 201, 255, 178, 175, 202, 255, 188, 194, 216, 255, 173, 228, 242, 255, 170, 226, 241, + 255, 171, 225, 240, 255, 172, 225, 240, 255, 172, 225, 239, 255, 173, 224, 239, 255, 174, 224, 239, 255, 174, 224, 239, 255, 175, 223, 240, 255, 176, 223, + 240, 255, 205, 221, 230, 255, 229, 217, 219, 255, 227, 216, 219, 255, 234, 224, 222, 255, 228, 216, 217, 255, 215, 200, 209, 255, 206, 189, 203, 255, 207, + 190, 204, 255, 207, 191, 205, 255, 208, 194, 208, 255, 202, 200, 213, 255, 198, 197, 213, 255, 185, 197, 215, 255, 180, 207, 224, 255, 180, 213, 229, 255, + 180, 204, 221, 255, 181, 186, 210, 255, 186, 189, 211, 255, 183, 201, 216, 255, 179, 218, 229, 255, 182, 214, 227, 255, 188, 189, 211, 255, 188, 184, 208, + 255, 187, 193, 212, 255, 187, 186, 209, 255, 187, 184, 208, 255, 190, 186, 208, 255, 187, 190, 210, 255, 179, 199, 217, 255, 184, 198, 216, 255, 183, 203, + 219, 255, 180, 208, 224, 255, 178, 206, 222, 255, 176, 204, 221, 255, 175, 204, 221, 255, 174, 204, 221, 255, 174, 203, 220, 255, 173, 203, 220, 255, 173, + 203, 220, 255, 172, 202, 220, 255, 171, 201, 219, 255, 171, 200, 218, 255, 171, 198, 216, 255, 171, 195, 213, 255, 171, 196, 214, 255, 170, 204, 223, 255, + 226, 246, 251, 255, 230, 248, 252, 255, 233, 249, 252, 255, 96, 102, 103, 255, 1, 1, 1, 255, 205, 213, 215, 255, 243, 251, 252, 255, 246, 252, 253, + 255, 246, 251, 252, 255, 247, 251, 252, 255, 248, 251, 252, 255, 249, 251, 252, 255, 251, 253, 254, 255, 250, 252, 252, 255, 252, 253, 253, 255, 253, 254, + 254, 255, 252, 252, 253, 255, 251, 251, 252, 255, 253, 253, 254, 255, 254, 254, 254, 255, 252, 252, 252, 255, 252, 252, 252, 255, 252, 252, 252, 255, 252, + 252, 252, 255, 254, 254, 254, 255, 254, 254, 254, 255, 254, 254, 254, 255, 83, 83, 83, 255, 1, 1, 1, 255, 2, 2, 2, 255, 112, 112, 112, 255, + 179, 179, 179, 255, 177, 177, 177, 255, 148, 148, 148, 255, 69, 69, 69, 255, 4, 4, 4, 255, 0, 0, 0, 255, 0, 0, 0, 255, 1, 1, 1, + 255, 1, 1, 1, 255, 2, 3, 3, 255, 5, 5, 5, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 35, 36, 36, 255, 198, 206, + 207, 255, 200, 209, 211, 255, 168, 177, 179, 255, 89, 94, 96, 255, 8, 8, 8, 255, 5, 5, 5, 255, 4, 4, 4, 255, 5, 5, 5, 255, 10, + 10, 10, 255, 193, 218, 224, 255, 214, 244, 251, 255, 210, 243, 251, 255, 207, 242, 250, 255, 199, 239, 249, 255, 200, 240, 250, 255, 194, 207, 221, 255, + 189, 189, 209, 255, 183, 181, 205, 255, 180, 178, 203, 255, 179, 177, 201, 255, 178, 176, 201, 255, 183, 179, 204, 255, 176, 232, 246, 255, 173, 232, 246, + 255, 172, 232, 246, 255, 173, 232, 246, 255, 174, 231, 245, 255, 175, 231, 245, 255, 176, 231, 245, 255, 177, 231, 245, 255, 177, 230, 245, 255, 178, 230, + 245, 255, 194, 228, 240, 255, 233, 223, 225, 255, 228, 217, 219, 255, 233, 224, 223, 255, 229, 217, 218, 255, 215, 201, 209, 255, 210, 193, 205, 255, 211, + 195, 207, 255, 209, 201, 213, 255, 201, 209, 222, 255, 196, 208, 222, 255, 200, 199, 214, 255, 191, 197, 215, 255, 183, 213, 228, 255, 183, 217, 232, 255, + 184, 207, 224, 255, 187, 186, 210, 255, 195, 188, 208, 255, 192, 195, 213, 255, 185, 220, 229, 255, 195, 231, 237, 255, 203, 217, 225, 255, 209, 201, 216, + 255, 209, 205, 219, 255, 204, 205, 219, 255, 205, 198, 216, 255, 201, 198, 215, 255, 192, 198, 215, 255, 184, 199, 217, 255, 195, 196, 213, 255, 192, 204, + 219, 255, 180, 207, 223, 255, 179, 205, 222, 255, 176, 204, 220, 255, 176, 203, 220, 255, 175, 203, 219, 255, 174, 203, 219, 255, 173, 202, 219, 255, 173, + 201, 218, 255, 172, 200, 218, 255, 172, 199, 218, 255, 171, 198, 216, 255, 171, 197, 215, 255, 170, 194, 212, 255, 170, 194, 212, 255, 169, 201, 220, 255, + 225, 244, 249, 255, 229, 246, 250, 255, 232, 247, 250, 255, 96, 101, 103, 255, 1, 1, 1, 255, 87, 90, 91, 255, 133, 137, 138, 255, 134, 138, 139, + 255, 135, 138, 139, 255, 136, 139, 139, 255, 136, 139, 139, 255, 138, 139, 139, 255, 138, 139, 140, 255, 138, 139, 140, 255, 139, 139, 140, 255, 139, 139, + 140, 255, 139, 139, 140, 255, 139, 139, 140, 255, 140, 140, 140, 255, 140, 140, 140, 255, 140, 140, 140, 255, 140, 140, 140, 255, 140, 140, 140, 255, 140, + 140, 140, 255, 140, 140, 140, 255, 144, 145, 145, 255, 237, 237, 237, 255, 82, 82, 82, 255, 1, 1, 1, 255, 0, 0, 0, 255, 1, 1, 1, 255, + 1, 1, 1, 255, 1, 1, 1, 255, 2, 2, 2, 255, 1, 1, 1, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, + 255, 0, 0, 0, 255, 0, 0, 0, 255, 1, 1, 1, 255, 1, 1, 1, 255, 0, 0, 0, 255, 1, 1, 1, 255, 1, 1, 1, 255, 7, 7, + 7, 255, 9, 9, 9, 255, 4, 4, 4, 255, 4, 4, 4, 255, 4, 4, 4, 255, 4, 4, 4, 255, 5, 5, 5, 255, 6, 6, 6, 255, 12, + 12, 12, 255, 202, 220, 226, 255, 223, 246, 253, 255, 220, 245, 253, 255, 215, 245, 252, 255, 205, 242, 251, 255, 207, 242, 252, 255, 195, 208, 222, 255, + 189, 189, 209, 255, 183, 182, 205, 255, 181, 179, 203, 255, 180, 178, 201, 255, 180, 177, 201, 255, 181, 177, 202, 255, 179, 229, 243, 255, 174, 231, 245, + 255, 175, 231, 244, 255, 176, 230, 244, 255, 177, 229, 243, 255, 178, 229, 243, 255, 178, 228, 242, 255, 179, 228, 242, 255, 180, 227, 242, 255, 180, 227, + 242, 255, 192, 226, 240, 255, 230, 220, 222, 255, 230, 219, 220, 255, 232, 223, 222, 255, 225, 213, 216, 255, 215, 200, 208, 255, 213, 198, 210, 255, 211, + 205, 218, 255, 210, 206, 219, 255, 212, 202, 214, 255, 212, 200, 212, 255, 207, 197, 212, 255, 194, 203, 218, 255, 186, 216, 230, 255, 186, 223, 236, 255, + 192, 199, 217, 255, 195, 189, 210, 255, 200, 190, 209, 255, 204, 195, 210, 255, 207, 213, 221, 255, 225, 227, 226, 255, 235, 220, 215, 255, 236, 224, 223, + 255, 242, 232, 232, 255, 244, 234, 234, 255, 245, 235, 234, 255, 244, 235, 235, 255, 233, 228, 233, 255, 203, 210, 223, 255, 200, 197, 213, 255, 199, 206, + 221, 255, 181, 207, 222, 255, 183, 206, 223, 255, 180, 205, 221, 255, 182, 205, 221, 255, 177, 204, 220, 255, 175, 203, 219, 255, 175, 202, 219, 255, 174, + 202, 219, 255, 173, 201, 218, 255, 172, 200, 218, 255, 171, 199, 217, 255, 171, 198, 215, 255, 170, 194, 212, 255, 170, 194, 212, 255, 169, 202, 219, 255, + 224, 245, 250, 255, 228, 246, 251, 255, 231, 248, 251, 255, 101, 107, 109, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, + 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, + 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, + 2, 2, 255, 2, 2, 2, 255, 13, 13, 13, 255, 217, 217, 217, 255, 82, 82, 82, 255, 2, 2, 2, 255, 1, 1, 1, 255, 1, 1, 1, 255, + 1, 1, 1, 255, 1, 1, 1, 255, 1, 1, 1, 255, 1, 1, 1, 255, 1, 1, 1, 255, 1, 1, 1, 255, 1, 1, 1, 255, 1, 1, 1, + 255, 1, 1, 1, 255, 2, 2, 2, 255, 2, 2, 2, 255, 2, 2, 2, 255, 1, 1, 1, 255, 2, 2, 2, 255, 3, 3, 3, 255, 3, 3, + 3, 255, 3, 3, 3, 255, 4, 4, 4, 255, 5, 5, 5, 255, 6, 6, 6, 255, 7, 7, 7, 255, 8, 8, 8, 255, 9, 9, 9, 255, 18, + 19, 20, 255, 195, 221, 227, 255, 211, 243, 250, 255, 207, 242, 250, 255, 203, 241, 249, 255, 197, 237, 247, 255, 196, 238, 248, 255, 194, 208, 222, 255, + 190, 190, 210, 255, 185, 182, 207, 255, 182, 180, 203, 255, 182, 179, 202, 255, 181, 178, 202, 255, 182, 178, 202, 255, 184, 221, 237, 255, 177, 229, 242, + 255, 177, 228, 242, 255, 179, 228, 242, 255, 179, 228, 241, 255, 180, 228, 242, 255, 181, 228, 242, 255, 182, 227, 241, 255, 183, 227, 241, 255, 184, 227, + 242, 255, 185, 227, 242, 255, 223, 226, 230, 255, 235, 226, 226, 255, 227, 216, 219, 255, 218, 204, 211, 255, 215, 199, 209, 255, 217, 203, 213, 255, 218, + 205, 214, 255, 218, 201, 211, 255, 216, 200, 210, 255, 213, 199, 211, 255, 209, 198, 212, 255, 203, 203, 217, 255, 191, 215, 228, 255, 196, 209, 223, 255, + 200, 193, 212, 255, 205, 196, 211, 255, 211, 200, 211, 255, 222, 208, 212, 255, 234, 221, 215, 255, 239, 224, 214, 255, 234, 219, 215, 255, 232, 217, 217, + 255, 243, 229, 227, 255, 246, 233, 231, 255, 248, 236, 233, 255, 248, 237, 233, 255, 248, 237, 233, 255, 244, 236, 236, 255, 220, 219, 227, 255, 202, 212, + 227, 255, 185, 211, 226, 255, 180, 209, 224, 255, 180, 208, 223, 255, 180, 207, 223, 255, 177, 206, 222, 255, 176, 206, 222, 255, 175, 205, 221, 255, 174, + 205, 221, 255, 173, 204, 221, 255, 172, 203, 220, 255, 172, 202, 219, 255, 170, 200, 217, 255, 169, 197, 214, 255, 168, 195, 213, 255, 168, 204, 221, 255, + 223, 246, 251, 255, 227, 247, 251, 255, 231, 248, 252, 255, 196, 209, 212, 255, 107, 112, 113, 255, 99, 103, 103, 255, 100, 103, 104, 255, 100, 102, 103, + 255, 101, 101, 102, 255, 101, 102, 102, 255, 102, 102, 103, 255, 103, 103, 104, 255, 104, 104, 105, 255, 105, 105, 105, 255, 105, 106, 106, 255, 106, 106, + 106, 255, 106, 106, 106, 255, 106, 106, 107, 255, 106, 106, 106, 255, 106, 106, 106, 255, 106, 106, 106, 255, 106, 106, 106, 255, 106, 106, 107, 255, 106, + 106, 107, 255, 107, 107, 107, 255, 112, 112, 112, 255, 232, 232, 232, 255, 152, 153, 153, 255, 107, 108, 108, 255, 107, 107, 108, 255, 107, 107, 107, 255, + 107, 107, 107, 255, 107, 108, 108, 255, 107, 107, 108, 255, 107, 108, 108, 255, 107, 107, 108, 255, 107, 107, 108, 255, 107, 107, 107, 255, 106, 107, 108, + 255, 106, 107, 107, 255, 106, 108, 108, 255, 105, 108, 108, 255, 104, 107, 107, 255, 104, 107, 108, 255, 104, 107, 108, 255, 103, 107, 108, 255, 103, 107, + 108, 255, 102, 108, 109, 255, 102, 108, 109, 255, 101, 108, 110, 255, 101, 108, 110, 255, 100, 109, 111, 255, 100, 109, 112, 255, 99, 110, 112, 255, 138, + 153, 156, 255, 221, 244, 250, 255, 221, 246, 252, 255, 218, 245, 252, 255, 215, 244, 252, 255, 207, 242, 251, 255, 209, 242, 251, 255, 196, 211, 224, 255, + 191, 191, 210, 255, 186, 184, 207, 255, 184, 181, 204, 255, 184, 180, 203, 255, 183, 179, 203, 255, 183, 179, 203, 255, 188, 223, 238, 255, 181, 235, 248, + 255, 181, 235, 247, 255, 182, 235, 247, 255, 183, 234, 247, 255, 184, 234, 246, 255, 184, 234, 246, 255, 185, 233, 246, 255, 186, 233, 245, 255, 187, 233, + 245, 255, 187, 232, 245, 255, 213, 229, 236, 255, 232, 220, 222, 255, 220, 206, 213, 255, 218, 201, 210, 255, 221, 204, 212, 255, 223, 206, 213, 255, 222, + 204, 212, 255, 218, 202, 212, 255, 217, 201, 212, 255, 215, 201, 213, 255, 213, 200, 213, 255, 211, 201, 214, 255, 208, 204, 217, 255, 208, 200, 214, 255, + 210, 201, 213, 255, 222, 209, 214, 255, 229, 214, 214, 255, 239, 224, 215, 255, 243, 229, 215, 255, 240, 224, 215, 255, 235, 219, 215, 255, 231, 214, 216, + 255, 242, 225, 223, 255, 244, 228, 224, 255, 248, 234, 229, 255, 249, 236, 231, 255, 249, 237, 232, 255, 250, 237, 233, 255, 246, 237, 235, 255, 227, 226, + 235, 255, 193, 212, 226, 255, 184, 209, 223, 255, 184, 207, 222, 255, 180, 206, 221, 255, 178, 206, 221, 255, 177, 205, 220, 255, 176, 204, 220, 255, 175, + 204, 219, 255, 174, 202, 218, 255, 173, 201, 218, 255, 172, 200, 216, 255, 170, 198, 215, 255, 169, 195, 212, 255, 169, 193, 211, 255, 167, 200, 217, 255, + 222, 243, 248, 255, 226, 245, 249, 255, 229, 246, 250, 255, 232, 247, 251, 255, 235, 248, 251, 255, 238, 250, 252, 255, 241, 250, 253, 255, 243, 247, 250, + 255, 244, 245, 248, 255, 246, 246, 249, 255, 247, 247, 249, 255, 248, 248, 251, 255, 249, 250, 252, 255, 251, 254, 254, 255, 252, 254, 254, 255, 252, 254, + 254, 255, 253, 253, 254, 255, 253, 253, 253, 255, 253, 253, 254, 255, 253, 253, 254, 255, 254, 254, 254, 255, 254, 254, 255, 255, 254, 254, 255, 255, 254, + 254, 254, 255, 254, 255, 255, 255, 254, 254, 254, 255, 254, 254, 255, 255, 254, 255, 255, 255, 254, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, + 253, 254, 254, 255, 253, 254, 254, 255, 254, 254, 255, 255, 253, 254, 255, 255, 253, 255, 255, 255, 253, 255, 255, 255, 252, 254, 254, 255, 252, 254, 254, + 255, 252, 254, 255, 255, 251, 253, 254, 255, 251, 254, 255, 255, 250, 253, 254, 255, 249, 253, 254, 255, 248, 253, 254, 255, 246, 252, 254, 255, 245, 252, + 254, 255, 244, 251, 254, 255, 242, 251, 254, 255, 239, 250, 254, 255, 237, 250, 254, 255, 236, 249, 254, 255, 233, 248, 254, 255, 230, 248, 254, 255, 227, + 247, 253, 255, 224, 246, 253, 255, 221, 246, 252, 255, 217, 245, 252, 255, 213, 244, 251, 255, 204, 241, 250, 255, 206, 242, 251, 255, 197, 213, 226, 255, + 191, 192, 211, 255, 187, 184, 207, 255, 186, 182, 205, 255, 185, 181, 204, 255, 185, 181, 203, 255, 185, 180, 203, 255, 190, 216, 232, 255, 183, 232, 244, + 255, 184, 231, 243, 255, 185, 230, 243, 255, 186, 230, 243, 255, 187, 230, 242, 255, 187, 230, 242, 255, 189, 229, 241, 255, 189, 228, 241, 255, 190, 228, + 241, 255, 191, 228, 241, 255, 195, 226, 239, 255, 224, 221, 225, 255, 225, 209, 215, 255, 222, 210, 216, 255, 214, 217, 226, 255, 206, 220, 230, 255, 216, + 214, 222, 255, 216, 203, 214, 255, 216, 202, 214, 255, 216, 203, 214, 255, 216, 204, 215, 255, 217, 206, 216, 255, 216, 206, 216, 255, 216, 206, 215, 255, + 230, 216, 216, 255, 237, 222, 216, 255, 241, 226, 217, 255, 245, 231, 217, 255, 244, 230, 217, 255, 239, 224, 216, 255, 228, 213, 216, 255, 235, 217, 219, + 255, 241, 223, 222, 255, 242, 225, 223, 255, 248, 235, 230, 255, 249, 236, 229, 255, 249, 236, 230, 255, 250, 236, 230, 255, 250, 238, 232, 255, 247, 237, + 236, 255, 214, 223, 232, 255, 186, 211, 224, 255, 182, 209, 223, 255, 182, 208, 222, 255, 180, 207, 222, 255, 179, 206, 221, 255, 178, 205, 220, 255, 176, + 204, 220, 255, 175, 203, 219, 255, 174, 203, 219, 255, 172, 201, 218, 255, 171, 199, 216, 255, 169, 196, 213, 255, 169, 194, 211, 255, 167, 201, 217, 255, + 221, 246, 251, 255, 226, 247, 252, 255, 230, 248, 252, 255, 233, 249, 253, 255, 236, 250, 253, 255, 240, 251, 254, 255, 242, 251, 253, 255, 242, 243, 247, + 255, 243, 244, 248, 255, 245, 245, 248, 255, 246, 246, 249, 255, 248, 248, 250, 255, 249, 249, 251, 255, 250, 251, 252, 255, 250, 251, 252, 255, 251, 252, + 253, 255, 252, 253, 254, 255, 253, 254, 254, 255, 253, 254, 255, 255, 254, 255, 255, 255, 254, 255, 255, 255, 253, 253, 254, 255, 254, 254, 254, 255, 254, + 254, 254, 255, 254, 255, 255, 255, 254, 255, 255, 255, 254, 255, 255, 255, 254, 254, 254, 255, 253, 254, 254, 255, 253, 254, 254, 255, 253, 254, 254, 255, + 253, 254, 254, 255, 253, 254, 254, 255, 253, 254, 254, 255, 253, 254, 255, 255, 252, 254, 255, 255, 252, 254, 254, 255, 251, 253, 254, 255, 251, 254, 255, + 255, 250, 254, 255, 255, 249, 253, 255, 255, 248, 253, 254, 255, 246, 252, 254, 255, 245, 252, 254, 255, 243, 252, 254, 255, 241, 251, 253, 255, 239, 251, + 254, 255, 236, 250, 254, 255, 234, 250, 253, 255, 232, 249, 253, 255, 229, 248, 253, 255, 226, 247, 252, 255, 223, 247, 252, 255, 221, 246, 252, 255, 218, + 246, 252, 255, 215, 245, 251, 255, 213, 244, 251, 255, 210, 243, 251, 255, 206, 242, 251, 255, 200, 239, 249, 255, 202, 240, 249, 255, 197, 215, 227, 255, + 192, 192, 211, 255, 189, 185, 208, 255, 188, 183, 205, 255, 187, 183, 204, 255, 187, 182, 204, 255, 187, 183, 205, 255, 190, 217, 233, 255, 187, 234, 246, + 255, 187, 233, 245, 255, 188, 233, 245, 255, 189, 233, 245, 255, 190, 233, 245, 255, 191, 233, 244, 255, 192, 233, 244, 255, 193, 232, 244, 255, 193, 232, + 244, 255, 194, 232, 244, 255, 195, 231, 243, 255, 199, 219, 230, 255, 211, 210, 221, 255, 205, 213, 224, 255, 197, 227, 239, 255, 198, 230, 241, 255, 203, + 227, 238, 255, 220, 209, 219, 255, 219, 207, 217, 255, 219, 207, 217, 255, 220, 209, 218, 255, 223, 213, 220, 255, 223, 213, 219, 255, 233, 221, 219, 255, + 240, 226, 219, 255, 243, 230, 219, 255, 244, 230, 218, 255, 245, 234, 219, 255, 244, 230, 218, 255, 233, 219, 217, 255, 221, 207, 215, 255, 231, 214, 218, + 255, 242, 225, 223, 255, 243, 226, 223, 255, 248, 235, 229, 255, 249, 236, 230, 255, 249, 236, 229, 255, 249, 234, 227, 255, 249, 234, 227, 255, 250, 238, + 233, 255, 245, 237, 235, 255, 215, 223, 232, 255, 186, 212, 226, 255, 184, 211, 225, 255, 182, 210, 224, 255, 180, 209, 223, 255, 179, 208, 223, 255, 177, + 207, 222, 255, 176, 206, 222, 255, 175, 205, 221, 255, 173, 204, 220, 255, 172, 201, 217, 255, 171, 199, 214, 255, 170, 196, 213, 255, 169, 202, 218, 255, + 220, 242, 248, 255, 223, 244, 249, 255, 227, 245, 250, 255, 230, 246, 250, 255, 233, 247, 251, 255, 236, 249, 252, 255, 239, 247, 250, 255, 240, 241, 246, + 255, 243, 250, 252, 255, 244, 245, 249, 255, 245, 245, 248, 255, 247, 247, 250, 255, 248, 249, 251, 255, 249, 251, 252, 255, 250, 252, 253, 255, 251, 254, + 254, 255, 252, 254, 254, 255, 252, 254, 255, 255, 252, 254, 254, 255, 253, 254, 254, 255, 253, 253, 254, 255, 253, 254, 254, 255, 253, 254, 255, 255, 253, + 254, 255, 255, 253, 254, 254, 255, 253, 255, 255, 255, 253, 254, 254, 255, 253, 254, 254, 255, 253, 254, 254, 255, 253, 253, 254, 255, 253, 253, 254, 255, + 252, 253, 254, 255, 253, 254, 255, 255, 253, 254, 255, 255, 253, 254, 255, 255, 252, 254, 254, 255, 252, 254, 254, 255, 251, 254, 255, 255, 251, 254, 255, + 255, 250, 253, 254, 255, 250, 253, 254, 255, 249, 253, 255, 255, 248, 253, 254, 255, 247, 252, 254, 255, 246, 252, 254, 255, 245, 252, 254, 255, 243, 252, + 254, 255, 242, 251, 254, 255, 241, 251, 254, 255, 239, 250, 254, 255, 238, 250, 253, 255, 236, 249, 254, 255, 234, 249, 254, 255, 232, 248, 253, 255, 230, + 248, 253, 255, 228, 248, 253, 255, 226, 247, 253, 255, 223, 246, 253, 255, 220, 245, 253, 255, 210, 243, 251, 255, 214, 244, 252, 255, 204, 224, 235, 255, + 193, 192, 211, 255, 190, 185, 208, 255, 190, 185, 206, 255, 190, 184, 205, 255, 189, 184, 206, 255, 191, 185, 207, 255, 194, 232, 244, 255, 192, 237, 249, + 255, 192, 237, 248, 255, 191, 236, 248, 255, 192, 236, 247, 255, 193, 236, 247, 255, 194, 235, 246, 255, 195, 235, 246, 255, 196, 235, 245, 255, 197, 234, + 245, 255, 198, 234, 245, 255, 199, 233, 243, 255, 202, 221, 231, 255, 211, 211, 222, 255, 208, 215, 225, 255, 201, 228, 239, 255, 201, 231, 241, 255, 202, + 231, 240, 255, 223, 225, 229, 255, 228, 217, 222, 255, 226, 215, 221, 255, 226, 217, 222, 255, 229, 221, 224, 255, 233, 223, 223, 255, 241, 228, 221, 255, + 243, 231, 221, 255, 243, 230, 221, 255, 242, 227, 219, 255, 246, 234, 221, 255, 244, 232, 220, 255, 229, 214, 217, 255, 222, 209, 217, 255, 227, 212, 217, + 255, 243, 226, 224, 255, 243, 227, 224, 255, 247, 232, 227, 255, 249, 236, 229, 255, 250, 237, 230, 255, 248, 232, 226, 255, 249, 234, 226, 255, 250, 237, + 230, 255, 249, 238, 232, 255, 246, 236, 236, 255, 211, 220, 230, 255, 188, 211, 224, 255, 184, 210, 223, 255, 182, 208, 222, 255, 181, 207, 221, 255, 180, + 206, 221, 255, 178, 205, 220, 255, 177, 204, 219, 255, 175, 202, 217, 255, 174, 200, 216, 255, 173, 197, 213, 255, 172, 194, 211, 255, 170, 199, 216, 255, + 218, 244, 250, 255, 223, 245, 250, 255, 226, 247, 251, 255, 230, 248, 252, 255, 234, 249, 252, 255, 236, 249, 253, 255, 238, 243, 247, 255, 239, 244, 248, + 255, 244, 252, 254, 255, 245, 251, 253, 255, 244, 245, 248, 255, 246, 247, 250, 255, 247, 249, 251, 255, 249, 250, 252, 255, 251, 254, 254, 255, 252, 254, + 255, 255, 252, 254, 255, 255, 252, 254, 254, 255, 253, 254, 254, 255, 252, 253, 253, 255, 253, 254, 254, 255, 254, 254, 255, 255, 254, 254, 255, 255, 254, + 255, 255, 255, 254, 255, 255, 255, 254, 255, 255, 255, 254, 255, 255, 255, 253, 254, 255, 255, 253, 255, 255, 255, 252, 253, 254, 255, 252, 253, 254, 255, + 252, 253, 253, 255, 253, 254, 255, 255, 253, 254, 255, 255, 252, 254, 254, 255, 252, 254, 254, 255, 252, 254, 254, 255, 251, 253, 254, 255, 251, 254, 255, + 255, 250, 253, 254, 255, 249, 253, 254, 255, 248, 253, 254, 255, 247, 252, 254, 255, 246, 252, 254, 255, 244, 252, 254, 255, 242, 251, 254, 255, 240, 250, + 253, 255, 238, 250, 253, 255, 236, 249, 253, 255, 234, 249, 253, 255, 230, 248, 252, 255, 228, 247, 252, 255, 225, 247, 252, 255, 223, 246, 252, 255, 219, + 245, 251, 255, 216, 244, 251, 255, 213, 243, 251, 255, 210, 243, 251, 255, 208, 241, 250, 255, 201, 238, 248, 255, 202, 239, 249, 255, 200, 235, 245, 255, + 195, 201, 219, 255, 192, 186, 208, 255, 192, 186, 207, 255, 192, 185, 207, 255, 193, 188, 208, 255, 194, 207, 224, 255, 193, 233, 244, 255, 193, 232, 243, + 255, 194, 232, 243, 255, 195, 232, 243, 255, 196, 232, 243, 255, 197, 231, 243, 255, 198, 231, 242, 255, 199, 231, 242, 255, 200, 231, 242, 255, 201, 231, + 242, 255, 201, 231, 241, 255, 202, 230, 240, 255, 205, 221, 231, 255, 214, 214, 224, 255, 211, 216, 227, 255, 204, 228, 238, 255, 205, 230, 240, 255, 205, + 230, 239, 255, 208, 230, 238, 255, 230, 228, 230, 255, 235, 225, 226, 255, 234, 225, 226, 255, 236, 227, 227, 255, 242, 231, 225, 255, 243, 231, 223, 255, + 243, 230, 223, 255, 243, 229, 222, 255, 241, 227, 221, 255, 247, 236, 223, 255, 244, 233, 222, 255, 229, 214, 219, 255, 223, 211, 219, 255, 225, 213, 219, + 255, 243, 226, 224, 255, 244, 227, 225, 255, 246, 230, 226, 255, 249, 235, 229, 255, 250, 237, 230, 255, 248, 233, 227, 255, 251, 239, 231, 255, 251, 237, + 229, 255, 246, 228, 224, 255, 250, 238, 233, 255, 245, 235, 237, 255, 208, 219, 231, 255, 195, 214, 227, 255, 198, 213, 227, 255, 189, 211, 224, 255, 182, + 208, 222, 255, 180, 207, 221, 255, 179, 206, 221, 255, 177, 205, 219, 255, 176, 202, 218, 255, 174, 200, 216, 255, 173, 196, 213, 255, 172, 201, 217, 255, + 217, 243, 249, 255, 221, 245, 250, 255, 225, 246, 251, 255, 228, 247, 251, 255, 231, 248, 252, 255, 234, 247, 251, 255, 235, 236, 242, 255, 239, 248, 251, + 255, 241, 251, 253, 255, 243, 251, 253, 255, 243, 244, 248, 255, 246, 250, 252, 255, 248, 253, 254, 255, 248, 253, 254, 255, 250, 253, 254, 255, 250, 253, + 254, 255, 251, 253, 254, 255, 251, 252, 253, 255, 251, 252, 253, 255, 252, 253, 254, 255, 252, 254, 255, 255, 252, 254, 255, 255, 252, 254, 255, 255, 252, + 254, 254, 255, 252, 254, 254, 255, 252, 254, 254, 255, 252, 254, 254, 255, 252, 254, 254, 255, 252, 254, 254, 255, 252, 253, 253, 255, 251, 253, 253, 255, + 251, 253, 253, 255, 251, 254, 255, 255, 251, 253, 254, 255, 251, 254, 254, 255, 250, 254, 254, 255, 250, 253, 254, 255, 249, 253, 254, 255, 248, 253, 254, + 255, 247, 253, 254, 255, 246, 252, 254, 255, 245, 252, 254, 255, 243, 252, 254, 255, 241, 251, 253, 255, 240, 251, 253, 255, 238, 250, 253, 255, 237, 250, + 253, 255, 235, 249, 253, 255, 233, 249, 253, 255, 231, 248, 252, 255, 229, 247, 253, 255, 227, 247, 252, 255, 225, 246, 252, 255, 223, 246, 252, 255, 221, + 245, 252, 255, 219, 245, 252, 255, 218, 245, 252, 255, 216, 243, 252, 255, 214, 243, 251, 255, 206, 241, 250, 255, 209, 242, 250, 255, 209, 242, 250, 255, + 203, 235, 246, 255, 195, 215, 230, 255, 195, 210, 226, 255, 196, 215, 230, 255, 198, 227, 239, 255, 201, 237, 248, 255, 198, 238, 248, 255, 197, 237, 248, + 255, 197, 237, 248, 255, 198, 237, 248, 255, 199, 237, 248, 255, 200, 237, 247, 255, 202, 237, 247, 255, 202, 237, 246, 255, 203, 237, 246, 255, 204, 236, + 246, 255, 205, 236, 246, 255, 206, 235, 244, 255, 208, 225, 234, 255, 216, 216, 226, 255, 214, 219, 228, 255, 208, 232, 241, 255, 208, 235, 243, 255, 209, + 235, 243, 255, 209, 234, 243, 255, 214, 235, 242, 255, 239, 233, 231, 255, 239, 230, 229, 255, 240, 232, 229, 255, 244, 234, 225, 255, 242, 230, 224, 255, + 244, 233, 225, 255, 242, 229, 224, 255, 238, 224, 222, 255, 247, 236, 225, 255, 244, 232, 224, 255, 228, 215, 221, 255, 225, 214, 221, 255, 226, 215, 221, + 255, 242, 226, 225, 255, 244, 228, 226, 255, 244, 228, 225, 255, 248, 235, 229, 255, 250, 238, 231, 255, 249, 236, 230, 255, 251, 239, 231, 255, 251, 239, + 231, 255, 246, 228, 223, 255, 248, 232, 227, 255, 249, 237, 233, 255, 241, 234, 237, 255, 243, 229, 239, 255, 238, 223, 236, 255, 225, 220, 233, 255, 212, + 216, 230, 255, 194, 211, 225, 255, 181, 208, 222, 255, 179, 206, 221, 255, 178, 205, 219, 255, 176, 202, 217, 255, 175, 197, 213, 255, 173, 202, 218, 255, + 214, 240, 247, 255, 218, 242, 248, 255, 222, 244, 249, 255, 225, 245, 250, 255, 229, 246, 251, 255, 231, 241, 247, 255, 233, 237, 243, 255, 238, 250, 252, + 255, 240, 250, 253, 255, 242, 248, 251, 255, 242, 243, 247, 255, 245, 252, 253, 255, 247, 253, 254, 255, 248, 253, 254, 255, 249, 253, 254, 255, 250, 253, + 254, 255, 250, 251, 252, 255, 250, 252, 253, 255, 251, 254, 254, 255, 252, 254, 254, 255, 252, 254, 255, 255, 252, 254, 255, 255, 253, 254, 254, 255, 253, + 254, 254, 255, 253, 254, 254, 255, 253, 254, 254, 255, 252, 254, 254, 255, 253, 254, 255, 255, 253, 254, 255, 255, 251, 253, 253, 255, 251, 252, 253, 255, + 250, 252, 253, 255, 252, 254, 254, 255, 252, 254, 254, 255, 251, 254, 254, 255, 252, 254, 255, 255, 251, 254, 255, 255, 251, 253, 254, 255, 250, 253, 254, + 255, 250, 253, 254, 255, 249, 253, 254, 255, 248, 253, 254, 255, 247, 252, 254, 255, 246, 252, 254, 255, 245, 252, 254, 255, 244, 251, 254, 255, 242, 251, + 254, 255, 241, 251, 254, 255, 240, 250, 254, 255, 238, 249, 254, 255, 236, 249, 254, 255, 234, 249, 254, 255, 231, 248, 253, 255, 230, 248, 253, 255, 227, + 247, 253, 255, 225, 246, 252, 255, 222, 246, 252, 255, 220, 245, 252, 255, 217, 244, 252, 255, 210, 241, 250, 255, 212, 242, 251, 255, 212, 242, 251, 255, + 210, 241, 250, 255, 208, 240, 250, 255, 206, 240, 249, 255, 205, 239, 249, 255, 204, 238, 249, 255, 203, 238, 248, 255, 202, 237, 248, 255, 200, 237, 247, + 255, 201, 237, 246, 255, 202, 236, 246, 255, 203, 236, 246, 255, 204, 236, 245, 255, 205, 236, 245, 255, 206, 235, 245, 255, 207, 235, 244, 255, 208, 235, + 244, 255, 209, 235, 244, 255, 209, 234, 243, 255, 212, 226, 235, 255, 219, 219, 228, 255, 218, 221, 230, 255, 211, 232, 240, 255, 212, 234, 242, 255, 212, + 234, 242, 255, 212, 234, 242, 255, 213, 234, 242, 255, 233, 232, 233, 255, 241, 232, 231, 255, 243, 234, 229, 255, 242, 231, 227, 255, 244, 234, 227, 255, + 241, 231, 226, 255, 239, 226, 225, 255, 238, 224, 224, 255, 246, 236, 227, 255, 243, 232, 226, 255, 228, 216, 222, 255, 227, 217, 224, 255, 228, 218, 224, + 255, 242, 227, 226, 255, 244, 228, 227, 255, 245, 228, 226, 255, 248, 234, 229, 255, 249, 237, 231, 255, 250, 237, 231, 255, 251, 238, 231, 255, 252, 241, + 232, 255, 251, 238, 230, 255, 246, 226, 222, 255, 249, 237, 231, 255, 245, 236, 234, 255, 244, 232, 238, 255, 232, 221, 233, 255, 215, 216, 229, 255, 206, + 213, 226, 255, 190, 209, 223, 255, 184, 207, 221, 255, 182, 206, 220, 255, 180, 203, 218, 255, 178, 201, 216, 255, 177, 197, 213, 255, 175, 200, 215, 255, + 215, 244, 251, 255, 219, 245, 251, 255, 223, 247, 252, 255, 227, 248, 252, 255, 230, 248, 252, 255, 228, 233, 241, 255, 234, 242, 247, 255, 240, 251, 253, + 255, 242, 251, 253, 255, 238, 242, 247, 255, 242, 246, 250, 255, 246, 252, 254, 255, 248, 253, 254, 255, 248, 253, 254, 255, 247, 251, 252, 255, 248, 249, + 251, 255, 250, 252, 253, 255, 251, 253, 254, 255, 251, 254, 255, 255, 251, 254, 254, 255, 252, 254, 255, 255, 252, 254, 254, 255, 252, 254, 254, 255, 252, + 254, 254, 255, 252, 254, 254, 255, 252, 254, 254, 255, 252, 254, 254, 255, 252, 254, 254, 255, 252, 254, 254, 255, 250, 252, 253, 255, 249, 251, 252, 255, + 249, 252, 253, 255, 250, 253, 254, 255, 251, 254, 255, 255, 250, 253, 254, 255, 249, 253, 254, 255, 248, 253, 254, 255, 248, 253, 254, 255, 246, 252, 254, + 255, 246, 252, 254, 255, 244, 252, 253, 255, 243, 251, 253, 255, 241, 251, 254, 255, 239, 250, 253, 255, 237, 250, 253, 255, 236, 250, 253, 255, 234, 249, + 253, 255, 231, 248, 253, 255, 229, 248, 253, 255, 227, 247, 252, 255, 224, 247, 252, 255, 222, 246, 252, 255, 219, 245, 251, 255, 217, 244, 251, 255, 215, + 243, 251, 255, 212, 243, 250, 255, 210, 242, 250, 255, 209, 241, 250, 255, 207, 240, 249, 255, 203, 238, 247, 255, 204, 239, 247, 255, 204, 238, 247, 255, + 204, 238, 248, 255, 203, 238, 247, 255, 203, 237, 246, 255, 203, 236, 246, 255, 203, 236, 246, 255, 204, 236, 245, 255, 203, 235, 245, 255, 203, 235, 245, + 255, 204, 235, 244, 255, 205, 235, 244, 255, 207, 235, 244, 255, 208, 235, 244, 255, 209, 235, 244, 255, 210, 235, 244, 255, 211, 235, 244, 255, 212, 235, + 244, 255, 212, 235, 244, 255, 213, 235, 243, 255, 215, 228, 236, 255, 222, 221, 230, 255, 220, 224, 231, 255, 215, 233, 241, 255, 215, 235, 243, 255, 216, + 235, 243, 255, 216, 236, 243, 255, 219, 236, 242, 255, 237, 226, 228, 255, 240, 230, 229, 255, 244, 234, 230, 255, 244, 234, 229, 255, 249, 241, 231, 255, + 236, 225, 226, 255, 240, 228, 227, 255, 237, 224, 226, 255, 246, 236, 229, 255, 242, 232, 228, 255, 230, 219, 225, 255, 230, 220, 226, 255, 231, 222, 226, + 255, 241, 227, 227, 255, 242, 227, 227, 255, 245, 229, 228, 255, 247, 233, 229, 255, 250, 236, 231, 255, 250, 238, 231, 255, 251, 239, 231, 255, 252, 241, + 233, 255, 252, 241, 232, 255, 247, 230, 225, 255, 249, 236, 229, 255, 247, 237, 233, 255, 243, 235, 236, 255, 220, 225, 233, 255, 196, 215, 227, 255, 192, + 213, 225, 255, 189, 212, 224, 255, 188, 210, 224, 255, 184, 209, 222, 255, 182, 206, 220, 255, 181, 204, 218, 255, 179, 199, 215, 255, 177, 201, 217, 255, + 210, 239, 247, 255, 214, 241, 248, 255, 217, 242, 249, 255, 220, 243, 249, 255, 224, 241, 247, 255, 226, 228, 238, 255, 230, 246, 250, 255, 233, 248, 251, + 255, 236, 247, 250, 255, 236, 237, 243, 255, 239, 247, 250, 255, 241, 250, 251, 255, 244, 250, 251, 255, 244, 246, 249, 255, 244, 247, 250, 255, 246, 251, + 253, 255, 248, 253, 254, 255, 248, 253, 254, 255, 249, 253, 254, 255, 249, 253, 254, 255, 250, 253, 254, 255, 250, 253, 254, 255, 250, 253, 254, 255, 250, + 253, 254, 255, 251, 254, 254, 255, 251, 254, 255, 255, 250, 253, 254, 255, 251, 253, 254, 255, 250, 253, 254, 255, 248, 251, 252, 255, 248, 250, 251, 255, + 248, 251, 252, 255, 250, 253, 254, 255, 250, 253, 254, 255, 249, 253, 254, 255, 249, 253, 254, 255, 248, 253, 254, 255, 248, 252, 254, 255, 247, 252, 254, + 255, 246, 252, 254, 255, 245, 252, 254, 255, 244, 252, 254, 255, 243, 251, 254, 255, 242, 251, 254, 255, 241, 251, 254, 255, 240, 251, 254, 255, 239, 250, + 254, 255, 237, 250, 254, 255, 237, 249, 254, 255, 235, 249, 254, 255, 233, 249, 254, 255, 231, 248, 253, 255, 230, 248, 253, 255, 228, 247, 253, 255, 227, + 247, 253, 255, 225, 246, 253, 255, 223, 246, 253, 255, 222, 246, 253, 255, 220, 245, 253, 255, 213, 243, 252, 255, 216, 243, 252, 255, 216, 243, 252, 255, + 215, 243, 252, 255, 214, 243, 251, 255, 213, 242, 251, 255, 212, 241, 251, 255, 211, 241, 250, 255, 210, 241, 250, 255, 208, 241, 250, 255, 208, 240, 249, + 255, 208, 240, 249, 255, 209, 240, 249, 255, 210, 240, 249, 255, 211, 240, 248, 255, 212, 240, 248, 255, 213, 240, 248, 255, 214, 240, 248, 255, 215, 239, + 247, 255, 216, 239, 247, 255, 216, 239, 246, 255, 218, 231, 239, 255, 225, 224, 232, 255, 223, 226, 233, 255, 218, 236, 243, 255, 219, 239, 246, 255, 219, + 239, 245, 255, 219, 238, 245, 255, 232, 234, 237, 255, 242, 231, 229, 255, 243, 233, 230, 255, 245, 236, 231, 255, 248, 241, 232, 255, 247, 239, 232, 255, + 235, 223, 227, 255, 243, 232, 230, 255, 238, 226, 228, 255, 245, 235, 230, 255, 242, 232, 229, 255, 233, 223, 227, 255, 234, 225, 228, 255, 234, 225, 228, + 255, 243, 230, 229, 255, 241, 227, 228, 255, 244, 229, 229, 255, 246, 232, 229, 255, 249, 236, 231, 255, 250, 238, 231, 255, 251, 239, 232, 255, 252, 240, + 232, 255, 252, 242, 233, 255, 249, 234, 227, 255, 249, 233, 226, 255, 249, 238, 233, 255, 246, 236, 234, 255, 242, 234, 236, 255, 233, 226, 234, 255, 217, + 219, 230, 255, 204, 216, 228, 255, 201, 213, 227, 255, 201, 212, 226, 255, 197, 209, 223, 255, 185, 206, 219, 255, 181, 200, 216, 255, 179, 202, 217, 255, + 210, 243, 250, 255, 215, 244, 251, 255, 218, 245, 252, 255, 218, 239, 245, 255, 223, 234, 242, 255, 225, 233, 242, 255, 233, 249, 253, 255, 236, 250, 253, + 255, 235, 242, 248, 255, 234, 237, 243, 255, 237, 246, 248, 255, 239, 246, 248, 255, 241, 244, 247, 255, 241, 246, 248, 255, 242, 247, 249, 255, 244, 247, + 249, 255, 245, 249, 251, 255, 249, 253, 254, 255, 250, 253, 254, 255, 251, 254, 254, 255, 251, 254, 255, 255, 251, 254, 255, 255, 251, 254, 254, 255, 251, + 254, 254, 255, 252, 254, 255, 255, 252, 254, 255, 255, 251, 253, 254, 255, 251, 254, 254, 255, 251, 253, 254, 255, 248, 251, 253, 255, 247, 250, 251, 255, + 247, 250, 252, 255, 250, 253, 254, 255, 250, 254, 255, 255, 250, 253, 254, 255, 250, 253, 255, 255, 249, 253, 254, 255, 248, 253, 254, 255, 247, 252, 254, + 255, 246, 252, 254, 255, 246, 252, 254, 255, 244, 251, 254, 255, 243, 251, 254, 255, 241, 250, 253, 255, 240, 250, 253, 255, 238, 250, 253, 255, 236, 249, + 254, 255, 235, 249, 253, 255, 233, 248, 253, 255, 230, 248, 253, 255, 228, 247, 252, 255, 226, 246, 252, 255, 224, 246, 252, 255, 222, 245, 252, 255, 220, + 245, 252, 255, 218, 244, 252, 255, 216, 244, 251, 255, 214, 242, 250, 255, 213, 242, 250, 255, 208, 239, 249, 255, 209, 240, 249, 255, 209, 240, 249, 255, + 209, 239, 249, 255, 209, 239, 248, 255, 209, 239, 247, 255, 208, 238, 247, 255, 209, 238, 247, 255, 209, 238, 247, 255, 209, 237, 246, 255, 209, 237, 246, + 255, 211, 237, 245, 255, 212, 237, 245, 255, 214, 237, 245, 255, 215, 237, 245, 255, 215, 237, 245, 255, 217, 237, 244, 255, 218, 237, 245, 255, 218, 237, + 245, 255, 219, 237, 244, 255, 220, 237, 244, 255, 222, 232, 238, 255, 228, 227, 233, 255, 227, 228, 235, 255, 222, 235, 241, 255, 222, 238, 244, 255, 222, + 238, 244, 255, 223, 238, 244, 255, 243, 236, 234, 255, 242, 232, 231, 255, 245, 236, 233, 255, 249, 242, 234, 255, 250, 243, 235, 255, 242, 233, 232, 255, + 239, 228, 231, 255, 242, 232, 231, 255, 238, 228, 230, 255, 244, 234, 231, 255, 242, 232, 231, 255, 235, 226, 230, 255, 237, 229, 231, 255, 236, 228, 230, + 255, 243, 231, 231, 255, 242, 229, 229, 255, 243, 229, 229, 255, 247, 233, 230, 255, 249, 236, 231, 255, 250, 239, 233, 255, 251, 240, 233, 255, 252, 241, + 233, 255, 253, 243, 234, 255, 250, 236, 229, 255, 249, 233, 226, 255, 250, 238, 232, 255, 247, 237, 234, 255, 244, 236, 235, 255, 245, 234, 235, 255, 247, + 226, 230, 255, 241, 221, 228, 255, 237, 222, 232, 255, 217, 216, 229, 255, 191, 208, 221, 255, 185, 205, 219, 255, 183, 201, 216, 255, 181, 201, 216, 255, + 206, 240, 248, 255, 211, 242, 249, 255, 215, 243, 250, 255, 217, 238, 245, 255, 218, 221, 233, 255, 223, 240, 247, 255, 224, 242, 248, 255, 226, 238, 245, + 255, 230, 232, 240, 255, 237, 242, 245, 255, 244, 248, 249, 255, 237, 240, 245, 255, 238, 244, 247, 255, 239, 245, 248, 255, 241, 245, 248, 255, 242, 245, + 248, 255, 243, 245, 248, 255, 244, 247, 250, 255, 246, 252, 254, 255, 247, 253, 254, 255, 248, 252, 254, 255, 248, 253, 254, 255, 248, 253, 254, 255, 248, + 253, 254, 255, 248, 253, 254, 255, 248, 253, 254, 255, 248, 253, 254, 255, 248, 253, 254, 255, 248, 252, 254, 255, 246, 250, 252, 255, 246, 249, 251, 255, + 245, 249, 251, 255, 246, 252, 254, 255, 246, 252, 254, 255, 246, 252, 254, 255, 245, 252, 254, 255, 244, 252, 253, 255, 243, 252, 254, 255, 242, 251, 253, + 255, 241, 251, 253, 255, 239, 251, 253, 255, 238, 250, 253, 255, 236, 250, 253, 255, 235, 249, 253, 255, 233, 248, 253, 255, 231, 248, 253, 255, 230, 247, + 252, 255, 228, 247, 252, 255, 226, 247, 252, 255, 224, 247, 252, 255, 222, 246, 251, 255, 221, 245, 252, 255, 220, 245, 251, 255, 218, 244, 251, 255, 217, + 243, 251, 255, 216, 243, 250, 255, 214, 243, 250, 255, 214, 242, 250, 255, 213, 242, 250, 255, 209, 240, 248, 255, 211, 240, 249, 255, 212, 240, 249, 255, + 212, 240, 248, 255, 212, 240, 248, 255, 213, 240, 248, 255, 213, 240, 248, 255, 213, 239, 248, 255, 213, 239, 247, 255, 213, 239, 247, 255, 213, 239, 247, + 255, 214, 239, 247, 255, 216, 239, 247, 255, 217, 239, 247, 255, 218, 240, 247, 255, 219, 240, 247, 255, 220, 240, 247, 255, 221, 240, 247, 255, 221, 240, + 247, 255, 223, 240, 247, 255, 223, 240, 246, 255, 225, 235, 241, 255, 231, 229, 235, 255, 230, 230, 236, 255, 225, 238, 244, 255, 225, 241, 246, 255, 225, + 241, 246, 255, 232, 240, 244, 255, 244, 235, 233, 255, 241, 231, 233, 255, 242, 233, 233, 255, 248, 240, 235, 255, 249, 243, 236, 255, 240, 230, 232, 255, + 240, 231, 233, 255, 241, 232, 233, 255, 239, 230, 232, 255, 245, 235, 233, 255, 242, 233, 233, 255, 239, 231, 233, 255, 240, 232, 233, 255, 238, 230, 232, + 255, 244, 233, 232, 255, 245, 232, 232, 255, 242, 229, 230, 255, 246, 233, 231, 255, 248, 236, 232, 255, 251, 240, 234, 255, 252, 241, 234, 255, 252, 241, + 233, 255, 253, 242, 233, 255, 251, 240, 231, 255, 248, 231, 225, 255, 251, 239, 231, 255, 248, 238, 234, 255, 246, 236, 234, 255, 244, 236, 235, 255, 245, + 235, 232, 255, 215, 220, 228, 255, 199, 215, 227, 255, 193, 213, 226, 255, 189, 210, 223, 255, 187, 208, 221, 255, 185, 204, 218, 255, 183, 204, 218, 255, + 203, 229, 238, 255, 208, 237, 245, 255, 212, 240, 247, 255, 214, 232, 241, 255, 215, 219, 232, 255, 220, 238, 244, 255, 222, 229, 238, 255, 224, 232, 240, + 255, 228, 230, 239, 255, 248, 250, 250, 255, 243, 245, 248, 255, 238, 242, 246, 255, 235, 244, 246, 255, 237, 243, 246, 255, 238, 243, 247, 255, 240, 242, + 247, 255, 241, 242, 247, 255, 243, 243, 248, 255, 244, 248, 251, 255, 247, 253, 254, 255, 248, 253, 254, 255, 248, 252, 254, 255, 248, 253, 254, 255, 249, + 253, 254, 255, 249, 252, 253, 255, 249, 253, 254, 255, 248, 252, 254, 255, 249, 253, 254, 255, 248, 253, 254, 255, 244, 249, 251, 255, 245, 248, 249, 255, + 244, 249, 250, 255, 247, 252, 254, 255, 248, 253, 254, 255, 248, 253, 254, 255, 247, 252, 254, 255, 246, 252, 254, 255, 246, 252, 254, 255, 245, 251, 253, + 255, 245, 251, 253, 255, 243, 251, 253, 255, 242, 251, 254, 255, 241, 251, 254, 255, 240, 250, 253, 255, 240, 250, 254, 255, 238, 249, 254, 255, 236, 249, + 254, 255, 235, 249, 254, 255, 234, 248, 254, 255, 232, 249, 253, 255, 231, 248, 253, 255, 229, 247, 253, 255, 228, 247, 253, 255, 226, 246, 253, 255, 224, + 246, 253, 255, 223, 245, 253, 255, 222, 245, 252, 255, 221, 244, 252, 255, 219, 244, 251, 255, 214, 242, 251, 255, 216, 242, 251, 255, 217, 243, 251, 255, + 217, 242, 251, 255, 216, 242, 250, 255, 216, 242, 250, 255, 216, 241, 250, 255, 216, 241, 249, 255, 215, 241, 249, 255, 215, 241, 248, 255, 216, 241, 248, + 255, 217, 241, 248, 255, 219, 241, 247, 255, 220, 241, 248, 255, 221, 241, 247, 255, 222, 241, 247, 255, 223, 241, 247, 255, 224, 241, 247, 255, 224, 241, + 247, 255, 225, 241, 247, 255, 226, 241, 247, 255, 228, 236, 242, 255, 233, 231, 237, 255, 233, 232, 238, 255, 228, 239, 244, 255, 228, 242, 246, 255, 228, + 242, 246, 255, 231, 242, 245, 255, 240, 234, 236, 255, 242, 233, 235, 255, 241, 232, 234, 255, 242, 234, 235, 255, 242, 234, 235, 255, 242, 234, 235, 255, + 241, 233, 235, 255, 241, 233, 235, 255, 241, 232, 234, 255, 246, 238, 236, 255, 242, 234, 235, 255, 244, 236, 235, 255, 241, 234, 235, 255, 240, 232, 234, + 255, 245, 235, 234, 255, 246, 235, 234, 255, 243, 231, 232, 255, 244, 232, 232, 255, 248, 235, 233, 255, 250, 239, 234, 255, 252, 242, 234, 255, 252, 242, + 234, 255, 252, 242, 233, 255, 252, 242, 233, 255, 249, 234, 228, 255, 251, 238, 230, 255, 249, 239, 234, 255, 247, 237, 234, 255, 245, 236, 234, 255, 246, + 237, 235, 255, 237, 232, 229, 255, 197, 215, 226, 255, 198, 215, 226, 255, 191, 211, 224, 255, 189, 208, 221, 255, 187, 204, 218, 255, 185, 203, 218, 255, + 200, 218, 229, 255, 203, 220, 231, 255, 207, 236, 244, 255, 210, 219, 232, 255, 214, 228, 239, 255, 216, 232, 240, 255, 219, 226, 236, 255, 222, 228, 237, + 255, 228, 232, 240, 255, 242, 245, 247, 255, 233, 235, 242, 255, 234, 242, 245, 255, 232, 241, 245, 255, 234, 240, 245, 255, 235, 239, 244, 255, 237, 238, + 245, 255, 238, 239, 245, 255, 240, 240, 246, 255, 241, 242, 247, 255, 244, 251, 253, 255, 246, 252, 254, 255, 246, 252, 254, 255, 246, 252, 254, 255, 247, + 252, 254, 255, 247, 252, 254, 255, 247, 252, 254, 255, 246, 252, 253, 255, 246, 252, 254, 255, 245, 252, 253, 255, 242, 248, 250, 255, 241, 246, 248, 255, + 240, 246, 249, 255, 243, 251, 253, 255, 244, 251, 253, 255, 243, 251, 253, 255, 242, 251, 253, 255, 240, 250, 252, 255, 238, 248, 250, 255, 240, 246, 247, + 255, 233, 242, 246, 255, 235, 248, 252, 255, 234, 248, 252, 255, 233, 248, 252, 255, 231, 247, 252, 255, 228, 246, 251, 255, 227, 246, 251, 255, 225, 246, + 251, 255, 222, 245, 251, 255, 221, 245, 250, 255, 219, 244, 250, 255, 217, 243, 250, 255, 215, 242, 250, 255, 214, 242, 249, 255, 212, 241, 249, 255, 211, + 240, 248, 255, 210, 240, 248, 255, 210, 239, 248, 255, 209, 239, 247, 255, 209, 239, 247, 255, 208, 237, 246, 255, 209, 238, 246, 255, 210, 238, 246, 255, + 211, 237, 246, 255, 212, 237, 245, 255, 213, 237, 245, 255, 214, 237, 245, 255, 215, 237, 245, 255, 217, 237, 245, 255, 218, 238, 245, 255, 219, 237, 244, + 255, 221, 238, 245, 255, 222, 238, 245, 255, 223, 239, 245, 255, 224, 239, 245, 255, 225, 239, 245, 255, 226, 239, 245, 255, 226, 239, 245, 255, 227, 240, + 245, 255, 228, 240, 246, 255, 229, 240, 245, 255, 231, 237, 241, 255, 235, 233, 238, 255, 235, 234, 239, 255, 231, 240, 244, 255, 231, 241, 246, 255, 231, + 242, 246, 255, 231, 242, 246, 255, 234, 241, 244, 255, 243, 236, 237, 255, 244, 235, 237, 255, 244, 236, 237, 255, 243, 235, 237, 255, 246, 238, 238, 255, + 246, 239, 238, 255, 244, 237, 237, 255, 243, 235, 236, 255, 247, 240, 238, 255, 246, 238, 238, 255, 247, 240, 238, 255, 243, 236, 237, 255, 241, 234, 236, + 255, 246, 238, 236, 255, 247, 237, 235, 255, 245, 235, 234, 255, 243, 232, 233, 255, 249, 237, 234, 255, 250, 239, 235, 255, 252, 242, 236, 255, 252, 243, + 235, 255, 252, 242, 233, 255, 252, 242, 234, 255, 250, 236, 230, 255, 251, 239, 231, 255, 250, 240, 234, 255, 248, 238, 235, 255, 246, 236, 234, 255, 245, + 236, 234, 255, 249, 239, 234, 255, 222, 226, 227, 255, 196, 213, 225, 255, 194, 211, 223, 255, 191, 209, 222, 255, 189, 205, 219, 255, 187, 203, 218, 255, + 198, 215, 227, 255, 200, 220, 232, 255, 204, 221, 232, 255, 207, 208, 226, 255, 210, 223, 236, 255, 215, 230, 239, 255, 216, 225, 235, 255, 218, 220, 233, + 255, 222, 234, 240, 255, 226, 230, 239, 255, 227, 236, 242, 255, 228, 237, 243, 255, 230, 236, 243, 255, 231, 236, 243, 255, 233, 235, 243, 255, 234, 235, + 243, 255, 236, 236, 244, 255, 237, 237, 244, 255, 238, 238, 245, 255, 240, 247, 250, 255, 242, 249, 252, 255, 242, 249, 252, 255, 243, 249, 252, 255, 243, + 250, 252, 255, 243, 250, 252, 255, 243, 250, 252, 255, 243, 250, 252, 255, 243, 250, 252, 255, 242, 249, 252, 255, 240, 246, 249, 255, 239, 245, 247, 255, + 238, 245, 248, 255, 241, 249, 251, 255, 241, 249, 252, 255, 241, 249, 251, 255, 243, 249, 249, 255, 245, 248, 247, 255, 246, 247, 246, 255, 243, 244, 244, + 255, 229, 235, 241, 255, 235, 247, 251, 255, 234, 246, 250, 255, 232, 246, 250, 255, 231, 246, 250, 255, 230, 245, 250, 255, 228, 244, 250, 255, 227, 244, + 250, 255, 226, 244, 250, 255, 224, 244, 250, 255, 223, 243, 249, 255, 222, 242, 249, 255, 220, 242, 249, 255, 220, 242, 249, 255, 219, 242, 249, 255, 218, + 241, 249, 255, 217, 241, 249, 255, 217, 241, 249, 255, 216, 241, 249, 255, 216, 240, 249, 255, 213, 240, 248, 255, 215, 240, 249, 255, 217, 241, 248, 255, + 217, 240, 248, 255, 217, 240, 248, 255, 218, 240, 248, 255, 218, 240, 248, 255, 219, 241, 248, 255, 220, 241, 247, 255, 221, 241, 248, 255, 223, 241, 248, + 255, 224, 241, 247, 255, 225, 241, 247, 255, 226, 242, 247, 255, 227, 241, 247, 255, 228, 242, 247, 255, 229, 242, 247, 255, 230, 243, 248, 255, 231, 243, + 247, 255, 231, 243, 247, 255, 232, 243, 248, 255, 233, 240, 244, 255, 237, 235, 240, 255, 237, 236, 241, 255, 233, 242, 246, 255, 233, 244, 248, 255, 234, + 244, 248, 255, 233, 244, 247, 255, 234, 244, 248, 255, 244, 239, 240, 255, 245, 237, 239, 255, 244, 237, 239, 255, 246, 238, 239, 255, 248, 241, 240, 255, + 248, 241, 240, 255, 246, 239, 239, 255, 244, 237, 238, 255, 248, 242, 239, 255, 248, 242, 240, 255, 248, 242, 239, 255, 244, 238, 238, 255, 242, 236, 237, + 255, 247, 239, 237, 255, 248, 239, 237, 255, 248, 239, 236, 255, 241, 232, 234, 255, 249, 239, 236, 255, 249, 238, 235, 255, 252, 243, 236, 255, 253, 244, + 236, 255, 252, 242, 234, 255, 253, 243, 235, 255, 250, 235, 229, 255, 251, 240, 232, 255, 250, 241, 234, 255, 249, 239, 235, 255, 247, 237, 235, 255, 246, + 236, 235, 255, 244, 237, 236, 255, 249, 239, 231, 255, 206, 220, 227, 255, 196, 214, 225, 255, 194, 211, 224, 255, 191, 207, 220, 255, 189, 205, 219, 255, + 194, 211, 225, 255, 197, 220, 233, 255, 201, 214, 229, 255, 204, 208, 225, 255, 207, 215, 230, 255, 212, 225, 236, 255, 213, 224, 236, 255, 216, 220, 232, + 255, 218, 228, 237, 255, 221, 229, 238, 255, 223, 234, 240, 255, 225, 234, 241, 255, 227, 234, 241, 255, 229, 234, 242, 255, 231, 234, 242, 255, 233, 235, + 243, 255, 237, 237, 244, 255, 239, 239, 245, 255, 240, 241, 246, 255, 237, 243, 248, 255, 237, 243, 248, 255, 237, 244, 248, 255, 238, 244, 248, 255, 238, + 244, 248, 255, 238, 244, 248, 255, 238, 244, 248, 255, 238, 244, 247, 255, 238, 244, 247, 255, 237, 243, 247, 255, 237, 243, 247, 255, 236, 243, 246, 255, + 236, 242, 246, 255, 235, 242, 246, 255, 242, 246, 247, 255, 245, 247, 246, 255, 244, 245, 245, 255, 240, 242, 243, 255, 236, 239, 241, 255, 232, 236, 239, + 255, 227, 231, 236, 255, 224, 234, 240, 255, 222, 233, 238, 255, 220, 231, 238, 255, 218, 230, 236, 255, 216, 228, 235, 255, 215, 227, 233, 255, 213, 225, + 233, 255, 212, 224, 231, 255, 210, 223, 230, 255, 209, 221, 229, 255, 209, 220, 228, 255, 209, 218, 227, 255, 209, 217, 226, 255, 209, 217, 225, 255, 210, + 216, 225, 255, 210, 216, 225, 255, 212, 216, 225, 255, 213, 216, 225, 255, 215, 216, 225, 255, 215, 218, 227, 255, 217, 217, 226, 255, 220, 218, 226, 255, + 222, 219, 227, 255, 223, 220, 228, 255, 225, 222, 229, 255, 227, 222, 230, 255, 228, 225, 232, 255, 230, 230, 236, 255, 236, 235, 239, 255, 240, 237, 239, + 255, 240, 236, 239, 255, 238, 235, 238, 255, 236, 233, 237, 255, 236, 233, 238, 255, 236, 233, 238, 255, 236, 234, 239, 255, 237, 235, 239, 255, 237, 236, + 240, 255, 238, 237, 241, 255, 238, 237, 241, 255, 239, 237, 241, 255, 240, 238, 241, 255, 240, 238, 242, 255, 239, 239, 243, 255, 239, 240, 243, 255, 239, + 240, 244, 255, 239, 240, 244, 255, 240, 241, 244, 255, 245, 241, 242, 255, 247, 241, 241, 255, 246, 240, 240, 255, 248, 243, 241, 255, 248, 243, 241, 255, + 249, 244, 242, 255, 247, 241, 241, 255, 246, 239, 240, 255, 248, 242, 240, 255, 249, 244, 241, 255, 249, 243, 241, 255, 246, 240, 241, 255, 243, 237, 239, + 255, 248, 241, 239, 255, 249, 240, 239, 255, 249, 241, 238, 255, 241, 233, 236, 255, 250, 240, 237, 255, 249, 237, 236, 255, 252, 244, 238, 255, 252, 244, + 237, 255, 253, 244, 236, 255, 253, 243, 235, 255, 249, 235, 229, 255, 251, 240, 233, 255, 251, 241, 235, 255, 249, 240, 235, 255, 248, 238, 235, 255, 246, + 237, 235, 255, 244, 236, 235, 255, 247, 238, 235, 255, 234, 229, 226, 255, 201, 208, 222, 255, 199, 205, 220, 255, 197, 203, 218, 255, 193, 201, 216, 255, + 192, 209, 224, 255, 195, 211, 226, 255, 198, 201, 220, 255, 202, 212, 227, 255, 206, 218, 230, 255, 211, 221, 232, 255, 210, 214, 229, 255, 214, 219, 231, + 255, 218, 225, 236, 255, 224, 236, 241, 255, 231, 241, 245, 255, 236, 243, 247, 255, 242, 245, 249, 255, 246, 249, 250, 255, 249, 251, 252, 255, 251, 252, + 253, 255, 252, 253, 253, 255, 253, 253, 253, 255, 250, 252, 252, 255, 239, 244, 248, 255, 234, 241, 246, 255, 235, 242, 246, 255, 235, 242, 246, 255, 235, + 242, 246, 255, 236, 242, 246, 255, 236, 242, 246, 255, 236, 242, 246, 255, 236, 242, 246, 255, 236, 241, 245, 255, 235, 241, 245, 255, 235, 241, 245, 255, + 234, 240, 244, 255, 234, 240, 244, 255, 240, 243, 244, 255, 236, 239, 242, 255, 232, 236, 240, 255, 230, 235, 239, 255, 229, 233, 237, 255, 228, 232, 237, + 255, 225, 229, 235, 255, 222, 231, 238, 255, 222, 230, 236, 255, 220, 228, 235, 255, 219, 227, 233, 255, 217, 225, 232, 255, 216, 224, 231, 255, 215, 222, + 229, 255, 213, 221, 228, 255, 212, 219, 227, 255, 211, 218, 226, 255, 210, 217, 225, 255, 210, 216, 224, 255, 210, 214, 224, 255, 211, 214, 223, 255, 212, + 214, 223, 255, 212, 214, 223, 255, 214, 214, 223, 255, 216, 214, 223, 255, 217, 214, 223, 255, 219, 214, 223, 255, 221, 215, 224, 255, 223, 217, 225, 255, + 225, 218, 226, 255, 226, 219, 227, 255, 228, 221, 228, 255, 228, 224, 231, 255, 224, 233, 239, 255, 233, 236, 240, 255, 239, 238, 241, 255, 244, 239, 241, + 255, 244, 239, 241, 255, 245, 240, 243, 255, 243, 238, 242, 255, 238, 235, 239, 255, 238, 234, 238, 255, 239, 235, 239, 255, 239, 236, 240, 255, 240, 237, + 241, 255, 240, 237, 241, 255, 240, 238, 242, 255, 241, 239, 242, 255, 241, 239, 243, 255, 241, 240, 243, 255, 241, 241, 244, 255, 241, 241, 244, 255, 242, + 241, 245, 255, 242, 242, 245, 255, 242, 242, 245, 255, 241, 242, 245, 255, 246, 243, 244, 255, 247, 241, 242, 255, 251, 246, 243, 255, 248, 243, 242, 255, + 250, 245, 243, 255, 248, 242, 243, 255, 246, 241, 241, 255, 248, 243, 242, 255, 249, 244, 243, 255, 250, 245, 242, 255, 247, 242, 242, 255, 244, 240, 241, + 255, 248, 242, 240, 255, 249, 241, 241, 255, 250, 243, 240, 255, 242, 235, 237, 255, 250, 241, 239, 255, 249, 239, 237, 255, 252, 243, 238, 255, 253, 245, + 238, 255, 253, 245, 238, 255, 253, 244, 236, 255, 249, 235, 229, 255, 251, 240, 233, 255, 251, 241, 235, 255, 250, 241, 236, 255, 249, 239, 236, 255, 247, + 237, 235, 255, 244, 236, 235, 255, 244, 236, 235, 255, 250, 239, 231, 255, 213, 214, 223, 255, 201, 206, 220, 255, 200, 204, 219, 255, 197, 201, 217, 255, + 189, 209, 224, 255, 193, 206, 223, 255, 197, 199, 219, 255, 203, 212, 225, 255, 212, 216, 227, 255, 220, 222, 230, 255, 211, 214, 228, 255, 226, 229, 238, + 255, 246, 249, 249, 255, 250, 252, 252, 255, 250, 252, 253, 255, 249, 251, 252, 255, 247, 251, 252, 255, 250, 253, 254, 255, 246, 251, 252, 255, 241, 248, + 250, 255, 236, 243, 247, 255, 233, 241, 245, 255, 231, 239, 245, 255, 231, 239, 244, 255, 231, 239, 245, 255, 232, 239, 245, 255, 232, 240, 245, 255, 233, + 240, 245, 255, 233, 240, 245, 255, 233, 240, 245, 255, 233, 239, 244, 255, 233, 239, 244, 255, 232, 239, 243, 255, 232, 238, 243, 255, 231, 238, 243, 255, + 230, 238, 242, 255, 230, 237, 242, 255, 231, 236, 240, 255, 230, 234, 239, 255, 227, 232, 237, 255, 226, 231, 236, 255, 225, 230, 235, 255, 225, 229, 234, + 255, 224, 227, 233, 255, 218, 226, 235, 255, 217, 228, 234, 255, 216, 226, 233, 255, 214, 225, 231, 255, 214, 223, 231, 255, 213, 222, 230, 255, 212, 221, + 228, 255, 211, 220, 227, 255, 211, 218, 226, 255, 210, 217, 225, 255, 210, 216, 225, 255, 211, 215, 224, 255, 211, 215, 224, 255, 212, 215, 223, 255, 213, + 215, 223, 255, 214, 215, 223, 255, 216, 215, 223, 255, 217, 216, 223, 255, 219, 216, 224, 255, 221, 216, 224, 255, 223, 217, 225, 255, 225, 219, 226, 255, + 227, 220, 227, 255, 229, 221, 228, 255, 230, 224, 230, 255, 226, 232, 238, 255, 233, 230, 235, 255, 240, 232, 234, 255, 245, 234, 234, 255, 249, 238, 234, + 255, 248, 239, 236, 255, 246, 237, 238, 255, 244, 237, 240, 255, 240, 237, 240, 255, 241, 237, 240, 255, 241, 237, 241, 255, 242, 238, 241, 255, 242, 238, + 242, 255, 242, 239, 243, 255, 243, 240, 243, 255, 243, 241, 244, 255, 243, 241, 244, 255, 243, 242, 245, 255, 243, 242, 245, 255, 244, 243, 245, 255, 244, + 243, 246, 255, 244, 243, 246, 255, 244, 243, 246, 255, 243, 244, 246, 255, 244, 244, 246, 255, 249, 244, 244, 255, 251, 247, 245, 255, 249, 243, 243, 255, + 251, 247, 245, 255, 248, 243, 244, 255, 247, 242, 243, 255, 249, 245, 244, 255, 249, 245, 243, 255, 251, 247, 244, 255, 248, 244, 243, 255, 247, 242, 242, + 255, 248, 242, 242, 255, 249, 242, 241, 255, 251, 245, 242, 255, 243, 237, 239, 255, 250, 241, 239, 255, 250, 241, 239, 255, 250, 242, 239, 255, 253, 245, + 239, 255, 253, 246, 239, 255, 253, 244, 237, 255, 250, 237, 231, 255, 251, 239, 232, 255, 250, 240, 234, 255, 250, 241, 237, 255, 249, 240, 236, 255, 247, + 238, 237, 255, 244, 236, 236, 255, 242, 235, 235, 255, 247, 237, 233, 255, 233, 228, 228, 255, 205, 208, 222, 255, 203, 206, 220, 255, 199, 203, 219, 255, + 187, 206, 222, 255, 190, 197, 218, 255, 195, 202, 220, 255, 198, 207, 224, 255, 203, 207, 224, 255, 208, 211, 226, 255, 205, 209, 227, 255, 213, 225, 235, + 255, 218, 227, 237, 255, 220, 229, 238, 255, 219, 230, 239, 255, 220, 230, 239, 255, 221, 231, 241, 255, 228, 239, 245, 255, 227, 237, 243, 255, 226, 234, + 242, 255, 228, 234, 242, 255, 229, 235, 242, 255, 230, 236, 242, 255, 231, 236, 243, 255, 232, 237, 243, 255, 232, 237, 243, 255, 233, 238, 243, 255, 234, + 238, 243, 255, 234, 238, 243, 255, 234, 238, 243, 255, 234, 237, 242, 255, 235, 237, 242, 255, 236, 237, 242, 255, 236, 237, 241, 255, 235, 237, 241, 255, + 234, 236, 240, 255, 233, 235, 240, 255, 230, 234, 238, 255, 226, 231, 236, 255, 224, 228, 235, 255, 222, 228, 234, 255, 223, 227, 233, 255, 222, 226, 232, + 255, 221, 224, 231, 255, 217, 221, 231, 255, 222, 225, 232, 255, 223, 224, 230, 255, 224, 223, 229, 255, 224, 222, 228, 255, 223, 221, 227, 255, 223, 220, + 226, 255, 222, 219, 225, 255, 222, 218, 224, 255, 222, 217, 223, 255, 222, 216, 222, 255, 222, 216, 222, 255, 223, 216, 222, 255, 223, 215, 221, 255, 224, + 216, 222, 255, 225, 216, 222, 255, 226, 216, 222, 255, 228, 216, 222, 255, 229, 217, 223, 255, 229, 217, 223, 255, 231, 218, 224, 255, 233, 220, 225, 255, + 235, 222, 227, 255, 236, 223, 228, 255, 232, 229, 233, 255, 231, 228, 233, 255, 240, 227, 231, 255, 245, 231, 232, 255, 249, 237, 233, 255, 253, 247, 239, + 255, 252, 246, 242, 255, 250, 239, 236, 255, 247, 236, 237, 255, 244, 235, 238, 255, 242, 237, 240, 255, 245, 239, 241, 255, 245, 240, 242, 255, 246, 240, + 243, 255, 246, 241, 243, 255, 246, 242, 244, 255, 246, 242, 244, 255, 246, 243, 245, 255, 247, 244, 246, 255, 247, 244, 246, 255, 247, 244, 246, 255, 247, + 245, 247, 255, 247, 245, 247, 255, 247, 245, 247, 255, 246, 245, 247, 255, 247, 246, 247, 255, 252, 249, 247, 255, 250, 246, 246, 255, 250, 245, 245, 255, + 251, 248, 246, 255, 249, 245, 245, 255, 249, 245, 245, 255, 248, 245, 245, 255, 249, 245, 245, 255, 251, 247, 245, 255, 250, 246, 245, 255, 248, 244, 244, + 255, 249, 244, 244, 255, 249, 243, 243, 255, 252, 247, 243, 255, 244, 238, 240, 255, 249, 242, 241, 255, 251, 244, 241, 255, 250, 241, 240, 255, 253, 246, + 240, 255, 253, 246, 240, 255, 252, 244, 238, 255, 250, 239, 233, 255, 251, 239, 233, 255, 250, 240, 235, 255, 250, 241, 237, 255, 249, 241, 238, 255, 246, + 238, 237, 255, 243, 236, 236, 255, 242, 235, 235, 255, 243, 235, 234, 255, 249, 239, 231, 255, 217, 213, 223, 255, 209, 207, 220, 255, 207, 203, 218, 255, + 185, 201, 220, 255, 189, 191, 213, 255, 193, 203, 221, 255, 194, 202, 221, 255, 195, 204, 224, 255, 198, 199, 221, 255, 201, 211, 228, 255, 205, 219, 233, + 255, 210, 220, 233, 255, 211, 222, 235, 255, 213, 224, 236, 255, 215, 226, 237, 255, 217, 227, 238, 255, 219, 228, 239, 255, 221, 230, 240, 255, 223, 231, + 240, 255, 225, 232, 241, 255, 226, 232, 241, 255, 227, 233, 241, 255, 228, 234, 241, 255, 230, 234, 242, 255, 231, 234, 241, 255, 231, 235, 242, 255, 232, + 235, 242, 255, 233, 235, 241, 255, 233, 235, 241, 255, 233, 235, 240, 255, 233, 235, 240, 255, 233, 233, 239, 255, 231, 231, 237, 255, 230, 230, 237, 255, + 228, 229, 236, 255, 226, 228, 235, 255, 225, 227, 234, 255, 225, 229, 234, 255, 222, 226, 233, 255, 220, 224, 232, 255, 219, 224, 230, 255, 219, 224, 230, + 255, 218, 222, 230, 255, 216, 218, 228, 255, 211, 216, 229, 255, 208, 209, 224, 255, 214, 211, 224, 255, 226, 219, 225, 255, 227, 219, 225, 255, 227, 218, + 224, 255, 227, 218, 223, 255, 227, 217, 222, 255, 227, 216, 221, 255, 228, 215, 221, 255, 228, 215, 221, 255, 226, 217, 222, 255, 221, 219, 225, 255, 220, + 216, 223, 255, 218, 208, 219, 255, 218, 207, 220, 255, 220, 209, 220, 255, 222, 211, 222, 255, 223, 211, 223, 255, 225, 213, 224, 255, 227, 216, 225, 255, + 229, 217, 226, 255, 232, 220, 228, 255, 233, 227, 233, 255, 238, 226, 231, 255, 244, 231, 233, 255, 251, 247, 246, 255, 252, 245, 239, 255, 254, 254, 254, + 255, 254, 253, 251, 255, 251, 245, 243, 255, 249, 243, 241, 255, 246, 237, 238, 255, 244, 237, 240, 255, 247, 240, 242, 255, 248, 241, 242, 255, 248, 242, + 243, 255, 248, 243, 244, 255, 248, 243, 245, 255, 249, 244, 245, 255, 249, 244, 246, 255, 248, 245, 246, 255, 249, 246, 247, 255, 249, 246, 247, 255, 249, + 246, 247, 255, 249, 246, 247, 255, 249, 247, 248, 255, 249, 247, 248, 255, 250, 248, 248, 255, 252, 249, 248, 255, 250, 246, 246, 255, 250, 246, 246, 255, + 251, 248, 247, 255, 250, 247, 247, 255, 251, 248, 247, 255, 249, 245, 246, 255, 250, 246, 246, 255, 252, 248, 246, 255, 250, 246, 246, 255, 248, 245, 245, + 255, 250, 245, 245, 255, 249, 244, 244, 255, 253, 248, 245, 255, 246, 241, 242, 255, 248, 241, 242, 255, 252, 245, 242, 255, 249, 242, 240, 255, 253, 247, + 242, 255, 253, 247, 241, 255, 253, 245, 239, 255, 251, 241, 235, 255, 251, 240, 235, 255, 250, 240, 236, 255, 250, 241, 238, 255, 249, 241, 238, 255, 246, + 239, 238, 255, 243, 237, 237, 255, 241, 236, 237, 255, 242, 235, 234, 255, 247, 237, 232, 255, 236, 228, 227, 255, 213, 208, 220, 255, 209, 204, 218, 255, + 191, 199, 217, 255, 191, 196, 215, 255, 191, 198, 218, 255, 195, 205, 223, 255, 195, 204, 223, 255, 195, 197, 220, 255, 203, 213, 228, 255, 206, 215, 231, + 255, 210, 216, 230, 255, 211, 219, 233, 255, 213, 221, 234, 255, 215, 223, 235, 255, 218, 224, 236, 255, 220, 225, 237, 255, 221, 227, 237, 255, 223, 228, + 238, 255, 225, 229, 238, 255, 226, 229, 239, 255, 227, 230, 239, 255, 228, 231, 239, 255, 229, 232, 239, 255, 230, 232, 240, 255, 231, 232, 239, 255, 231, + 232, 240, 255, 232, 232, 239, 255, 232, 232, 238, 255, 232, 232, 239, 255, 233, 232, 238, 255, 233, 231, 235, 255, 233, 230, 235, 255, 233, 231, 234, 255, + 234, 231, 234, 255, 233, 231, 234, 255, 233, 232, 233, 255, 223, 227, 233, 255, 219, 223, 231, 255, 217, 222, 229, 255, 216, 221, 230, 255, 215, 220, 228, + 255, 214, 219, 227, 255, 214, 216, 225, 255, 208, 214, 227, 255, 203, 203, 222, 255, 202, 202, 221, 255, 209, 208, 222, 255, 225, 217, 223, 255, 226, 217, + 223, 255, 225, 216, 221, 255, 226, 215, 221, 255, 226, 215, 220, 255, 226, 214, 220, 255, 221, 215, 222, 255, 202, 220, 230, 255, 201, 216, 227, 255, 203, + 202, 219, 255, 204, 200, 218, 255, 206, 204, 220, 255, 209, 207, 222, 255, 211, 209, 223, 255, 213, 211, 224, 255, 216, 213, 226, 255, 219, 215, 227, 255, + 221, 218, 229, 255, 224, 220, 230, 255, 228, 223, 232, 255, 236, 226, 232, 255, 244, 231, 232, 255, 250, 241, 238, 255, 253, 247, 241, 255, 255, 255, 255, + 255, 255, 254, 252, 255, 252, 246, 242, 255, 251, 244, 240, 255, 247, 238, 240, 255, 246, 238, 241, 255, 247, 241, 243, 255, 248, 242, 243, 255, 249, 243, + 245, 255, 249, 244, 245, 255, 248, 244, 245, 255, 249, 245, 246, 255, 249, 245, 246, 255, 249, 246, 247, 255, 249, 246, 248, 255, 249, 247, 248, 255, 249, + 247, 248, 255, 249, 247, 248, 255, 249, 248, 249, 255, 249, 248, 249, 255, 251, 248, 248, 255, 251, 248, 248, 255, 250, 247, 247, 255, 251, 247, 248, 255, + 253, 250, 249, 255, 252, 249, 248, 255, 251, 249, 248, 255, 249, 246, 247, 255, 250, 247, 247, 255, 252, 249, 248, 255, 251, 248, 247, 255, 249, 246, 247, + 255, 251, 247, 246, 255, 249, 245, 245, 255, 253, 249, 246, 255, 248, 243, 243, 255, 248, 242, 242, 255, 252, 246, 244, 255, 251, 244, 242, 255, 253, 248, + 243, 255, 253, 247, 242, 255, 253, 246, 240, 255, 251, 242, 237, 255, 251, 242, 237, 255, 249, 239, 236, 255, 250, 241, 238, 255, 249, 241, 238, 255, 246, + 239, 239, 255, 244, 237, 238, 255, 241, 236, 237, 255, 242, 235, 235, 255, 245, 236, 233, 255, 250, 239, 231, 255, 220, 213, 222, 255, 211, 205, 218, 255, + 180, 181, 206, 255, 182, 193, 215, 255, 185, 203, 222, 255, 187, 205, 224, 255, 189, 196, 218, 255, 192, 199, 221, 255, 195, 211, 228, 255, 197, 214, 230, + 255, 202, 213, 229, 255, 203, 217, 232, 255, 205, 219, 233, 255, 207, 220, 234, 255, 209, 222, 235, 255, 211, 223, 236, 255, 213, 224, 236, 255, 215, 226, + 237, 255, 217, 226, 237, 255, 219, 227, 238, 255, 221, 228, 238, 255, 222, 228, 238, 255, 223, 229, 238, 255, 224, 229, 238, 255, 225, 229, 238, 255, 226, + 230, 238, 255, 227, 230, 237, 255, 227, 230, 237, 255, 227, 229, 237, 255, 235, 232, 235, 255, 244, 236, 234, 255, 246, 238, 234, 255, 247, 240, 234, 255, + 248, 241, 235, 255, 246, 240, 234, 255, 247, 241, 235, 255, 227, 229, 231, 255, 216, 221, 228, 255, 214, 219, 227, 255, 213, 218, 227, 255, 212, 217, 226, + 255, 212, 216, 225, 255, 213, 214, 223, 255, 208, 210, 224, 255, 201, 200, 220, 255, 199, 198, 219, 255, 201, 199, 218, 255, 220, 214, 222, 255, 222, 214, + 221, 255, 222, 213, 220, 255, 222, 213, 220, 255, 222, 213, 220, 255, 223, 212, 219, 255, 206, 209, 220, 255, 199, 206, 220, 255, 201, 201, 217, 255, 204, + 199, 216, 255, 205, 200, 219, 255, 207, 204, 220, 255, 209, 208, 222, 255, 191, 190, 202, 255, 215, 212, 225, 255, 217, 215, 226, 255, 205, 202, 213, 255, + 216, 213, 223, 255, 225, 222, 231, 255, 230, 225, 233, 255, 237, 227, 233, 255, 246, 232, 232, 255, 250, 238, 235, 255, 253, 247, 243, 255, 254, 254, 254, + 255, 254, 254, 253, 255, 252, 245, 240, 255, 250, 242, 241, 255, 247, 239, 241, 255, 247, 240, 242, 255, 248, 242, 243, 255, 228, 223, 225, 255, 249, 244, + 245, 255, 249, 244, 246, 255, 250, 246, 247, 255, 250, 246, 247, 255, 250, 247, 248, 255, 250, 247, 248, 255, 250, 247, 248, 255, 250, 248, 249, 255, 250, + 248, 249, 255, 250, 248, 249, 255, 250, 248, 249, 255, 251, 249, 249, 255, 251, 248, 248, 255, 251, 248, 249, 255, 251, 249, 248, 255, 253, 250, 249, 255, + 253, 251, 249, 255, 252, 250, 249, 255, 252, 249, 249, 255, 250, 248, 248, 255, 251, 248, 248, 255, 252, 250, 248, 255, 252, 249, 248, 255, 250, 247, 247, + 255, 252, 248, 247, 255, 251, 246, 246, 255, 253, 249, 247, 255, 250, 245, 245, 255, 249, 244, 244, 255, 252, 247, 244, 255, 252, 246, 243, 255, 253, 247, + 243, 255, 254, 249, 243, 255, 253, 247, 242, 255, 252, 244, 239, 255, 249, 240, 237, 255, 249, 238, 236, 255, 238, 228, 225, 255, 236, 227, 225, 255, 231, + 224, 223, 255, 240, 234, 234, 255, 243, 236, 237, 255, 242, 236, 236, 255, 244, 236, 234, 255, 249, 238, 231, 255, 237, 228, 226, 255, 212, 205, 219, 255, + 178, 180, 205, 255, 180, 194, 216, 255, 182, 197, 218, 255, 184, 197, 219, 255, 186, 188, 214, 255, 189, 201, 222, 255, 192, 205, 225, 255, 194, 208, 227, + 255, 210, 218, 229, 255, 200, 213, 229, 255, 200, 213, 230, 255, 203, 215, 231, 255, 205, 217, 232, 255, 206, 218, 233, 255, 208, 219, 233, 255, 210, 220, + 234, 255, 212, 221, 234, 255, 214, 222, 235, 255, 215, 223, 235, 255, 216, 223, 235, 255, 218, 224, 235, 255, 219, 224, 235, 255, 220, 225, 235, 255, 221, + 225, 235, 255, 221, 225, 234, 255, 222, 225, 234, 255, 222, 224, 233, 255, 231, 227, 232, 255, 239, 230, 230, 255, 241, 231, 230, 255, 241, 232, 230, 255, + 241, 232, 230, 255, 240, 232, 230, 255, 239, 232, 229, 255, 228, 226, 228, 255, 214, 218, 226, 255, 212, 216, 226, 255, 209, 214, 225, 255, 209, 213, 223, + 255, 209, 213, 222, 255, 210, 211, 222, 255, 209, 208, 221, 255, 199, 199, 218, 255, 197, 195, 216, 255, 197, 195, 215, 255, 212, 208, 219, 255, 214, 209, + 218, 255, 214, 209, 218, 255, 214, 208, 218, 255, 215, 208, 218, 255, 216, 208, 217, 255, 201, 198, 215, 255, 199, 195, 215, 255, 201, 195, 213, 255, 202, + 196, 215, 255, 205, 199, 218, 255, 208, 203, 220, 255, 210, 207, 222, 255, 123, 121, 130, 255, 179, 176, 186, 255, 216, 212, 224, 255, 98, 96, 101, 255, + 221, 217, 227, 255, 227, 222, 232, 255, 232, 224, 233, 255, 236, 226, 233, 255, 245, 231, 233, 255, 248, 236, 236, 255, 252, 247, 243, 255, 255, 255, 254, + 255, 254, 254, 252, 255, 252, 245, 240, 255, 249, 242, 242, 255, 247, 240, 242, 255, 247, 241, 243, 255, 240, 235, 237, 255, 142, 140, 140, 255, 249, 245, + 246, 255, 249, 246, 247, 255, 249, 246, 247, 255, 249, 247, 248, 255, 249, 247, 248, 255, 163, 161, 162, 255, 250, 248, 249, 255, 250, 248, 249, 255, 250, + 249, 250, 255, 250, 249, 250, 255, 250, 249, 250, 255, 251, 249, 250, 255, 251, 249, 249, 255, 251, 249, 249, 255, 252, 249, 249, 255, 253, 251, 250, 255, + 253, 251, 250, 255, 252, 250, 249, 255, 252, 250, 249, 255, 251, 248, 249, 255, 251, 248, 249, 255, 253, 250, 249, 255, 252, 250, 249, 255, 220, 218, 218, + 255, 194, 192, 192, 255, 252, 248, 248, 255, 253, 250, 247, 255, 251, 247, 246, 255, 249, 245, 245, 255, 252, 247, 245, 255, 253, 248, 245, 255, 253, 248, + 244, 255, 254, 249, 244, 255, 253, 248, 243, 255, 252, 244, 240, 255, 250, 242, 239, 255, 250, 241, 239, 255, 166, 160, 158, 255, 195, 188, 187, 255, 163, + 158, 157, 255, 217, 211, 211, 255, 244, 238, 237, 255, 243, 236, 236, 255, 244, 236, 235, 255, 247, 237, 233, 255, 251, 239, 229, 255, 218, 212, 222, 255, + 175, 183, 207, 255, 177, 196, 217, 255, 180, 198, 218, 255, 182, 193, 216, 255, 184, 188, 215, 255, 186, 204, 223, 255, 189, 206, 225, 255, 191, 208, 226, + 255, 202, 214, 228, 255, 198, 213, 229, 255, 197, 213, 229, 255, 199, 214, 231, 255, 202, 216, 231, 255, 204, 217, 232, 255, 206, 218, 233, 255, 208, 220, + 233, 255, 210, 221, 234, 255, 212, 221, 234, 255, 213, 222, 234, 255, 215, 223, 235, 255, 217, 223, 234, 255, 218, 224, 234, 255, 218, 224, 234, 255, 220, + 224, 234, 255, 221, 224, 234, 255, 221, 224, 233, 255, 220, 223, 233, 255, 228, 224, 230, 255, 235, 225, 227, 255, 237, 227, 228, 255, 237, 227, 227, 255, + 237, 228, 227, 255, 236, 227, 227, 255, 235, 227, 226, 255, 228, 224, 225, 255, 212, 216, 224, 255, 209, 213, 224, 255, 206, 211, 222, 255, 206, 210, 221, + 255, 205, 210, 221, 255, 207, 209, 219, 255, 209, 205, 218, 255, 200, 202, 219, 255, 194, 192, 214, 255, 194, 193, 213, 255, 212, 208, 218, 255, 216, 210, + 219, 255, 216, 209, 219, 255, 216, 210, 218, 255, 217, 209, 218, 255, 218, 210, 218, 255, 202, 198, 215, 255, 198, 195, 215, 255, 201, 195, 214, 255, 203, + 197, 216, 255, 206, 198, 217, 255, 208, 202, 220, 255, 211, 205, 222, 255, 201, 197, 211, 255, 102, 100, 106, 255, 127, 124, 131, 255, 186, 182, 192, 255, + 225, 219, 230, 255, 156, 152, 159, 255, 116, 112, 117, 255, 173, 166, 171, 255, 243, 230, 234, 255, 167, 159, 159, 255, 250, 241, 237, 255, 195, 192, 188, + 255, 231, 228, 225, 255, 169, 164, 163, 255, 145, 141, 142, 255, 177, 172, 174, 255, 248, 243, 245, 255, 231, 227, 228, 255, 186, 183, 184, 255, 224, 220, + 221, 255, 138, 136, 137, 255, 122, 121, 122, 255, 196, 194, 195, 255, 220, 218, 219, 255, 62, 62, 62, 255, 150, 149, 150, 255, 250, 249, 250, 255, 169, + 168, 169, 255, 125, 124, 125, 255, 189, 189, 189, 255, 251, 250, 250, 255, 151, 150, 150, 255, 110, 109, 109, 255, 228, 227, 227, 255, 134, 133, 133, 255, + 128, 127, 127, 255, 179, 178, 178, 255, 252, 250, 250, 255, 203, 201, 201, 255, 127, 126, 126, 255, 156, 155, 154, 255, 253, 251, 250, 255, 111, 110, 110, + 255, 98, 97, 97, 255, 226, 223, 223, 255, 254, 251, 249, 255, 244, 240, 239, 255, 144, 142, 142, 255, 111, 109, 108, 255, 245, 241, 238, 255, 138, 135, + 133, 255, 137, 134, 132, 255, 165, 162, 158, 255, 251, 245, 241, 255, 177, 171, 170, 255, 126, 122, 121, 255, 91, 88, 87, 255, 225, 217, 216, 255, 167, + 161, 160, 255, 246, 239, 238, 255, 200, 194, 194, 255, 123, 119, 119, 255, 145, 140, 140, 255, 246, 236, 233, 255, 250, 239, 230, 255, 237, 228, 225, 255, + 173, 184, 209, 255, 175, 192, 214, 255, 178, 194, 216, 255, 181, 186, 211, 255, 182, 193, 217, 255, 184, 200, 221, 255, 186, 201, 222, 255, 188, 204, 224, + 255, 190, 205, 224, 255, 193, 207, 226, 255, 195, 208, 227, 255, 197, 210, 228, 255, 199, 211, 229, 255, 201, 213, 229, 255, 203, 214, 230, 255, 204, 215, + 230, 255, 206, 216, 231, 255, 208, 217, 231, 255, 210, 217, 231, 255, 211, 218, 231, 255, 212, 218, 231, 255, 213, 219, 231, 255, 214, 219, 231, 255, 215, + 219, 231, 255, 216, 220, 230, 255, 217, 220, 230, 255, 216, 218, 230, 255, 224, 219, 227, 255, 230, 220, 224, 255, 232, 221, 224, 255, 232, 221, 224, 255, + 232, 222, 224, 255, 231, 222, 223, 255, 226, 219, 222, 255, 226, 220, 222, 255, 211, 213, 222, 255, 206, 211, 221, 255, 204, 208, 220, 255, 202, 208, 219, + 255, 203, 207, 219, 255, 205, 206, 217, 255, 209, 203, 216, 255, 201, 203, 218, 255, 192, 190, 212, 255, 192, 190, 211, 255, 208, 204, 216, 255, 211, 206, + 216, 255, 211, 206, 216, 255, 212, 206, 216, 255, 213, 206, 216, 255, 214, 207, 217, 255, 201, 197, 215, 255, 199, 194, 214, 255, 201, 195, 214, 255, 203, + 197, 216, 255, 206, 199, 217, 255, 209, 201, 220, 255, 212, 205, 222, 255, 214, 209, 224, 255, 100, 98, 104, 255, 124, 121, 128, 255, 223, 218, 229, 255, + 188, 183, 192, 255, 133, 129, 134, 255, 234, 226, 234, 255, 98, 95, 98, 255, 243, 232, 234, 255, 113, 108, 108, 255, 249, 239, 237, 255, 128, 126, 121, + 255, 238, 232, 228, 255, 97, 94, 94, 255, 215, 209, 210, 255, 248, 243, 245, 255, 249, 244, 246, 255, 194, 191, 193, 255, 167, 165, 166, 255, 181, 178, + 180, 255, 157, 156, 156, 255, 247, 245, 246, 255, 105, 104, 104, 255, 251, 249, 250, 255, 119, 118, 119, 255, 251, 250, 251, 255, 207, 206, 207, 255, 151, + 150, 151, 255, 251, 250, 251, 255, 110, 110, 110, 255, 242, 242, 243, 255, 77, 77, 77, 255, 248, 247, 246, 255, 214, 212, 212, 255, 127, 127, 126, 255, + 254, 252, 251, 255, 103, 103, 102, 255, 248, 247, 247, 255, 111, 111, 111, 255, 252, 250, 250, 255, 126, 126, 125, 255, 236, 235, 234, 255, 151, 149, 150, + 255, 221, 220, 219, 255, 252, 250, 249, 255, 254, 251, 249, 255, 213, 210, 210, 255, 105, 103, 103, 255, 251, 247, 246, 255, 142, 140, 139, 255, 205, 201, + 199, 255, 219, 216, 213, 255, 104, 102, 100, 255, 228, 221, 219, 255, 116, 113, 112, 255, 249, 241, 239, 255, 70, 68, 68, 255, 248, 240, 238, 255, 112, + 108, 108, 255, 244, 236, 235, 255, 104, 100, 100, 255, 244, 237, 236, 255, 132, 128, 128, 255, 214, 205, 204, 255, 249, 238, 231, 255, 252, 240, 227, 255, + 174, 185, 208, 255, 173, 190, 213, 255, 178, 192, 213, 255, 178, 180, 207, 255, 180, 195, 217, 255, 182, 197, 219, 255, 184, 200, 221, 255, 186, 201, 222, + 255, 188, 203, 223, 255, 190, 204, 224, 255, 192, 206, 225, 255, 194, 207, 226, 255, 196, 209, 227, 255, 199, 210, 227, 255, 201, 212, 228, 255, 203, 213, + 228, 255, 204, 214, 229, 255, 206, 214, 229, 255, 208, 215, 229, 255, 210, 216, 230, 255, 211, 216, 230, 255, 212, 217, 230, 255, 214, 217, 229, 255, 215, + 217, 229, 255, 215, 217, 229, 255, 216, 217, 228, 255, 215, 216, 227, 255, 220, 215, 224, 255, 226, 215, 222, 255, 227, 216, 221, 255, 227, 216, 221, 255, + 226, 215, 221, 255, 225, 216, 220, 255, 215, 208, 217, 255, 220, 214, 219, 255, 209, 208, 219, 255, 204, 208, 219, 255, 202, 206, 218, 255, 200, 205, 217, + 255, 200, 205, 217, 255, 202, 204, 216, 255, 208, 202, 214, 255, 206, 199, 215, 255, 191, 188, 210, 255, 190, 188, 209, 255, 209, 204, 216, 255, 212, 206, + 217, 255, 213, 207, 216, 255, 213, 207, 216, 255, 215, 208, 217, 255, 216, 209, 217, 255, 201, 197, 215, 255, 198, 194, 214, 255, 201, 195, 213, 255, 203, + 197, 216, 255, 206, 199, 218, 255, 209, 202, 220, 255, 212, 206, 223, 255, 216, 209, 225, 255, 120, 117, 125, 255, 199, 195, 206, 255, 224, 220, 231, 255, + 140, 136, 143, 255, 192, 187, 194, 255, 234, 227, 235, 255, 106, 102, 105, 255, 222, 213, 215, 255, 137, 133, 131, 255, 251, 244, 240, 255, 116, 115, 110, + 255, 252, 248, 243, 255, 113, 111, 110, 255, 250, 245, 244, 255, 248, 244, 245, 255, 249, 245, 246, 255, 166, 163, 164, 255, 198, 196, 197, 255, 151, 149, + 150, 255, 211, 210, 210, 255, 251, 249, 250, 255, 115, 114, 115, 255, 251, 250, 250, 255, 117, 117, 117, 255, 252, 251, 251, 255, 155, 154, 155, 255, 120, + 119, 120, 255, 140, 139, 140, 255, 136, 135, 136, 255, 212, 212, 212, 255, 153, 152, 153, 255, 253, 252, 252, 255, 183, 183, 182, 255, 183, 182, 182, 255, + 253, 253, 252, 255, 116, 116, 116, 255, 217, 216, 216, 255, 86, 85, 85, 255, 140, 139, 139, 255, 119, 119, 119, 255, 241, 240, 239, 255, 121, 120, 120, + 255, 248, 246, 246, 255, 253, 251, 250, 255, 254, 251, 250, 255, 183, 181, 180, 255, 183, 181, 181, 255, 253, 250, 248, 255, 115, 114, 113, 255, 254, 250, + 247, 255, 226, 223, 219, 255, 137, 134, 132, 255, 179, 174, 173, 255, 187, 183, 180, 255, 251, 244, 242, 255, 107, 104, 103, 255, 249, 242, 240, 255, 113, + 110, 109, 255, 213, 206, 204, 255, 145, 140, 140, 255, 245, 238, 237, 255, 137, 133, 133, 255, 216, 208, 208, 255, 248, 237, 232, 255, 251, 239, 228, 255, + 175, 184, 206, 255, 172, 191, 213, 255, 177, 182, 206, 255, 176, 183, 209, 255, 178, 196, 217, 255, 179, 197, 219, 255, 181, 199, 220, 255, 183, 201, 221, + 255, 186, 202, 222, 255, 188, 203, 223, 255, 190, 205, 224, 255, 192, 206, 225, 255, 195, 208, 225, 255, 197, 209, 226, 255, 199, 210, 227, 255, 200, 211, + 228, 255, 203, 212, 228, 255, 205, 213, 228, 255, 207, 213, 228, 255, 208, 214, 228, 255, 210, 214, 228, 255, 211, 215, 228, 255, 212, 215, 228, 255, 213, + 215, 228, 255, 214, 215, 227, 255, 214, 215, 227, 255, 213, 214, 226, 255, 217, 212, 222, 255, 221, 210, 218, 255, 222, 210, 218, 255, 221, 210, 217, 255, + 220, 209, 217, 255, 219, 210, 217, 255, 211, 203, 215, 255, 217, 211, 218, 255, 203, 201, 214, 255, 202, 205, 217, 255, 200, 203, 215, 255, 198, 202, 215, + 255, 197, 202, 214, 255, 199, 201, 214, 255, 205, 201, 213, 255, 213, 199, 212, 255, 191, 190, 210, 255, 189, 186, 207, 255, 208, 203, 215, 255, 211, 206, + 215, 255, 212, 206, 216, 255, 214, 207, 217, 255, 215, 207, 217, 255, 216, 208, 217, 255, 201, 198, 215, 255, 198, 194, 214, 255, 201, 195, 213, 255, 204, + 198, 217, 255, 207, 201, 219, 255, 210, 203, 221, 255, 213, 206, 223, 255, 216, 210, 225, 255, 100, 97, 103, 255, 221, 216, 228, 255, 225, 221, 231, 255, + 147, 144, 150, 255, 174, 169, 175, 255, 212, 205, 212, 255, 116, 113, 116, 255, 207, 200, 202, 255, 131, 127, 125, 255, 240, 235, 229, 255, 88, 87, 86, + 255, 254, 252, 247, 255, 114, 112, 110, 255, 250, 246, 246, 255, 250, 245, 247, 255, 250, 246, 247, 255, 136, 134, 135, 255, 229, 227, 227, 255, 119, 118, + 119, 255, 242, 240, 241, 255, 234, 232, 233, 255, 129, 129, 129, 255, 247, 245, 246, 255, 102, 102, 102, 255, 251, 250, 251, 255, 164, 163, 164, 255, 195, + 195, 195, 255, 233, 232, 233, 255, 194, 193, 194, 255, 183, 182, 183, 255, 183, 183, 183, 255, 253, 252, 253, 255, 153, 153, 152, 255, 214, 213, 213, 255, + 254, 253, 252, 255, 114, 114, 114, 255, 225, 224, 224, 255, 133, 133, 133, 255, 249, 248, 248, 255, 178, 177, 177, 255, 253, 252, 252, 255, 108, 107, 107, + 255, 245, 243, 243, 255, 253, 251, 251, 255, 254, 252, 250, 255, 153, 151, 150, 255, 212, 210, 210, 255, 253, 251, 249, 255, 107, 106, 105, 255, 241, 237, + 234, 255, 142, 141, 139, 255, 168, 165, 163, 255, 183, 179, 177, 255, 163, 159, 158, 255, 222, 216, 214, 255, 83, 81, 80, 255, 249, 241, 240, 255, 114, + 111, 111, 255, 219, 212, 211, 255, 124, 120, 119, 255, 239, 232, 232, 255, 102, 99, 99, 255, 244, 235, 235, 255, 247, 236, 233, 255, 251, 238, 229, 255, + 181, 185, 204, 255, 173, 185, 207, 255, 172, 172, 200, 255, 174, 183, 208, 255, 175, 190, 213, 255, 177, 192, 215, 255, 179, 194, 216, 255, 181, 195, 217, + 255, 183, 197, 218, 255, 186, 198, 219, 255, 188, 199, 220, 255, 190, 201, 221, 255, 192, 202, 222, 255, 193, 204, 223, 255, 196, 205, 224, 255, 198, 205, + 224, 255, 200, 206, 224, 255, 202, 207, 225, 255, 203, 208, 224, 255, 205, 209, 225, 255, 206, 209, 224, 255, 208, 209, 225, 255, 209, 210, 224, 255, 210, + 210, 224, 255, 211, 210, 224, 255, 211, 210, 224, 255, 211, 209, 222, 255, 214, 207, 219, 255, 218, 205, 216, 255, 218, 205, 215, 255, 217, 205, 214, 255, + 215, 204, 214, 255, 214, 204, 213, 255, 206, 198, 212, 255, 214, 209, 217, 255, 195, 194, 212, 255, 200, 203, 215, 255, 197, 201, 214, 255, 196, 200, 214, + 255, 195, 199, 212, 255, 197, 199, 212, 255, 202, 199, 211, 255, 215, 197, 210, 255, 196, 194, 211, 255, 187, 184, 204, 255, 204, 200, 212, 255, 207, 202, + 213, 255, 208, 202, 214, 255, 209, 203, 214, 255, 211, 205, 215, 255, 212, 205, 216, 255, 200, 196, 214, 255, 199, 194, 214, 255, 201, 196, 214, 255, 204, + 199, 217, 255, 207, 201, 220, 255, 210, 204, 222, 255, 213, 207, 224, 255, 217, 211, 226, 255, 163, 159, 169, 255, 223, 218, 230, 255, 227, 222, 232, 255, + 225, 220, 229, 255, 132, 128, 133, 255, 135, 131, 136, 255, 229, 222, 229, 255, 243, 236, 239, 255, 148, 144, 145, 255, 149, 144, 144, 255, 182, 180, 175, + 255, 252, 247, 244, 255, 183, 179, 180, 255, 249, 245, 246, 255, 249, 245, 247, 255, 249, 246, 248, 255, 186, 184, 185, 255, 250, 248, 249, 255, 184, 182, + 183, 255, 251, 249, 250, 255, 232, 231, 231, 255, 204, 203, 204, 255, 252, 251, 251, 255, 158, 158, 158, 255, 206, 206, 206, 255, 246, 246, 246, 255, 141, + 141, 141, 255, 146, 145, 146, 255, 243, 242, 243, 255, 208, 207, 208, 255, 230, 229, 230, 255, 253, 253, 253, 255, 193, 193, 192, 255, 246, 246, 245, 255, + 250, 249, 249, 255, 189, 188, 188, 255, 253, 252, 253, 255, 167, 166, 167, 255, 134, 134, 134, 255, 223, 222, 222, 255, 254, 253, 252, 255, 203, 202, 202, + 255, 163, 162, 162, 255, 253, 252, 251, 255, 255, 253, 251, 255, 193, 191, 190, 255, 244, 241, 242, 255, 253, 251, 249, 255, 222, 220, 218, 255, 131, 129, + 128, 255, 165, 163, 161, 255, 223, 220, 217, 255, 250, 245, 243, 255, 145, 143, 141, 255, 156, 152, 151, 255, 181, 176, 175, 255, 244, 237, 236, 255, 190, + 184, 183, 255, 249, 241, 240, 255, 166, 161, 160, 255, 129, 124, 124, 255, 216, 210, 210, 255, 244, 236, 236, 255, 246, 236, 233, 255, 250, 238, 230, 255, + 185, 188, 204, 255, 172, 177, 200, 255, 171, 172, 199, 255, 172, 191, 213, 255, 174, 193, 214, 255, 176, 195, 216, 255, 177, 196, 217, 255, 180, 197, 218, + 255, 182, 199, 219, 255, 184, 200, 220, 255, 187, 201, 221, 255, 189, 202, 221, 255, 191, 203, 222, 255, 193, 204, 223, 255, 196, 205, 222, 255, 199, 205, + 223, 255, 201, 206, 223, 255, 204, 206, 223, 255, 205, 206, 223, 255, 205, 206, 222, 255, 206, 206, 222, 255, 208, 205, 221, 255, 208, 205, 221, 255, 209, + 206, 221, 255, 210, 205, 219, 255, 210, 204, 218, 255, 209, 202, 217, 255, 209, 199, 214, 255, 209, 195, 210, 255, 207, 194, 209, 255, 209, 195, 209, 255, + 206, 193, 208, 255, 205, 196, 209, 255, 200, 191, 208, 255, 206, 199, 210, 255, 193, 192, 211, 255, 197, 198, 212, 255, 196, 198, 212, 255, 194, 198, 211, + 255, 194, 197, 211, 255, 194, 197, 210, 255, 200, 197, 210, 255, 214, 197, 209, 255, 201, 195, 211, 255, 186, 183, 202, 255, 208, 201, 213, 255, 211, 205, + 215, 255, 213, 206, 215, 255, 214, 207, 215, 255, 215, 208, 217, 255, 217, 209, 217, 255, 202, 197, 215, 255, 198, 194, 214, 255, 201, 196, 213, 255, 205, + 199, 217, 255, 207, 202, 220, 255, 211, 205, 222, 255, 215, 208, 224, 255, 217, 212, 227, 255, 221, 216, 229, 255, 224, 219, 231, 255, 228, 222, 232, 255, + 231, 225, 234, 255, 234, 228, 236, 255, 236, 230, 238, 255, 238, 231, 238, 255, 244, 237, 240, 255, 246, 239, 241, 255, 247, 240, 241, 255, 251, 246, 243, + 255, 249, 244, 244, 255, 248, 244, 245, 255, 249, 246, 247, 255, 250, 247, 248, 255, 250, 248, 249, 255, 251, 249, 250, 255, 251, 249, 250, 255, 251, 249, + 250, 255, 252, 251, 251, 255, 252, 251, 251, 255, 252, 251, 252, 255, 252, 251, 252, 255, 252, 252, 252, 255, 252, 252, 252, 255, 252, 252, 252, 255, 253, + 253, 253, 255, 252, 252, 252, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 254, 255, 254, 254, 253, 255, 255, 254, 253, 255, 254, 254, 253, 255, + 254, 254, 253, 255, 253, 253, 252, 255, 253, 252, 252, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 252, 252, 255, 254, 253, 253, 255, 253, 252, 252, + 255, 253, 252, 251, 255, 254, 252, 252, 255, 255, 253, 252, 255, 254, 252, 251, 255, 251, 249, 250, 255, 254, 252, 250, 255, 254, 252, 250, 255, 254, 251, + 248, 255, 254, 251, 248, 255, 253, 249, 246, 255, 253, 248, 245, 255, 253, 248, 246, 255, 252, 246, 244, 255, 251, 245, 243, 255, 250, 243, 242, 255, 250, + 243, 242, 255, 249, 242, 241, 255, 248, 240, 240, 255, 245, 238, 238, 255, 244, 237, 237, 255, 244, 236, 236, 255, 246, 235, 234, 255, 249, 237, 231, 255, + 179, 185, 203, 255, 168, 167, 194, 255, 169, 175, 200, 255, 170, 184, 209, 255, 172, 186, 210, 255, 174, 187, 211, 255, 176, 189, 212, 255, 178, 190, 214, + 255, 180, 192, 214, 255, 182, 193, 216, 255, 184, 195, 216, 255, 186, 196, 218, 255, 188, 197, 218, 255, 190, 187, 210, 255, 203, 188, 209, 255, 207, 189, + 209, 255, 210, 190, 208, 255, 213, 192, 208, 255, 215, 193, 208, 255, 216, 194, 208, 255, 217, 194, 208, 255, 216, 191, 208, 255, 216, 191, 207, 255, 217, + 192, 208, 255, 219, 194, 207, 255, 220, 195, 206, 255, 219, 195, 205, 255, 218, 194, 204, 255, 212, 189, 204, 255, 202, 184, 204, 255, 209, 188, 203, 255, + 209, 188, 203, 255, 206, 186, 202, 255, 194, 185, 204, 255, 203, 194, 208, 255, 193, 186, 204, 255, 191, 195, 211, 255, 195, 197, 211, 255, 193, 196, 209, + 255, 192, 196, 209, 255, 192, 196, 209, 255, 197, 195, 209, 255, 209, 196, 209, 255, 210, 194, 209, 255, 186, 183, 201, 255, 202, 197, 210, 255, 205, 201, + 212, 255, 207, 202, 213, 255, 209, 203, 214, 255, 210, 204, 215, 255, 212, 205, 216, 255, 201, 197, 214, 255, 199, 195, 215, 255, 201, 197, 214, 255, 205, + 200, 218, 255, 208, 203, 221, 255, 211, 206, 223, 255, 215, 209, 225, 255, 218, 212, 227, 255, 221, 216, 229, 255, 225, 219, 231, 255, 228, 223, 233, 255, + 231, 226, 235, 255, 235, 229, 237, 255, 237, 231, 238, 255, 238, 232, 239, 255, 244, 238, 241, 255, 245, 240, 242, 255, 244, 239, 243, 255, 244, 240, 244, + 255, 246, 242, 245, 255, 248, 245, 246, 255, 249, 246, 248, 255, 250, 247, 248, 255, 250, 248, 249, 255, 251, 249, 250, 255, 251, 249, 250, 255, 252, 250, + 251, 255, 252, 251, 251, 255, 252, 251, 251, 255, 252, 252, 252, 255, 252, 251, 252, 255, 253, 252, 253, 255, 252, 252, 252, 255, 253, 252, 252, 255, 253, + 253, 253, 255, 253, 252, 253, 255, 253, 253, 253, 255, 254, 253, 254, 255, 253, 253, 253, 255, 254, 253, 253, 255, 255, 254, 254, 255, 255, 254, 254, 255, + 254, 253, 253, 255, 253, 253, 253, 255, 254, 253, 253, 255, 254, 253, 253, 255, 254, 253, 253, 255, 253, 253, 253, 255, 253, 253, 252, 255, 253, 252, 252, + 255, 253, 252, 252, 255, 254, 253, 252, 255, 255, 254, 252, 255, 254, 253, 251, 255, 252, 250, 251, 255, 254, 252, 250, 255, 254, 252, 250, 255, 254, 252, + 249, 255, 254, 251, 249, 255, 253, 249, 247, 255, 253, 248, 246, 255, 252, 247, 246, 255, 252, 247, 245, 255, 251, 245, 244, 255, 250, 243, 242, 255, 250, + 243, 242, 255, 249, 242, 241, 255, 248, 241, 240, 255, 246, 238, 238, 255, 245, 238, 238, 255, 243, 236, 236, 255, 245, 236, 234, 255, 249, 237, 232, 255, + 169, 174, 197, 255, 166, 165, 191, 255, 168, 180, 204, 255, 169, 186, 209, 255, 171, 187, 210, 255, 173, 189, 211, 255, 175, 190, 212, 255, 177, 191, 213, + 255, 179, 193, 214, 255, 182, 194, 215, 255, 184, 195, 216, 255, 187, 196, 217, 255, 189, 194, 215, 255, 198, 180, 205, 255, 196, 181, 204, 255, 195, 181, + 204, 255, 195, 182, 204, 255, 196, 182, 204, 255, 196, 183, 204, 255, 197, 183, 204, 255, 198, 183, 204, 255, 198, 183, 204, 255, 197, 183, 204, 255, 199, + 184, 204, 255, 201, 185, 204, 255, 199, 184, 203, 255, 199, 184, 202, 255, 202, 186, 202, 255, 203, 187, 201, 255, 206, 191, 201, 255, 204, 189, 200, 255, + 194, 181, 199, 255, 201, 181, 200, 255, 191, 180, 201, 255, 199, 190, 205, 255, 191, 182, 202, 255, 188, 184, 204, 255, 194, 195, 208, 255, 193, 194, 208, + 255, 192, 194, 207, 255, 192, 194, 208, 255, 195, 194, 207, 255, 203, 195, 207, 255, 215, 193, 206, 255, 190, 187, 204, 255, 203, 197, 210, 255, 207, 202, + 212, 255, 208, 203, 213, 255, 210, 204, 214, 255, 212, 205, 215, 255, 213, 207, 216, 255, 201, 198, 214, 255, 198, 195, 215, 255, 202, 197, 214, 255, 205, + 200, 217, 255, 209, 204, 221, 255, 211, 207, 223, 255, 215, 210, 225, 255, 218, 213, 227, 255, 222, 217, 230, 255, 225, 220, 231, 255, 228, 223, 234, 255, + 232, 226, 235, 255, 235, 230, 237, 255, 237, 232, 239, 255, 239, 233, 240, 255, 244, 238, 242, 255, 245, 240, 243, 255, 244, 240, 243, 255, 247, 242, 244, + 255, 249, 246, 247, 255, 248, 245, 247, 255, 249, 247, 248, 255, 250, 248, 249, 255, 250, 249, 250, 255, 251, 249, 250, 255, 251, 249, 250, 255, 251, 250, + 251, 255, 252, 251, 252, 255, 252, 251, 252, 255, 252, 252, 252, 255, 253, 252, 252, 255, 253, 252, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, + 253, 253, 255, 253, 253, 254, 255, 253, 253, 254, 255, 253, 253, 253, 255, 253, 253, 254, 255, 254, 254, 253, 255, 254, 254, 253, 255, 254, 254, 253, 255, + 254, 253, 253, 255, 253, 253, 254, 255, 253, 253, 253, 255, 253, 253, 254, 255, 253, 253, 254, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 254, + 255, 253, 253, 254, 255, 253, 253, 253, 255, 254, 253, 253, 255, 255, 253, 252, 255, 252, 251, 251, 255, 253, 251, 251, 255, 254, 252, 251, 255, 255, 252, + 250, 255, 254, 252, 249, 255, 253, 250, 247, 255, 253, 248, 246, 255, 251, 246, 245, 255, 252, 247, 245, 255, 251, 245, 244, 255, 250, 243, 242, 255, 248, + 241, 241, 255, 248, 240, 240, 255, 247, 240, 240, 255, 246, 239, 239, 255, 245, 238, 238, 255, 244, 236, 237, 255, 245, 235, 235, 255, 248, 236, 232, 255, + 165, 164, 190, 255, 165, 168, 193, 255, 166, 182, 206, 255, 168, 183, 207, 255, 170, 185, 208, 255, 172, 186, 209, 255, 174, 188, 210, 255, 176, 189, 211, + 255, 178, 190, 212, 255, 181, 191, 213, 255, 183, 192, 214, 255, 185, 193, 214, 255, 187, 191, 213, 255, 197, 177, 202, 255, 191, 179, 201, 255, 223, 204, + 204, 255, 231, 212, 205, 255, 206, 189, 202, 255, 229, 209, 205, 255, 220, 201, 203, 255, 231, 211, 204, 255, 223, 202, 203, 255, 196, 180, 201, 255, 229, + 209, 204, 255, 247, 229, 207, 255, 233, 211, 204, 255, 225, 205, 202, 255, 250, 232, 206, 255, 240, 217, 202, 255, 253, 234, 206, 255, 252, 231, 204, 255, + 223, 203, 198, 255, 199, 178, 198, 255, 189, 178, 199, 255, 196, 186, 203, 255, 188, 179, 200, 255, 184, 176, 198, 255, 192, 192, 206, 255, 192, 192, 207, + 255, 192, 193, 206, 255, 192, 193, 206, 255, 194, 194, 207, 255, 200, 194, 206, 255, 212, 193, 206, 255, 197, 191, 208, 255, 202, 196, 210, 255, 207, 201, + 213, 255, 209, 203, 213, 255, 210, 204, 214, 255, 212, 206, 215, 255, 214, 207, 216, 255, 201, 198, 214, 255, 199, 195, 215, 255, 202, 198, 214, 255, 206, + 202, 218, 255, 209, 204, 221, 255, 212, 208, 224, 255, 215, 211, 226, 255, 219, 214, 228, 255, 222, 218, 230, 255, 225, 221, 232, 255, 229, 224, 234, 255, + 231, 226, 236, 255, 235, 230, 238, 255, 237, 232, 239, 255, 239, 234, 241, 255, 244, 240, 242, 255, 246, 241, 243, 255, 244, 240, 244, 255, 249, 244, 245, + 255, 251, 247, 248, 255, 248, 245, 247, 255, 250, 248, 248, 255, 251, 249, 249, 255, 251, 249, 250, 255, 252, 250, 251, 255, 251, 250, 251, 255, 252, 251, + 252, 255, 253, 252, 252, 255, 253, 252, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 254, 253, 254, 255, 254, 253, 254, 255, 254, + 253, 254, 255, 253, 253, 253, 255, 254, 253, 254, 255, 254, 253, 254, 255, 254, 254, 254, 255, 254, 254, 253, 255, 254, 254, 254, 255, 253, 253, 254, 255, + 254, 254, 254, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 253, 254, 255, 253, 253, 254, 255, 253, 253, 254, + 255, 253, 253, 254, 255, 253, 253, 254, 255, 253, 253, 253, 255, 254, 253, 252, 255, 253, 252, 251, 255, 253, 252, 251, 255, 255, 253, 251, 255, 255, 253, + 250, 255, 254, 252, 249, 255, 253, 250, 248, 255, 252, 248, 247, 255, 250, 246, 245, 255, 252, 247, 245, 255, 251, 246, 245, 255, 250, 244, 243, 255, 249, + 242, 242, 255, 248, 241, 241, 255, 248, 241, 240, 255, 247, 240, 240, 255, 246, 239, 239, 255, 244, 237, 237, 255, 244, 235, 235, 255, 247, 236, 232, 255, + 163, 162, 187, 255, 165, 171, 195, 255, 166, 175, 202, 255, 167, 177, 204, 255, 169, 178, 205, 255, 171, 179, 205, 255, 172, 180, 206, 255, 175, 181, 207, + 255, 176, 182, 208, 255, 178, 184, 209, 255, 181, 185, 210, 255, 183, 186, 210, 255, 184, 184, 209, 255, 196, 174, 199, 255, 222, 200, 199, 255, 252, 232, + 207, 255, 251, 230, 206, 255, 246, 224, 205, 255, 246, 226, 206, 255, 250, 229, 206, 255, 245, 223, 204, 255, 233, 210, 202, 255, 193, 177, 198, 255, 237, + 217, 204, 255, 254, 237, 207, 255, 250, 229, 204, 255, 226, 204, 200, 255, 254, 236, 205, 255, 243, 218, 200, 255, 254, 234, 204, 255, 242, 217, 199, 255, + 237, 214, 197, 255, 201, 177, 195, 255, 186, 175, 196, 255, 193, 182, 200, 255, 185, 176, 198, 255, 182, 173, 195, 255, 189, 185, 201, 255, 192, 192, 205, + 255, 192, 191, 205, 255, 192, 193, 205, 255, 194, 193, 206, 255, 198, 194, 206, 255, 208, 194, 206, 255, 202, 191, 208, 255, 196, 191, 208, 255, 200, 195, + 210, 255, 201, 197, 211, 255, 203, 199, 212, 255, 205, 201, 213, 255, 207, 202, 215, 255, 200, 196, 214, 255, 199, 196, 214, 255, 202, 199, 214, 255, 206, + 202, 218, 255, 209, 205, 222, 255, 213, 209, 224, 255, 216, 212, 226, 255, 219, 215, 228, 255, 223, 220, 231, 255, 228, 223, 233, 255, 232, 226, 235, 255, + 233, 228, 237, 255, 236, 231, 238, 255, 239, 234, 240, 255, 240, 235, 241, 255, 243, 239, 242, 255, 246, 241, 243, 255, 244, 241, 245, 255, 249, 245, 246, + 255, 251, 248, 249, 255, 248, 246, 248, 255, 250, 249, 250, 255, 251, 249, 250, 255, 251, 250, 250, 255, 252, 250, 251, 255, 252, 251, 251, 255, 252, 251, + 252, 255, 253, 252, 252, 255, 253, 252, 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 254, 253, 254, 255, 254, 253, 254, 255, 254, 253, 254, 255, 254, + 253, 254, 255, 254, 254, 254, 255, 254, 254, 254, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 254, 254, 255, 254, 254, 254, 255, 212, 212, 212, 255, + 225, 225, 225, 255, 254, 254, 254, 255, 254, 254, 254, 255, 254, 254, 254, 255, 253, 253, 254, 255, 253, 253, 254, 255, 254, 254, 254, 255, 253, 253, 254, + 255, 253, 253, 254, 255, 253, 253, 254, 255, 253, 253, 253, 255, 253, 253, 253, 255, 253, 252, 253, 255, 253, 252, 252, 255, 254, 253, 251, 255, 254, 252, + 250, 255, 153, 152, 150, 255, 166, 163, 162, 255, 252, 248, 247, 255, 250, 246, 246, 255, 251, 246, 246, 255, 252, 247, 246, 255, 250, 245, 244, 255, 249, + 243, 243, 255, 248, 242, 242, 255, 248, 241, 241, 255, 247, 240, 240, 255, 246, 238, 239, 255, 243, 237, 238, 255, 244, 235, 236, 255, 247, 236, 233, 255, + 163, 161, 187, 255, 165, 178, 199, 255, 166, 180, 204, 255, 167, 180, 205, 255, 170, 182, 205, 255, 171, 182, 206, 255, 174, 184, 207, 255, 176, 185, 208, + 255, 178, 186, 208, 255, 179, 187, 209, 255, 182, 188, 210, 255, 184, 189, 210, 255, 185, 187, 209, 255, 194, 172, 197, 255, 229, 203, 198, 255, 251, 229, + 204, 255, 243, 219, 202, 255, 250, 230, 205, 255, 246, 224, 203, 255, 254, 236, 207, 255, 253, 232, 204, 255, 235, 212, 200, 255, 192, 173, 196, 255, 239, + 219, 202, 255, 251, 227, 202, 255, 254, 236, 205, 255, 231, 206, 197, 255, 254, 235, 203, 255, 243, 217, 198, 255, 254, 234, 202, 255, 252, 230, 200, 255, + 229, 206, 195, 255, 199, 175, 193, 255, 184, 172, 194, 255, 189, 178, 199, 255, 183, 173, 196, 255, 180, 172, 194, 255, 184, 178, 196, 255, 193, 190, 204, + 255, 192, 191, 205, 255, 193, 192, 205, 255, 194, 194, 206, 255, 196, 195, 206, 255, 203, 195, 206, 255, 202, 190, 207, 255, 202, 196, 210, 255, 206, 200, + 211, 255, 207, 201, 212, 255, 209, 203, 214, 255, 211, 204, 215, 255, 213, 206, 216, 255, 201, 198, 214, 255, 199, 196, 214, 255, 202, 199, 215, 255, 206, + 202, 218, 255, 209, 206, 222, 255, 213, 209, 225, 255, 216, 212, 227, 255, 220, 216, 229, 255, 227, 222, 232, 255, 237, 231, 235, 255, 239, 231, 235, 255, + 241, 232, 237, 255, 243, 236, 239, 255, 245, 239, 242, 255, 248, 241, 243, 255, 250, 243, 246, 255, 251, 245, 247, 255, 250, 246, 247, 255, 251, 247, 248, + 255, 252, 249, 250, 255, 251, 249, 250, 255, 243, 242, 242, 255, 203, 201, 202, 255, 242, 240, 240, 255, 254, 252, 252, 255, 218, 216, 216, 255, 231, 229, + 229, 255, 211, 210, 210, 255, 254, 253, 253, 255, 255, 254, 253, 255, 227, 227, 227, 255, 211, 210, 210, 255, 255, 254, 254, 255, 254, 253, 253, 255, 255, + 254, 254, 255, 255, 254, 254, 255, 254, 254, 254, 255, 245, 245, 245, 255, 205, 204, 204, 255, 240, 240, 240, 255, 241, 241, 241, 255, 64, 64, 64, 255, + 135, 135, 135, 255, 246, 246, 246, 255, 250, 250, 250, 255, 205, 205, 205, 255, 237, 237, 237, 255, 254, 254, 254, 255, 224, 224, 224, 255, 229, 229, 229, + 255, 208, 208, 208, 255, 252, 252, 253, 255, 254, 254, 253, 255, 255, 254, 253, 255, 252, 251, 251, 255, 208, 208, 208, 255, 228, 227, 226, 255, 254, 253, + 251, 255, 77, 76, 76, 255, 141, 140, 139, 255, 205, 203, 203, 255, 249, 245, 245, 255, 250, 246, 246, 255, 233, 228, 227, 255, 202, 198, 198, 255, 245, + 239, 239, 255, 243, 237, 237, 255, 204, 199, 199, 255, 219, 212, 213, 255, 217, 211, 212, 255, 243, 236, 238, 255, 243, 235, 236, 255, 246, 235, 234, 255, + 165, 165, 189, 255, 170, 179, 198, 255, 178, 182, 201, 255, 166, 171, 200, 255, 167, 172, 201, 255, 169, 173, 202, 255, 171, 174, 203, 255, 172, 175, 203, + 255, 174, 177, 204, 255, 176, 177, 204, 255, 178, 179, 205, 255, 180, 179, 206, 255, 182, 179, 204, 255, 192, 170, 195, 255, 226, 200, 195, 255, 252, 229, + 202, 255, 241, 216, 199, 255, 250, 229, 203, 255, 244, 221, 201, 255, 254, 235, 205, 255, 254, 235, 205, 255, 238, 214, 199, 255, 191, 171, 194, 255, 242, + 221, 201, 255, 241, 212, 197, 255, 254, 235, 203, 255, 239, 212, 196, 255, 254, 234, 202, 255, 243, 216, 196, 255, 254, 233, 200, 255, 246, 220, 196, 255, + 240, 214, 193, 255, 197, 172, 191, 255, 182, 170, 192, 255, 186, 173, 197, 255, 182, 171, 194, 255, 178, 170, 192, 255, 180, 173, 192, 255, 192, 190, 203, + 255, 193, 191, 204, 255, 193, 192, 204, 255, 194, 194, 205, 255, 195, 195, 206, 255, 200, 195, 207, 255, 200, 190, 205, 255, 199, 194, 210, 255, 200, 194, + 209, 255, 201, 196, 210, 255, 203, 198, 211, 255, 206, 200, 213, 255, 208, 202, 214, 255, 200, 197, 214, 255, 200, 197, 215, 255, 203, 200, 216, 255, 206, + 203, 219, 255, 209, 206, 223, 255, 213, 210, 225, 255, 221, 215, 228, 255, 230, 222, 230, 255, 233, 225, 231, 255, 234, 225, 232, 255, 235, 227, 233, 255, + 237, 230, 235, 255, 240, 232, 237, 255, 242, 236, 239, 255, 244, 239, 241, 255, 246, 240, 243, 255, 249, 243, 245, 255, 250, 245, 247, 255, 251, 247, 248, + 255, 253, 249, 249, 255, 230, 227, 226, 255, 35, 35, 35, 255, 48, 47, 47, 255, 34, 34, 34, 255, 246, 245, 244, 255, 17, 17, 17, 255, 49, 49, + 49, 255, 9, 9, 9, 255, 166, 166, 166, 255, 161, 161, 160, 255, 28, 28, 28, 255, 26, 26, 26, 255, 141, 141, 141, 255, 254, 254, 254, 255, 254, + 254, 254, 255, 255, 254, 254, 255, 238, 238, 238, 255, 35, 35, 35, 255, 72, 72, 72, 255, 25, 25, 25, 255, 171, 171, 171, 255, 9, 9, 9, 255, + 54, 54, 54, 255, 218, 218, 218, 255, 51, 51, 51, 255, 49, 49, 49, 255, 20, 20, 20, 255, 229, 229, 229, 255, 58, 58, 58, 255, 31, 31, 31, + 255, 20, 20, 20, 255, 119, 119, 119, 255, 254, 254, 254, 255, 255, 254, 253, 255, 79, 78, 78, 255, 61, 61, 61, 255, 22, 21, 21, 255, 200, 199, + 197, 255, 47, 46, 46, 255, 43, 42, 42, 255, 16, 16, 16, 255, 133, 131, 130, 255, 187, 184, 184, 255, 25, 25, 25, 255, 35, 34, 34, 255, 89, + 87, 87, 255, 209, 204, 204, 255, 0, 0, 0, 255, 47, 46, 46, 255, 7, 7, 7, 255, 199, 194, 195, 255, 243, 235, 236, 255, 246, 235, 234, 255, + 163, 169, 195, 255, 164, 173, 199, 255, 166, 176, 201, 255, 167, 178, 202, 255, 169, 179, 202, 255, 171, 179, 203, 255, 173, 180, 204, 255, 174, 181, 205, + 255, 177, 182, 205, 255, 179, 182, 205, 255, 181, 184, 206, 255, 183, 184, 207, 255, 184, 182, 205, 255, 189, 168, 193, 255, 223, 196, 193, 255, 252, 229, + 199, 255, 239, 214, 197, 255, 250, 230, 202, 255, 244, 219, 199, 255, 251, 227, 199, 255, 254, 234, 203, 255, 241, 216, 197, 255, 190, 170, 192, 255, 246, + 224, 200, 255, 251, 229, 200, 255, 254, 235, 202, 255, 246, 218, 195, 255, 254, 234, 200, 255, 244, 215, 194, 255, 254, 232, 199, 255, 238, 210, 192, 255, + 250, 223, 193, 255, 196, 171, 190, 255, 181, 168, 190, 255, 183, 170, 196, 255, 179, 169, 193, 255, 177, 169, 191, 255, 177, 169, 190, 255, 190, 188, 201, + 255, 193, 191, 203, 255, 194, 193, 204, 255, 194, 194, 205, 255, 195, 196, 205, 255, 198, 196, 206, 255, 199, 193, 206, 255, 202, 196, 210, 255, 202, 196, + 209, 255, 203, 198, 210, 255, 205, 199, 212, 255, 208, 201, 214, 255, 210, 203, 215, 255, 201, 198, 214, 255, 200, 198, 215, 255, 203, 201, 215, 255, 206, + 204, 218, 255, 211, 208, 223, 255, 222, 216, 226, 255, 234, 220, 225, 255, 229, 219, 226, 255, 229, 221, 228, 255, 230, 224, 231, 255, 233, 227, 233, 255, + 237, 231, 236, 255, 243, 236, 239, 255, 248, 241, 242, 255, 249, 243, 244, 255, 251, 245, 245, 255, 252, 247, 247, 255, 253, 249, 248, 255, 253, 250, 249, + 255, 252, 250, 249, 255, 128, 127, 125, 255, 91, 90, 89, 255, 253, 252, 250, 255, 16, 16, 16, 255, 191, 190, 189, 255, 0, 0, 0, 255, 236, 235, + 235, 255, 79, 79, 79, 255, 144, 144, 143, 255, 38, 38, 38, 255, 82, 81, 81, 255, 75, 75, 75, 255, 70, 70, 70, 255, 115, 115, 115, 255, 30, + 30, 30, 255, 30, 30, 30, 255, 189, 189, 189, 255, 15, 15, 15, 255, 115, 115, 115, 255, 171, 171, 171, 255, 250, 250, 250, 255, 14, 14, 14, 255, + 225, 225, 225, 255, 161, 161, 161, 255, 60, 60, 60, 255, 255, 255, 255, 255, 47, 47, 47, 255, 177, 177, 177, 255, 28, 28, 28, 255, 184, 184, 184, + 255, 149, 149, 149, 255, 58, 58, 59, 255, 254, 254, 253, 255, 255, 254, 253, 255, 33, 33, 32, 255, 87, 87, 87, 255, 154, 153, 152, 255, 239, 238, + 236, 255, 16, 16, 16, 255, 205, 203, 202, 255, 109, 108, 108, 255, 108, 107, 107, 255, 63, 62, 62, 255, 154, 151, 151, 255, 203, 199, 198, 255, 19, + 19, 19, 255, 181, 178, 178, 255, 28, 27, 28, 255, 241, 235, 236, 255, 51, 50, 50, 255, 148, 144, 145, 255, 243, 235, 236, 255, 245, 235, 234, 255, + 162, 168, 197, 255, 163, 170, 199, 255, 164, 171, 199, 255, 165, 171, 199, 255, 167, 172, 200, 255, 168, 173, 200, 255, 170, 174, 200, 255, 172, 176, 202, + 255, 174, 177, 202, 255, 176, 177, 203, 255, 178, 178, 203, 255, 180, 179, 204, 255, 181, 177, 202, 255, 187, 166, 191, 255, 217, 190, 191, 255, 253, 229, + 199, 255, 241, 215, 196, 255, 251, 229, 200, 255, 243, 217, 197, 255, 244, 218, 196, 255, 248, 226, 199, 255, 244, 219, 196, 255, 188, 168, 190, 255, 250, + 227, 198, 255, 233, 208, 195, 255, 250, 228, 199, 255, 251, 224, 195, 255, 254, 234, 199, 255, 242, 215, 193, 255, 253, 231, 197, 255, 235, 208, 190, 255, + 249, 221, 191, 255, 195, 169, 189, 255, 180, 167, 189, 255, 180, 168, 194, 255, 178, 168, 192, 255, 176, 168, 190, 255, 176, 167, 189, 255, 185, 180, 196, + 255, 196, 193, 203, 255, 197, 195, 204, 255, 197, 196, 205, 255, 195, 195, 206, 255, 196, 196, 206, 255, 198, 196, 207, 255, 198, 192, 208, 255, 203, 197, + 210, 255, 205, 198, 211, 255, 207, 200, 212, 255, 208, 202, 213, 255, 207, 201, 214, 255, 199, 196, 213, 255, 199, 198, 215, 255, 203, 201, 215, 255, 207, + 205, 219, 255, 216, 211, 223, 255, 232, 220, 224, 255, 244, 226, 221, 255, 235, 224, 229, 255, 239, 230, 234, 255, 244, 235, 238, 255, 245, 238, 240, 255, + 249, 241, 241, 255, 251, 243, 243, 255, 251, 244, 244, 255, 252, 246, 246, 255, 253, 248, 248, 255, 253, 249, 249, 255, 253, 249, 249, 255, 253, 250, 249, + 255, 251, 249, 249, 255, 104, 103, 102, 255, 109, 109, 108, 255, 218, 216, 215, 255, 11, 11, 11, 255, 194, 193, 192, 255, 22, 22, 22, 255, 253, 252, + 252, 255, 55, 55, 55, 255, 174, 174, 173, 255, 18, 18, 18, 255, 150, 149, 149, 255, 155, 155, 155, 255, 197, 197, 197, 255, 239, 239, 239, 255, 231, + 231, 231, 255, 231, 231, 231, 255, 216, 216, 216, 255, 167, 166, 166, 255, 106, 106, 106, 255, 23, 23, 23, 255, 236, 236, 236, 255, 0, 0, 0, 255, + 241, 241, 241, 255, 138, 138, 138, 255, 79, 79, 79, 255, 236, 236, 236, 255, 18, 18, 18, 255, 211, 211, 211, 255, 2, 2, 2, 255, 201, 201, 201, + 255, 101, 101, 101, 255, 95, 95, 95, 255, 254, 254, 253, 255, 237, 236, 236, 255, 166, 165, 165, 255, 143, 143, 143, 255, 7, 7, 7, 255, 195, 194, + 192, 255, 0, 0, 0, 255, 241, 239, 238, 255, 85, 84, 84, 255, 141, 139, 139, 255, 42, 42, 42, 255, 173, 169, 169, 255, 155, 153, 152, 255, 60, + 59, 59, 255, 152, 149, 149, 255, 43, 41, 42, 255, 230, 224, 226, 255, 20, 19, 19, 255, 183, 178, 179, 255, 243, 235, 236, 255, 245, 234, 234, 255, + 163, 170, 196, 255, 165, 175, 198, 255, 167, 179, 200, 255, 170, 178, 198, 255, 168, 170, 193, 255, 166, 171, 194, 255, 168, 173, 195, 255, 172, 174, 195, + 255, 175, 172, 194, 255, 176, 174, 198, 255, 177, 175, 202, 255, 179, 176, 202, 255, 180, 174, 201, 255, 185, 165, 190, 255, 191, 170, 189, 255, 243, 217, + 194, 255, 249, 226, 197, 255, 221, 196, 192, 255, 224, 198, 191, 255, 230, 202, 192, 255, 219, 194, 191, 255, 220, 193, 191, 255, 187, 166, 189, 255, 219, + 193, 191, 255, 201, 178, 190, 255, 210, 186, 190, 255, 209, 185, 189, 255, 207, 184, 189, 255, 199, 177, 187, 255, 199, 179, 188, 255, 191, 172, 187, 255, + 192, 173, 187, 255, 193, 167, 188, 255, 178, 166, 188, 255, 177, 166, 192, 255, 176, 166, 191, 255, 175, 166, 189, 255, 174, 167, 189, 255, 182, 176, 193, + 255, 205, 198, 204, 255, 201, 196, 204, 255, 194, 193, 204, 255, 193, 193, 204, 255, 194, 195, 205, 255, 198, 198, 207, 255, 196, 190, 207, 255, 198, 192, + 209, 255, 196, 193, 209, 255, 198, 190, 207, 255, 201, 192, 207, 255, 198, 192, 208, 255, 197, 195, 210, 255, 200, 198, 213, 255, 203, 202, 215, 255, 211, + 208, 220, 255, 217, 212, 222, 255, 242, 225, 223, 255, 238, 227, 228, 255, 238, 228, 233, 255, 247, 237, 238, 255, 247, 238, 240, 255, 250, 241, 242, 255, + 251, 244, 245, 255, 252, 246, 246, 255, 252, 246, 247, 255, 252, 247, 247, 255, 252, 247, 247, 255, 253, 248, 248, 255, 253, 250, 250, 255, 254, 251, 251, + 255, 252, 249, 250, 255, 195, 193, 193, 255, 19, 19, 19, 255, 20, 20, 20, 255, 154, 153, 153, 255, 177, 176, 175, 255, 53, 53, 53, 255, 253, 252, + 252, 255, 27, 27, 26, 255, 206, 205, 205, 255, 123, 123, 123, 255, 13, 13, 13, 255, 35, 35, 35, 255, 210, 210, 209, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 254, 255, 189, 189, 189, 255, 24, 24, 24, 255, 34, 34, 34, 255, 119, 119, 119, 255, 238, 238, 238, 255, 28, 28, 28, 255, + 89, 89, 89, 255, 218, 218, 219, 255, 26, 26, 26, 255, 17, 17, 17, 255, 129, 129, 129, 255, 218, 218, 218, 255, 8, 8, 8, 255, 23, 23, 23, + 255, 30, 30, 30, 255, 217, 217, 217, 255, 254, 253, 253, 255, 232, 232, 231, 255, 37, 37, 37, 255, 37, 37, 37, 255, 67, 67, 67, 255, 200, 199, + 198, 255, 22, 22, 22, 255, 252, 250, 250, 255, 57, 56, 56, 255, 173, 170, 170, 255, 142, 140, 140, 255, 12, 12, 12, 255, 31, 31, 31, 255, 200, + 196, 196, 255, 121, 118, 118, 255, 22, 21, 21, 255, 6, 6, 6, 255, 86, 84, 85, 255, 242, 235, 237, 255, 244, 236, 236, 255, 246, 235, 234, 255, + 174, 191, 202, 255, 176, 184, 199, 255, 166, 168, 190, 255, 169, 170, 192, 255, 180, 190, 201, 255, 171, 186, 201, 255, 167, 183, 200, 255, 173, 183, 200, + 255, 190, 183, 198, 255, 178, 173, 194, 255, 176, 168, 193, 255, 177, 169, 194, 255, 181, 177, 201, 255, 182, 164, 189, 255, 181, 163, 187, 255, 183, 165, + 187, 255, 186, 167, 187, 255, 183, 164, 187, 255, 184, 164, 187, 255, 185, 165, 188, 255, 185, 165, 188, 255, 185, 165, 188, 255, 186, 164, 187, 255, 186, + 165, 187, 255, 187, 165, 188, 255, 189, 165, 188, 255, 190, 165, 187, 255, 190, 165, 186, 255, 191, 166, 186, 255, 193, 166, 186, 255, 195, 166, 186, 255, + 195, 166, 187, 255, 193, 165, 187, 255, 177, 164, 187, 255, 176, 164, 189, 255, 175, 165, 188, 255, 174, 166, 187, 255, 174, 167, 188, 255, 176, 170, 190, + 255, 197, 192, 201, 255, 190, 189, 201, 255, 189, 190, 203, 255, 192, 194, 205, 255, 195, 197, 207, 255, 199, 200, 208, 255, 197, 194, 207, 255, 199, 193, + 209, 255, 189, 186, 205, 255, 189, 187, 204, 255, 194, 191, 207, 255, 201, 197, 211, 255, 209, 203, 215, 255, 205, 201, 215, 255, 206, 203, 217, 255, 207, + 206, 218, 255, 219, 214, 224, 255, 234, 223, 229, 255, 241, 231, 234, 255, 236, 230, 235, 255, 244, 235, 238, 255, 247, 238, 239, 255, 251, 242, 242, 255, + 251, 244, 244, 255, 251, 244, 245, 255, 252, 246, 246, 255, 253, 248, 248, 255, 253, 249, 249, 255, 253, 249, 249, 255, 254, 250, 250, 255, 253, 251, 251, + 255, 253, 251, 251, 255, 252, 250, 249, 255, 250, 248, 247, 255, 248, 246, 247, 255, 252, 250, 251, 255, 253, 252, 252, 255, 253, 252, 252, 255, 253, 253, + 253, 255, 254, 253, 253, 255, 255, 254, 254, 255, 254, 254, 254, 255, 248, 247, 247, 255, 253, 253, 252, 255, 255, 254, 254, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 253, 253, 253, 255, 250, 250, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 249, 249, 249, 255, 254, 254, 254, 255, 188, 188, 188, 255, 43, 43, 43, 255, 249, 249, 249, + 255, 252, 252, 252, 255, 254, 254, 255, 255, 254, 254, 254, 255, 254, 253, 254, 255, 253, 253, 253, 255, 248, 247, 246, 255, 255, 254, 252, 255, 255, 253, + 252, 255, 254, 253, 252, 255, 253, 250, 250, 255, 252, 249, 249, 255, 252, 249, 249, 255, 251, 247, 247, 255, 245, 241, 240, 255, 250, 245, 244, 255, 251, + 247, 246, 255, 89, 87, 87, 255, 134, 131, 131, 255, 238, 232, 234, 255, 244, 238, 239, 255, 244, 237, 238, 255, 245, 236, 236, 255, 246, 235, 235, 255, + 165, 170, 191, 255, 162, 162, 188, 255, 162, 161, 190, 255, 163, 162, 190, 255, 164, 163, 190, 255, 165, 164, 191, 255, 167, 163, 190, 255, 168, 162, 190, + 255, 173, 164, 191, 255, 171, 163, 191, 255, 174, 166, 194, 255, 175, 166, 193, 255, 176, 165, 192, 255, 178, 163, 189, 255, 189, 163, 188, 255, 182, 164, + 191, 255, 187, 165, 191, 255, 204, 168, 189, 255, 203, 168, 188, 255, 202, 168, 187, 255, 201, 168, 187, 255, 198, 167, 187, 255, 194, 164, 187, 255, 193, + 164, 187, 255, 194, 165, 188, 255, 197, 166, 186, 255, 196, 167, 187, 255, 194, 166, 187, 255, 192, 166, 186, 255, 189, 165, 186, 255, 187, 165, 185, 255, + 185, 165, 187, 255, 192, 176, 191, 255, 206, 190, 197, 255, 205, 190, 198, 255, 204, 190, 198, 255, 203, 190, 198, 255, 204, 190, 197, 255, 203, 191, 198, + 255, 193, 187, 199, 255, 188, 187, 201, 255, 191, 193, 204, 255, 195, 198, 206, 255, 197, 201, 208, 255, 199, 201, 208, 255, 198, 198, 208, 255, 201, 197, + 211, 255, 194, 196, 211, 255, 195, 197, 212, 255, 200, 202, 215, 255, 202, 205, 217, 255, 207, 205, 217, 255, 206, 203, 216, 255, 204, 203, 215, 255, 220, + 209, 220, 255, 235, 223, 229, 255, 241, 226, 230, 255, 239, 231, 235, 255, 244, 234, 235, 255, 249, 238, 238, 255, 246, 236, 237, 255, 247, 238, 240, 255, + 250, 243, 243, 255, 252, 246, 246, 255, 252, 247, 246, 255, 253, 248, 247, 255, 253, 249, 248, 255, 254, 250, 249, 255, 254, 251, 250, 255, 254, 251, 251, + 255, 254, 252, 251, 255, 253, 251, 250, 255, 252, 250, 250, 255, 251, 250, 251, 255, 252, 251, 252, 255, 252, 251, 252, 255, 252, 252, 252, 255, 253, 253, + 253, 255, 254, 253, 253, 255, 254, 253, 253, 255, 254, 254, 254, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 210, 210, 210, 255, 160, 160, 160, 255, 255, 254, 255, + 255, 254, 254, 254, 255, 254, 254, 255, 255, 254, 254, 254, 255, 254, 253, 253, 255, 254, 253, 253, 255, 255, 254, 253, 255, 254, 253, 252, 255, 254, 253, + 252, 255, 254, 253, 252, 255, 254, 252, 251, 255, 252, 250, 250, 255, 252, 249, 249, 255, 251, 247, 247, 255, 251, 247, 246, 255, 250, 245, 245, 255, 251, + 246, 246, 255, 158, 155, 155, 255, 203, 199, 199, 255, 245, 240, 241, 255, 244, 238, 239, 255, 244, 237, 238, 255, 245, 237, 237, 255, 246, 235, 235, 255, + 166, 166, 190, 255, 167, 168, 192, 255, 168, 169, 193, 255, 170, 173, 194, 255, 172, 176, 195, 255, 172, 175, 195, 255, 171, 170, 193, 255, 173, 170, 193, + 255, 179, 177, 196, 255, 182, 180, 198, 255, 187, 186, 200, 255, 190, 189, 202, 255, 191, 188, 202, 255, 188, 182, 199, 255, 181, 168, 192, 255, 178, 161, + 189, 255, 178, 162, 189, 255, 180, 162, 191, 255, 181, 163, 191, 255, 186, 170, 191, 255, 192, 179, 196, 255, 197, 188, 200, 255, 193, 183, 198, 255, 187, + 166, 191, 255, 193, 182, 199, 255, 197, 188, 202, 255, 198, 189, 202, 255, 196, 184, 199, 255, 190, 176, 194, 255, 181, 166, 190, 255, 184, 166, 189, 255, + 182, 164, 188, 255, 181, 166, 187, 255, 183, 167, 189, 255, 183, 168, 189, 255, 183, 167, 190, 255, 184, 168, 190, 255, 183, 169, 191, 255, 182, 169, 192, + 255, 184, 175, 196, 255, 191, 191, 202, 255, 194, 196, 204, 255, 196, 198, 206, 255, 198, 201, 207, 255, 197, 201, 208, 255, 199, 200, 209, 255, 198, 194, + 210, 255, 190, 199, 215, 255, 191, 202, 218, 255, 194, 206, 220, 255, 197, 208, 222, 255, 200, 207, 221, 255, 201, 205, 218, 255, 207, 206, 219, 255, 227, + 213, 224, 255, 222, 215, 225, 255, 239, 223, 229, 255, 243, 232, 234, 255, 238, 229, 233, 255, 232, 227, 233, 255, 243, 231, 235, 255, 249, 240, 241, 255, + 247, 241, 242, 255, 244, 239, 241, 255, 243, 239, 242, 255, 244, 241, 244, 255, 248, 244, 245, 255, 252, 247, 248, 255, 252, 248, 249, 255, 253, 250, 249, + 255, 252, 249, 250, 255, 250, 249, 250, 255, 250, 249, 250, 255, 251, 250, 251, 255, 251, 251, 252, 255, 252, 252, 252, 255, 252, 252, 252, 255, 253, 252, + 253, 255, 253, 253, 253, 255, 253, 253, 253, 255, 254, 254, 254, 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, + 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 254, 254, 254, 255, 254, 254, 254, 255, 255, 254, 254, 255, 254, 254, 254, 255, 254, 253, 253, 255, 255, 254, 253, 255, 254, 253, 252, 255, 253, 252, + 252, 255, 253, 252, 251, 255, 254, 253, 251, 255, 253, 251, 250, 255, 252, 249, 249, 255, 251, 248, 248, 255, 251, 247, 246, 255, 250, 246, 245, 255, 251, + 246, 245, 255, 250, 245, 245, 255, 248, 243, 243, 255, 245, 240, 241, 255, 244, 238, 239, 255, 244, 236, 238, 255, 246, 237, 237, 255, 246, 235, 234, 255, + 184, 193, 202, 255, 183, 191, 201, 255, 177, 184, 198, 255, 172, 178, 196, 255, 171, 175, 196, 255, 175, 180, 198, 255, 180, 187, 201, 255, 184, 191, 203, + 255, 188, 192, 204, 255, 189, 193, 204, 255, 190, 192, 204, 255, 195, 196, 205, 255, 204, 209, 212, 255, 209, 214, 215, 255, 207, 210, 213, 255, 178, 164, + 187, 255, 177, 161, 187, 255, 178, 161, 189, 255, 189, 179, 198, 255, 192, 182, 199, 255, 188, 178, 196, 255, 189, 176, 196, 255, 185, 168, 193, 255, 181, + 162, 186, 255, 184, 172, 194, 255, 186, 177, 196, 255, 187, 178, 195, 255, 189, 182, 196, 255, 192, 184, 197, 255, 196, 187, 199, 255, 196, 185, 197, 255, + 190, 176, 194, 255, 185, 174, 192, 255, 180, 170, 191, 255, 177, 167, 190, 255, 175, 167, 190, 255, 175, 168, 190, 255, 175, 169, 192, 255, 175, 171, 193, + 255, 178, 175, 195, 255, 182, 181, 199, 255, 185, 187, 202, 255, 192, 195, 206, 255, 192, 194, 205, 255, 194, 196, 206, 255, 195, 197, 208, 255, 197, 195, + 209, 255, 193, 195, 213, 255, 200, 199, 215, 255, 197, 199, 216, 255, 196, 200, 216, 255, 204, 207, 221, 255, 206, 208, 222, 255, 214, 213, 226, 255, 225, + 220, 229, 255, 219, 216, 226, 255, 224, 220, 229, 255, 235, 228, 234, 255, 233, 228, 234, 255, 239, 234, 238, 255, 243, 238, 241, 255, 245, 240, 242, 255, + 245, 241, 243, 255, 245, 242, 245, 255, 247, 243, 246, 255, 248, 245, 247, 255, 249, 247, 248, 255, 251, 248, 249, 255, 251, 249, 250, 255, 251, 249, 250, + 255, 252, 250, 251, 255, 252, 251, 252, 255, 251, 251, 252, 255, 252, 252, 253, 255, 253, 252, 253, 255, 253, 253, 253, 255, 253, 252, 253, 255, 253, 253, + 253, 255, 254, 253, 254, 255, 253, 253, 253, 255, 254, 254, 254, 255, 254, 254, 254, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, + 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 254, 254, 253, 255, 254, 254, 253, 255, 255, 254, 253, 255, 253, 253, 252, 255, 252, 252, + 252, 255, 251, 251, 252, 255, 253, 252, 251, 255, 254, 252, 250, 255, 252, 249, 249, 255, 251, 248, 248, 255, 250, 247, 247, 255, 250, 245, 245, 255, 250, + 245, 245, 255, 251, 246, 245, 255, 249, 243, 243, 255, 246, 240, 241, 255, 245, 238, 239, 255, 244, 236, 237, 255, 245, 235, 236, 255, 246, 235, 234, 255, + 169, 174, 195, 255, 169, 177, 196, 255, 172, 184, 199, 255, 180, 194, 203, 255, 187, 202, 208, 255, 192, 207, 210, 255, 198, 211, 213, 255, 204, 215, 215, + 255, 209, 218, 217, 255, 213, 221, 218, 255, 216, 222, 220, 255, 215, 218, 217, 255, 210, 210, 213, 255, 211, 210, 213, 255, 212, 210, 213, 255, 187, 176, + 193, 255, 175, 160, 185, 255, 176, 160, 184, 255, 197, 190, 201, 255, 200, 196, 206, 255, 184, 170, 193, 255, 179, 161, 189, 255, 179, 160, 187, 255, 181, + 160, 187, 255, 183, 163, 191, 255, 182, 166, 190, 255, 186, 175, 194, 255, 195, 194, 204, 255, 196, 196, 204, 255, 195, 191, 201, 255, 190, 182, 197, 255, + 187, 179, 196, 255, 186, 181, 196, 255, 188, 184, 197, 255, 189, 186, 199, 255, 188, 185, 198, 255, 188, 186, 199, 255, 190, 189, 200, 255, 193, 194, 202, + 255, 197, 198, 204, 255, 198, 199, 205, 255, 195, 195, 204, 255, 193, 195, 206, 255, 189, 191, 206, 255, 182, 183, 202, 255, 183, 182, 203, 255, 185, 185, + 205, 255, 185, 184, 206, 255, 188, 188, 208, 255, 191, 192, 211, 255, 194, 198, 215, 255, 198, 201, 218, 255, 201, 203, 218, 255, 209, 206, 220, 255, 214, + 211, 223, 255, 216, 214, 225, 255, 219, 217, 227, 255, 226, 222, 230, 255, 227, 223, 231, 255, 234, 231, 236, 255, 241, 240, 241, 255, 245, 244, 244, 255, + 243, 242, 244, 255, 243, 242, 245, 255, 245, 245, 248, 255, 246, 246, 249, 255, 244, 247, 250, 255, 244, 248, 250, 255, 246, 249, 251, 255, 247, 249, 251, + 255, 248, 250, 252, 255, 248, 250, 252, 255, 249, 251, 252, 255, 251, 251, 252, 255, 251, 251, 253, 255, 252, 252, 253, 255, 252, 252, 252, 255, 253, 253, + 253, 255, 253, 253, 254, 255, 253, 253, 254, 255, 254, 254, 254, 255, 254, 254, 254, 255, 254, 254, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, + 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 254, 254, 254, 255, 254, 254, 254, 255, 254, 253, 253, 255, 254, 254, 253, 255, 254, 253, 253, 255, 253, 253, 253, 255, 253, 252, + 252, 255, 253, 251, 252, 255, 253, 251, 251, 255, 253, 252, 251, 255, 253, 250, 250, 255, 251, 248, 249, 255, 251, 247, 248, 255, 250, 246, 246, 255, 250, + 245, 245, 255, 251, 246, 245, 255, 249, 243, 243, 255, 246, 240, 241, 255, 245, 238, 239, 255, 245, 237, 238, 255, 244, 235, 236, 255, 246, 235, 234, 255}; diff --git a/src/opus_encode.cpp b/src/opus_encode.cpp new file mode 100644 index 0000000..50c7690 --- /dev/null +++ b/src/opus_encode.cpp @@ -0,0 +1,506 @@ +// opus encoding functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include +#include +#include + +#include "opus_encode.h" + +/* Copyright (C)2012 Xiph.Org Foundation + File: opus_header.c + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +typedef struct { + unsigned char *data; + int maxlen; + int pos; +} Packet; + +typedef struct { + const unsigned char *data; + int maxlen; + int pos; +} ROPacket; + +static int write_uint32(Packet *p, ogg_uint32_t val) +{ + if (p->pos > p->maxlen - 4) { + return 0; + } + + p->data[p->pos] = (val) & 0xFF; + p->data[p->pos + 1] = (val >> 8) & 0xFF; + p->data[p->pos + 2] = (val >> 16) & 0xFF; + p->data[p->pos + 3] = (val >> 24) & 0xFF; + p->pos += 4; + return 1; +} + +static int write_uint16(Packet *p, ogg_uint16_t val) +{ + if (p->pos > p->maxlen - 2) { + return 0; + } + + p->data[p->pos] = (val) & 0xFF; + p->data[p->pos + 1] = (val >> 8) & 0xFF; + p->pos += 2; + return 1; +} + +static int write_chars(Packet *p, const unsigned char *str, int nb_chars) +{ + int i; + if (p->pos > p->maxlen - nb_chars) { + return 0; + } + for (i = 0; i < nb_chars; i++) { + p->data[p->pos++] = str[i]; + } + return 1; +} + +int opus_header_to_packet(const OpusHeader *h, unsigned char *packet, int len) +{ + int i; + Packet p; + unsigned char ch; + + p.data = packet; + p.maxlen = len; + p.pos = 0; + if (len < 19) { + return 0; + } + if (!write_chars(&p, (const unsigned char *)"OpusHead", 8)) { + return 0; + } + /* Version is 1 */ + ch = 1; + if (!write_chars(&p, &ch, 1)) { + return 0; + } + + ch = h->channels; + if (!write_chars(&p, &ch, 1)) { + return 0; + } + + if (!write_uint16(&p, h->preskip)) { + return 0; + } + + if (!write_uint32(&p, h->input_sample_rate)) { + return 0; + } + + if (!write_uint16(&p, h->gain)) { + return 0; + } + + ch = h->channel_mapping; + if (!write_chars(&p, &ch, 1)) { + return 0; + } + + if (h->channel_mapping != 0) { + ch = h->nb_streams; + if (!write_chars(&p, &ch, 1)) { + return 0; + } + + ch = h->nb_coupled; + if (!write_chars(&p, &ch, 1)) { + return 0; + } + + /* Multi-stream support */ + for (i = 0; i < h->channels; i++) { + if (!write_chars(&p, &h->stream_map[i], 1)) { + return 0; + } + } + } + + return p.pos; +} + +int opus_enc_alloc(opus_enc *opus) +{ + opus->header = (OpusHeader *)calloc(1, sizeof(OpusHeader)); + opus->header_data = (unsigned char *)calloc(1, 1024); + opus->tags = (unsigned char *)calloc(1, 1024); + opus->buffer = (unsigned char *)calloc(1, 2 * OPUS_FRAME_SIZE * sizeof(float)); + opus->last_pcm_packet = (float *)calloc(1, 2 * OPUS_FRAME_SIZE * sizeof(float)); + opus->granulepos = 0; + + memset(opus->song_title, 0, sizeof(opus->song_title)); + + return 0; +} + +int opus_enc_init(opus_enc *opus) +{ + int err; + int ret; + int bandwidth; + int audio_type; + + err = 0; + ret = OPUS_OK; + + opus->header->gain = 0; + opus->header->channels = opus->channel; + + if ((opus->bitrate < 8000) || (opus->bitrate > 510000)) { + opus->bitrate = DEFAULT_OPUS_BITRATE; + } + + if (opus->audio_type == 0) { + audio_type = OPUS_APPLICATION_AUDIO; + } + else { + audio_type = OPUS_APPLICATION_VOIP; + } + + opus->header->input_sample_rate = 48000; + opus->encoder = opus_encoder_create(opus->header->input_sample_rate, opus->channel, audio_type, &err); + if (opus->encoder == NULL) { + printf("Opus Encoder creation error: %s\n", opus_strerror(err)); + fflush(stdout); + return 1; + } + + ret |= opus_encoder_ctl(opus->encoder, OPUS_SET_BITRATE(opus->bitrate)); + + if (opus->bitrate_mode == 0) { // CBR + ret |= opus_encoder_ctl(opus->encoder, OPUS_SET_VBR(0)); + } + else { + ret |= opus_encoder_ctl(opus->encoder, OPUS_SET_VBR(1)); + } + + ret |= opus_encoder_ctl(opus->encoder, OPUS_SET_COMPLEXITY(10 - opus->quality)); + + switch (opus->bandwidth) { + case 0: + bandwidth = OPUS_BANDWIDTH_FULLBAND; // 20 kHz + break; + case 1: + bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND; // 12 kHz + break; + case 2: + bandwidth = OPUS_BANDWIDTH_WIDEBAND; // 8 kHz + break; + case 3: + bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; // 6 kHz + break; + case 4: + bandwidth = OPUS_BANDWIDTH_NARROWBAND; // 4 kHz + break; + default: + bandwidth = OPUS_BANDWIDTH_FULLBAND; + break; + } + + ret |= opus_encoder_ctl(opus->encoder, OPUS_SET_MAX_BANDWIDTH(bandwidth)); + + opus->last_bitrate = opus->bitrate; + + ret |= opus_encoder_ctl(opus->encoder, OPUS_GET_LOOKAHEAD(&opus->lookahead)); + opus->header->preskip = opus->lookahead; + if (opus->state == OPUS_STATE_NEW_STREAM) { + opus->header->preskip += OPUS_FRAME_SIZE - opus->lookahead; + } + + if (ret != OPUS_OK) { + return 1; + } + + opus->header_size = opus_header_to_packet(opus->header, opus->header_data, 100); + + int tags_offset = 0; + uint32_t len; + uint32_t num_comments = strlen(opus->song_title) > 0 ? 2 : 1; + + memcpy(opus->tags, "OpusTags", strlen("OpusTags")); + tags_offset += strlen("OpusTags"); + + len = strlen(opus_get_version_string()); + memcpy(opus->tags + tags_offset, &len, sizeof(len)); + tags_offset += sizeof(len); + + memcpy(opus->tags + tags_offset, opus_get_version_string(), strlen(opus_get_version_string())); + tags_offset += strlen(opus_get_version_string()); + + memcpy(opus->tags + tags_offset, &num_comments, sizeof(num_comments)); + tags_offset += sizeof(num_comments); + + len = strlen("ENCODER=") + strlen(PACKAGE_STRING); + memcpy(opus->tags + tags_offset, &len, sizeof(len)); + tags_offset += sizeof(len); + + memcpy(opus->tags + tags_offset, "ENCODER=", strlen("ENCODER=")); + tags_offset += strlen("ENCODER="); + + memcpy(opus->tags + tags_offset, PACKAGE_STRING, strlen(PACKAGE_STRING)); + tags_offset += strlen(PACKAGE_STRING); + + len = strlen(opus->song_title); + if (len > 0) { + memcpy(opus->tags + tags_offset, &len, sizeof(len)); + tags_offset += sizeof(len); + + memcpy(opus->tags + tags_offset, opus->song_title, len); + tags_offset += len; + } + + opus->tags_size = tags_offset; + + /* + int32_t val; + + opus_encoder_ctl (opus->encoder, OPUS_GET_BITRATE(&val)); + printf("OPUS bitrate: %d\n", val); + + opus_encoder_ctl (opus->encoder, OPUS_GET_COMPLEXITY(&val)); + printf("OPUS QUALITY: %d\n", val); + + opus_encoder_ctl (opus->encoder, OPUS_GET_APPLICATION(&val)); + printf("OPUS audio_type: %d\n", opus->audio_type ); + + opus_encoder_ctl (opus->encoder, OPUS_GET_MAX_BANDWIDTH(&val)); + printf("OPUS bandwidth: %d\n", val); + + opus_encoder_ctl (opus->encoder, OPUS_GET_VBR(&val)); + printf("OPUS VBR: %d\n\n", val); + */ + + // printf("OPUS bitrate: %d\n", opus->bitrate); + + return 0; +} + +// This function needs to be called before +// every connection +void opus_enc_write_header(opus_enc *opus) +{ + ogg_packet op; + + ogg_stream_clear(&opus->os); + ogg_stream_init(&opus->os, rand()); + opus_encoder_ctl(opus->encoder, OPUS_RESET_STATE); + + op.b_o_s = 1; + op.e_o_s = 0; + op.granulepos = 0; + op.packetno = 0; + op.packet = opus->header_data; + op.bytes = opus->header_size; + ogg_stream_packetin(&opus->os, &op); + + op.b_o_s = 0; + op.e_o_s = 0; + op.granulepos = 0; + op.packetno = opus->os.packetno; + op.packet = opus->tags; + op.bytes = opus->tags_size; + ogg_stream_packetin(&opus->os, &op); +} + +void opus_update_song_title(opus_enc *opus, char *song_title) +{ + snprintf(opus->song_title, sizeof(opus->song_title), "TITLE=%s", song_title); + opus->state = OPUS_STATE_NEW_SONG_AVAILABLE; +} + +int opus_enc_reinit(opus_enc *opus) +{ + opus_enc_close(opus); + return opus_enc_init(opus); +} + +int opus_enc_encode(opus_enc *opus, float *pcm_buf, char *enc_buf) +{ + int w = 0; + ogg_packet op; + + if (opus->encoder == NULL) { + // printf("Opus Encoder NULL wtf?\n"); + return 0; + } + + // Write header + while (ogg_stream_flush(&opus->os, &opus->og) != 0) { + memcpy(enc_buf + w, opus->og.header, opus->og.header_len); + w += opus->og.header_len; + memcpy(enc_buf + w, opus->og.body, opus->og.body_len); + w += opus->og.body_len; + } + + if (opus->last_bitrate != opus->bitrate) { + if ((opus->bitrate < 9600) || (opus->bitrate > 320000)) { + opus->bitrate = DEFAULT_OPUS_BITRATE; + } + opus_encoder_ctl(opus->encoder, OPUS_SET_BITRATE(opus->bitrate)); + opus->last_bitrate = opus->bitrate; + } + if (opus->state == OPUS_STATE_NEW_STREAM) { + opus_encoder_ctl(opus->encoder, OPUS_SET_PREDICTION_DISABLED(1)); + } + else { + opus_encoder_ctl(opus->encoder, OPUS_SET_PREDICTION_DISABLED(0)); + } + + opus->granulepos += OPUS_FRAME_SIZE; + + // At the end of an Opus stream/file, "opus->lookahead" (312) samples are missing on the output. + // Therefore we save the pcm data of the last opus frame here and inject it at + // the beginning of the next stream/file. + // Because an Opus frame contains always OPUS_FRAME_SIZE samples the decoder needs to skip the first + // OPUS_FRAME_SIZE - opus->lookahead (960 - 312) samples of the first Opus frame. Otherwise duplicate audio + // pcm data would be played back. + // This is done be setting opus->header->preskip to the appropriate value in opus_enc_init() when the new stream/file + // gets inizialized. + // This way we can create gapless streams and recordings if file splitting is active. + if (opus->state == OPUS_STATE_LAST_FRAME) { + memcpy(opus->last_pcm_packet, pcm_buf, opus->channel * OPUS_FRAME_SIZE * sizeof(float)); + op.e_o_s = 1; + } + else { + op.e_o_s = 0; + } + + opus->buffer_len = opus_encode_float(opus->encoder, pcm_buf, OPUS_FRAME_SIZE, opus->buffer, 2 * OPUS_FRAME_SIZE * sizeof(float)); + + op.b_o_s = 0; + op.granulepos = opus->granulepos; + op.packetno = opus->os.packetno; + op.packet = opus->buffer; + op.bytes = opus->buffer_len; + + ogg_stream_packetin(&opus->os, &op); + + while (ogg_stream_flush(&opus->os, &opus->og) != 0) { + memcpy(enc_buf + w, opus->og.header, opus->og.header_len); + w += opus->og.header_len; + memcpy(enc_buf + w, opus->og.body, opus->og.body_len); + w += opus->og.body_len; + } + + switch (opus->state) { + case OPUS_STATE_LAST_FRAME: + opus->state = OPUS_STATE_NEW_STREAM; + break; + case OPUS_STATE_NEW_STREAM: + opus->state = OPUS_STATE_NORMAL_FRAME; + break; + } + + return w; +} + +int opus_enc_flush(opus_enc *opus, char *enc_buf) +{ + int w; + float *flush_buf = (float *)calloc(OPUS_FRAME_SIZE, opus->channel * sizeof(float)); + w = opus_enc_encode(opus, flush_buf, enc_buf); + + return w; +} + +void opus_enc_close(opus_enc *opus) +{ + opus->granulepos = 0; + ogg_stream_clear(&opus->os); + opus_encoder_destroy(opus->encoder); +} + +int opus_enc_get_samplerate(opus_enc *opus) +{ + int32_t val; + opus_encoder_ctl(opus->encoder, OPUS_GET_SAMPLE_RATE(&val)); + + return val; +} + +// Currently unusedint opus_enc_get_samplerate(opus_enc *opus); +/* + +bool opus_enc_is_valid_srate(int samplerate) +{ + int i; + int valid_srates[] = {8000, 12000, 16000, 24000, 48000}; + + for (i = 0; i < 5; i++) + { + if (samplerate == valid_srates[i]) { + return true; + } + } + + return false; +} + +int opus_enc_get_valid_srate(int samplerate) +{ + int i; + int valid_srates[] = {8000, 12000, 16000, 24000, 48000}; + + if (samplerate > 48000) { + return 48000; + } + + for (i = 0; i < 5; i++) { + if (samplerate < valid_srates[i]) { + return valid_srates[i]; + } + } + + return -1; +} +*/ diff --git a/src/opus_encode.h b/src/opus_encode.h new file mode 100644 index 0000000..5a30b5a --- /dev/null +++ b/src/opus_encode.h @@ -0,0 +1,107 @@ +// opus encoding functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef OPUS_ENCODE_H +#define OPUS_ENCODE_H + +#include +#include +#include + +#include "config.h" + +#define OPUS_ENC_TYPE_REC 0 +#define OPUS_ENC_TYPE_STREAM 1 + +#define OPUS_KEY_FRAME_OFFSET 50 + +#define OPUS_STATE_OK 0 +#define OPUS_STATE_NORMAL_FRAME 1 +#define OPUS_STATE_NEW_STREAM 2 +#define OPUS_STATE_LAST_FRAME 3 +#define OPUS_STATE_NEW_SONG_AVAILABLE 4 + +#define OPUS_FRAME_SIZE 960 // Must be multiple of 120 (120 = 2,5ms, 960 = 20ms) +// #define OPUS_FRAME_SIZE (960/2) // Must be multiple of 120 (120 = 2,5ms, 960 = 20ms) +#define DEFAULT_OPUS_BITRATE 128000 + +typedef struct { + int version; + int channels; /* Number of channels: 1..255 */ + int preskip; + ogg_uint32_t input_sample_rate; + int gain; /* in dB S7.8 should be zero whenever possible */ + int channel_mapping; + /* The rest is only used if channel_mapping != 0 */ + int nb_streams; + int nb_coupled; + unsigned char stream_map[255]; +} OpusHeader; + +struct opus_enc { + ogg_stream_state os; + ogg_page og; + ogg_packet op; + ogg_packet op_last; + OpusEncoder *encoder; + OpusHeader *header; + int lookahead; + unsigned char *header_data; + unsigned char *tags; + int tags_size; + int header_size; + + ogg_int64_t prev_ganule; + ogg_int64_t granulepos; + + int last_bitrate; + int bitrate; + int samplerate; + int channel; + int state; + int bitrate_mode; + int quality; + int audio_type; + int bandwidth; + + char song_title[256]; + + unsigned char *buffer; + int buffer_len; + float *last_pcm_packet; +}; + +enum { + OPUS_READY = 0, + OPUS_BUSY = 1, +}; + +int opus_header_to_packet(const OpusHeader *h, unsigned char *packet, int len); +int opus_enc_alloc(opus_enc *opus); +int opus_enc_init(opus_enc *opus); +int opus_enc_reinit(opus_enc *opus); + +void opus_enc_write_header(opus_enc *opus); +int opus_enc_encode(opus_enc *opus, float *pcm_buf, char *enc_buf); +int opus_enc_flush(opus_enc *opus, char *enc_buf); +void opus_enc_close(opus_enc *opus); + +bool opus_enc_is_valid_srate(int samplerate); +int opus_enc_get_valid_srate(int samplerate); +int opus_enc_get_samplerate(opus_enc *opus); + +void opus_update_song_title(opus_enc *opus, char *song_title); + +#endif diff --git a/src/parseconfig.cpp b/src/parseconfig.cpp new file mode 100644 index 0000000..2e3adc0 --- /dev/null +++ b/src/parseconfig.cpp @@ -0,0 +1,264 @@ +/* + * config file parser + * + */ + +// taken from camE http://linuxbrit.co.uk/camE/ + +#include +#include +#include +#include +#include // for fl_fopen(...) + +#include "parseconfig.h" + +struct CFG_ENTRIES { + unsigned int ent_count; + char **ent_names; + char **ent_values; +}; + +struct CFG_SECTIONS { + unsigned int sec_count; + char **sec_names; + struct CFG_ENTRIES **sec_entries; +}; + +/* ------------------------------------------------------------------------ */ + +static struct CFG_SECTIONS *c; + +/* ------------------------------------------------------------------------ */ + +enum { + ALLOC_SIZE = 16, +}; + +void cfg_free(void) +{ + unsigned int i, j; + struct CFG_ENTRIES *e; + + if (c == NULL) { + return; + } + + for (i = 0; i < c->sec_count; i++) { + e = c->sec_entries[i]; + printf("ent_count: %d\n", e->ent_count); + for (j = 0; j < e->ent_count; j++) { + printf("i,j: %d,%d ", i, j); + printf("name,value: %s,%s\n", e->ent_names[j], e->ent_values[j]); + free(e->ent_names[j]); + free(e->ent_values[j]); + } + + free(e->ent_names); + free(e->ent_values); + free(c->sec_entries[i]); + free(c->sec_names[i]); + } + + free(c->sec_names); + free(c->sec_entries); + + c = NULL; +} + +static struct CFG_SECTIONS *cfg_init_sections(void) +{ + struct CFG_SECTIONS *c; + c = (CFG_SECTIONS *)malloc(sizeof(struct CFG_SECTIONS)); + memset(c, 0, sizeof(struct CFG_SECTIONS)); + c->sec_names = (char **)malloc(ALLOC_SIZE * sizeof(char *)); + c->sec_names[0] = NULL; + c->sec_entries = (CFG_ENTRIES **)malloc(ALLOC_SIZE * sizeof(struct CFG_ENTRIES *)); + c->sec_entries[0] = NULL; + return c; +} + +static struct CFG_ENTRIES *cfg_init_entries(void) +{ + struct CFG_ENTRIES *e; + e = (CFG_ENTRIES *)malloc(sizeof(struct CFG_ENTRIES)); + memset(e, 0, sizeof(struct CFG_ENTRIES)); + e->ent_names = (char **)malloc(ALLOC_SIZE * sizeof(char *)); + e->ent_names[0] = NULL; + e->ent_values = (char **)malloc(ALLOC_SIZE * sizeof(char *)); + e->ent_values[0] = NULL; + return e; +} + +static struct CFG_ENTRIES *cfg_find_section(struct CFG_SECTIONS *c, const char *name) +{ + struct CFG_ENTRIES *e; + unsigned int i; + + for (i = 0; i < c->sec_count; i++) { + if (strcmp(c->sec_names[i], name) == 0) { + return c->sec_entries[i]; + } + } + + /* 404 not found => create a new one */ + if ((c->sec_count % ALLOC_SIZE) == (ALLOC_SIZE - 2)) { + c->sec_names = (char **)realloc(c->sec_names, (c->sec_count + 2 + ALLOC_SIZE) * sizeof(char *)); + c->sec_entries = (CFG_ENTRIES **)realloc(c->sec_entries, (c->sec_count + 2 + ALLOC_SIZE) * sizeof(struct CFG_ENTRIES *)); + } + e = cfg_init_entries(); + c->sec_names[c->sec_count] = strdup(name); + c->sec_entries[c->sec_count] = e; + c->sec_count++; + c->sec_names[c->sec_count] = NULL; + c->sec_entries[c->sec_count] = NULL; + return e; +} + +static void cfg_set_entry(struct CFG_ENTRIES *e, const char *name, const char *value) +{ + unsigned int i; + + for (i = 0; i < e->ent_count; i++) { + if (strcmp(e->ent_names[i], name) == 0) { + break; + } + } + if (i == e->ent_count) { + /* 404 not found => create a new one */ + if ((e->ent_count % ALLOC_SIZE) == (ALLOC_SIZE - 2)) { + e->ent_names = (char **)realloc(e->ent_names, (e->ent_count + 2 + ALLOC_SIZE) * sizeof(char *)); + e->ent_values = (char **)realloc(e->ent_values, (e->ent_count + 2 + ALLOC_SIZE) * sizeof(char *)); + } + e->ent_count++; + e->ent_names[e->ent_count] = NULL; + e->ent_values[e->ent_count] = NULL; + } + e->ent_names[i] = strdup(name); + e->ent_values[i] = strdup(value); +} + +/* ------------------------------------------------------------------------ */ + +int cfg_parse_file(const char *filename) +{ + struct CFG_ENTRIES *e = NULL; + char line[1024], tag[64], value[1021]; + FILE *fp; + int nr; + + if (c != NULL) { + cfg_free(); + } + + c = cfg_init_sections(); + if ((fp = fl_fopen(filename, "rb")) == NULL) { + return -1; + } + + nr = 0; + while (NULL != fgets(line, 1023, fp)) { + nr++; + if (line[0] == '\n' || line[0] == '#' || line[0] == '%' || line[0] == ';') { + continue; + } + if (1 == sscanf(line, "[%1020[^]]]", value)) { + /* section */ + e = cfg_find_section(c, value); + } + else if (2 == sscanf(line, " %63[^= ] = %1020[^\n]", tag, value)) { + /* foo = bar */ + if (NULL == e) { + fprintf(stderr, "%s:%d: error: no section\n", filename, nr); + } + else { + cfg_set_entry(e, tag, value); + } + } /*else { + // Huh ? + fprintf(stderr,"%s:%d: syntax error\n",filename,nr); + }*/ + } + fclose(fp); + return 0; +} + +/* ------------------------------------------------------------------------ */ + +char **cfg_list_sections(void) +{ + return c->sec_names; +} + +char **cfg_list_entries(const char *name) +{ + unsigned int i; + + for (i = 0; i < c->sec_count; i++) { + if (0 == strcmp(c->sec_names[i], name)) { + return c->sec_entries[i]->ent_names; + } + } + return NULL; +} + +char *cfg_get_str(const char *sec, const char *ent, const char *def_val) +{ + struct CFG_ENTRIES *e = NULL; + char *v = NULL; + unsigned int i; + + for (i = 0; i < c->sec_count; i++) { + if (strcmp(c->sec_names[i], sec) == 0) { + e = c->sec_entries[i]; + } + } + if (e == NULL) { + if (def_val == NULL) { + return NULL; + } + else { + v = (char *)malloc(strlen(def_val) + 1); + strcpy(v, def_val); + return v; + } + } + for (i = 0; i < e->ent_count; i++) { + if (strcmp(e->ent_names[i], ent) == 0) { + v = e->ent_values[i]; + } + } + if (v == NULL) { + if (def_val == NULL) { + return NULL; + } + else { + v = (char *)malloc(strlen(def_val) + 1); + strcpy(v, def_val); + return v; + } + } + return strdup(v); +} + +int cfg_get_int(const char *sec, const char *ent, const int def_val) +{ + char *val; + + val = cfg_get_str(sec, ent, NULL); + if (val == NULL) { + return def_val; + } + return atoi(val); +} + +float cfg_get_float(const char *sec, const char *ent, const float def_val) +{ + char *val; + + val = cfg_get_str(sec, ent, NULL); + if (val == NULL) { + return def_val; + } + return atof(val); +} diff --git a/src/parseconfig.h b/src/parseconfig.h new file mode 100644 index 0000000..b09e12f --- /dev/null +++ b/src/parseconfig.h @@ -0,0 +1,14 @@ +#ifndef PARSECONFIG_H +#define PARSECONFIG_H + +// taken from camE http://linuxbrit.co.uk/camE/ + +int cfg_parse_file(const char *filename); +char **cfg_list_sections(void); +char **cfg_list_entries(const char *name); +char *cfg_get_str(const char *sec, const char *ent, const char *def_val); +int cfg_get_int(const char *sec, const char *ent, const int def_val); +float cfg_get_float(const char *sec, const char *ent, const float def_val); +void cfg_free(void); + +#endif /* PARSECONFIG_H */ diff --git a/src/port_audio.cpp b/src/port_audio.cpp new file mode 100644 index 0000000..e7ccc60 --- /dev/null +++ b/src/port_audio.cpp @@ -0,0 +1,1564 @@ +// portaudio functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include +#include +#include + +#include +#include +#include + +#ifdef WIN32 +#include +#endif + +#include "gettext.h" +#include "config.h" + +#include "butt.h" +#include "cfg.h" +#include "port_audio.h" +#include "parseconfig.h" +#include "lame_encode.h" +#include "aac_encode.h" +#include "shoutcast.h" +#include "icecast.h" +#include "webrtc.h" +#include "strfuncs.h" +#include "wav_header.h" +#include "ringbuffer.h" +#include "vu_meter.h" +#include "flgui.h" +#include "fl_funcs.h" +#include "Fl_LED.h" +#include "dsp.hpp" +#include "util.h" +#include "atom.h" + +#define TEST_RESAMPLING 0 + +int pa_frames; + +char *encode_buf; +float *pa_pcm_buf; +float *pa_pcm_buf2; +float *pa_mixer_buf; +float *pa_mixer_buf2; +float *stream_buf; +float *record_buf; +int framepacket_size; +int framepacket_size2; +int samplerate_dev2; + +bool pa_new_frames; +bool reconnect; +bool silence_detected; +bool signal_detected; +bool reset_streaming_compressor = false; +bool reset_recording_compressor = false; + +int num_of_input_channels; +int num_of_input_channels2; + +int vu_level_type = 0; // 0 = Streaming, 1 = Recording + +bool next_file; +FILE *next_fd; + +ringbuf_t rec_rb; +ringbuf_t stream_rb; +ringbuf_t pa_pcm_rb; +ringbuf_t pa_pcm2_rb; + +SRC_STATE *srconv_state_opus_stream = NULL; +SRC_STATE *srconv_state_opus_record = NULL; +SRC_STATE *srconv_state_dev2 = NULL; +SRC_DATA srconv_opus_stream; +SRC_DATA srconv_opus_record; +SRC_DATA srconv_dev2; + +ATOM_NEW_COND(stream_cond); +ATOM_NEW_COND(rec_cond); + +ATOM_NEW_INT(close_mixer_thread, 0); + +pthread_t rec_thread_detached; +pthread_t stream_thread_detached; +pthread_t mixer_thread_joinable; + +PaStream *stream; +PaStream *stream2; + +DSPEffects *streaming_dsp = NULL; +DSPEffects *recording_dsp = NULL; + +void snd_reset_streaming_compressor(void) +{ + reset_streaming_compressor = true; +} + +void snd_reset_recording_compressor(void) +{ + reset_recording_compressor = true; +} + +void snd_set_vu_level_type(int type) +{ + vu_level_type = type; + vu_init(); // Reset peak indicators +} + +int snd_init(void) +{ + char info_buf[256]; + + PaError p_err; + if ((p_err = Pa_Initialize()) != paNoError) { + snprintf(info_buf, sizeof(info_buf), _("PortAudio init failed:\n%s\n"), Pa_GetErrorText(p_err)); + DEBUG_LOG(info_buf); + fl_alert("%s", info_buf); + return 1; + } + + reconnect = false; + silence_detected = false; + return 0; +} + +int snd_reopen_streams(void) +{ + snd_close_streams(); + if ((snd_open_streams() != 0)) { + return 1; + } + return 0; +} + +void snd_init_dsp(void) +{ + if (streaming_dsp != NULL) { + delete streaming_dsp; + streaming_dsp = NULL; + } + + if (recording_dsp != NULL) { + delete recording_dsp; + recording_dsp = NULL; + } + + streaming_dsp = new DSPEffects(pa_frames, cfg.audio.channel, cfg.audio.samplerate); + recording_dsp = new DSPEffects(pa_frames, cfg.audio.channel, cfg.audio.samplerate); +} + +int snd_open_streams(void) +{ + int ret = 0; + int flag; + char info_buf[256]; + + PaDeviceIndex pa_dev_id; + PaStreamParameters pa_params; + PaStreamParameters pa_params2; + PaError pa_err; + const PaDeviceInfo *pa_dev_info; + + if (cfg.audio.dev_count == 0) { + print_info(_("ERROR: no sound device with input channels found"), 1); + return 1; + } + + pa_frames = round((cfg.audio.buffer_ms / 1000.0) * cfg.audio.samplerate); + + if (cfg.audio.dev_remember == REMEMBER_BY_NAME) { + cfg.audio.dev_num = snd_get_dev_num_by_name(cfg.audio.dev_name); + } + + if (cfg.audio.dev_num == -1) { + cfg.audio.dev_num = 0; + } + + pa_dev_id = cfg.audio.pcm_list[cfg.audio.dev_num]->dev_id; + + pa_dev_info = Pa_GetDeviceInfo(pa_dev_id); + if (pa_dev_info == NULL) { + snprintf(info_buf, sizeof(info_buf), _("Error getting device Info (%d)"), pa_dev_id); + print_info(info_buf, 1); + return 1; + } + + num_of_input_channels = pa_dev_info->maxInputChannels; + if (num_of_input_channels == 1) { + cfg.audio.left_ch = 1; + cfg.audio.right_ch = 1; + } + else if ((cfg.audio.left_ch > num_of_input_channels) || (cfg.audio.right_ch > num_of_input_channels)) { + cfg.audio.left_ch = 1; + cfg.audio.right_ch = 2; + } + + framepacket_size = pa_frames * cfg.audio.channel; + + pa_pcm_buf = (float *)malloc(2 * framepacket_size * sizeof(float)); + pa_mixer_buf = (float *)malloc(2 * framepacket_size * sizeof(float)); + stream_buf = (float *)malloc(2 * framepacket_size * sizeof(float)); + record_buf = (float *)malloc(2 * framepacket_size * sizeof(float)); + encode_buf = (char *)malloc(2 * framepacket_size * sizeof(char)); + + srconv_opus_stream.data_in = stream_buf; + srconv_opus_record.data_in = record_buf; + srconv_opus_stream.data_out = (float *)malloc(32 * framepacket_size * sizeof(float)); + srconv_opus_record.data_out = (float *)malloc(32 * framepacket_size * sizeof(float)); + srconv_dev2.data_out = (float *)malloc(32 * framepacket_size * sizeof(float)); + + rb_init(&rec_rb, 16 * framepacket_size * sizeof(float)); + rb_init(&stream_rb, 16 * framepacket_size * sizeof(float)); + rb_init(&pa_pcm_rb, 16 * framepacket_size * sizeof(float)); + + pa_params.device = pa_dev_id; + pa_params.channelCount = pa_dev_info->maxInputChannels; + pa_params.sampleFormat = paFloat32; + pa_params.suggestedLatency = pa_dev_info->defaultHighInputLatency; + pa_params.hostApiSpecificStreamInfo = NULL; + + pa_err = Pa_IsFormatSupported(&pa_params, NULL, cfg.audio.samplerate); + if (pa_err != paFormatIsSupported) { + if (pa_err == paInvalidSampleRate) { + snprintf(info_buf, sizeof(info_buf), + _("Samplerate not supported: %dHz\n" + "Using default samplerate: %dHz"), + cfg.audio.samplerate, (int)pa_dev_info->defaultSampleRate); + print_info(info_buf, 1); + + if (Pa_IsFormatSupported(&pa_params, NULL, pa_dev_info->defaultSampleRate) != paFormatIsSupported) { + print_info("FAILED", 1); + ret = 1; + goto cleanup1; + } + else { + cfg.audio.samplerate = (int)pa_dev_info->defaultSampleRate; + update_samplerates_list(); + update_codec_samplerates(); + } + } + else { + snprintf(info_buf, sizeof(info_buf), _("PA: Format not supported: %s\n"), Pa_GetErrorText(pa_err)); + print_info(info_buf, 1); + ret = 1; + goto cleanup1; + } + } + + flag = cfg.audio.disable_dithering == 0 ? paNoFlag : paDitherOff; + pa_err = Pa_OpenStream(&stream, &pa_params, NULL, cfg.audio.samplerate, pa_frames, flag, snd_callback, NULL); + if (pa_err != paNoError) { + snprintf(info_buf, sizeof(info_buf), _("error opening sound device: %s"), Pa_GetErrorText(pa_err)); + print_info(info_buf, 1); + ret = 1; + goto cleanup1; + } + + // Secondary device + if (cfg.audio.dev2_num >= 0) { + int frames_in_dev2; + if (cfg.audio.dev_remember == REMEMBER_BY_NAME) { + cfg.audio.dev2_num = snd_get_dev_num_by_name(cfg.audio.dev2_name); + } + + if (cfg.audio.dev2_num == -1) { + cfg.audio.dev2_num = 0; + } + + pa_dev_id = cfg.audio.pcm_list[cfg.audio.dev2_num]->dev_id; + + pa_dev_info = Pa_GetDeviceInfo(pa_dev_id); + if (pa_dev_info == NULL) { + snprintf(info_buf, sizeof(info_buf), _("Error getting device Info (%d)"), pa_dev_id); + print_info(info_buf, 1); + ret = 1; + goto cleanup1; + } + + num_of_input_channels2 = pa_dev_info->maxInputChannels; + if (num_of_input_channels2 == 1) { + cfg.audio.left_ch2 = 1; + cfg.audio.right_ch2 = 1; + } + else if ((cfg.audio.left_ch2 > num_of_input_channels2) || (cfg.audio.right_ch2 > num_of_input_channels2)) { + cfg.audio.left_ch2 = 1; + cfg.audio.right_ch2 = 2; + } + + pa_params2.device = pa_dev_id; + pa_params2.channelCount = num_of_input_channels2; + pa_params2.sampleFormat = paFloat32; + pa_params2.suggestedLatency = pa_dev_info->defaultHighInputLatency; + pa_params2.hostApiSpecificStreamInfo = NULL; + + pa_err = Pa_IsFormatSupported(&pa_params2, NULL, cfg.audio.samplerate); +#if TEST_RESAMPLING == 1 + if (pa_err == paFormatIsSupported) { + if (pa_err != paInvalidSampleRate) { +#else + if (pa_err != paFormatIsSupported) { + if (pa_err == paInvalidSampleRate) { +#endif + +#if TEST_RESAMPLING == 1 + if (Pa_IsFormatSupported(&pa_params2, NULL, 44100) != paFormatIsSupported) { +#else + // Use default sample rate of secondary audio device and resample to cfg.audio.samplerate + if (Pa_IsFormatSupported(&pa_params2, NULL, pa_dev_info->defaultSampleRate) != paFormatIsSupported) { +#endif + print_info(_("The selected secondary audio device can not be used"), 1); + ret = 1; + goto cleanup1; + } + else { +#if TEST_RESAMPLING == 1 + samplerate_dev2 = 44100; +#else + samplerate_dev2 = (int)pa_dev_info->defaultSampleRate; +#endif + if (srconv_state_dev2 != NULL) { + src_delete(srconv_state_dev2); + srconv_state_dev2 = NULL; + } + + srconv_state_dev2 = src_new(cfg.audio.resample_mode, cfg.audio.channel, &pa_err); + if (srconv_state_dev2 == NULL) { + print_info(_("ERROR: Could not initialize samplerate converter"), 0); + ret = 1; + goto cleanup1; + } + + frames_in_dev2 = (cfg.audio.buffer_ms * samplerate_dev2) / 1000; + srconv_dev2.src_ratio = (float)cfg.audio.samplerate / samplerate_dev2; + srconv_dev2.input_frames = frames_in_dev2; + srconv_dev2.output_frames = pa_frames; + srconv_dev2.end_of_input = 0; + + snprintf(info_buf, sizeof(info_buf), _("Samplerate of secondary device is resampled from %dHz to %dHz\n"), samplerate_dev2, + cfg.audio.samplerate); + print_info(info_buf, 1); + } + } + else { + snprintf(info_buf, sizeof(info_buf), _("PA: Format not supported: %s\n"), Pa_GetErrorText(pa_err)); + print_info(info_buf, 1); + ret = 1; + goto cleanup1; + } + } + else { + frames_in_dev2 = pa_frames; + samplerate_dev2 = cfg.audio.samplerate; + } + + framepacket_size2 = frames_in_dev2 * num_of_input_channels2; + pa_pcm_buf2 = (float *)malloc(2 * framepacket_size2 * sizeof(float)); + pa_mixer_buf2 = (float *)malloc(2 * framepacket_size2 * sizeof(float)); + rb_init(&pa_pcm2_rb, 16 * framepacket_size2 * sizeof(float)); + srconv_dev2.data_in = pa_pcm_buf2; + + int flag = cfg.audio.disable_dithering == 0 ? paNoFlag : paDitherOff; + pa_err = Pa_OpenStream(&stream2, &pa_params2, NULL, samplerate_dev2, frames_in_dev2, flag, snd_callback2, NULL); + + if (pa_err != paNoError) { + snprintf(info_buf, sizeof(info_buf), _("error opening secondary sound device: %s"), Pa_GetErrorText(pa_err)); + print_info(info_buf, 1); + ret = 1; + goto cleanup2; + } + + Pa_StartStream(stream2); + } + + Pa_StartStream(stream); + + snd_init_dsp(); + snd_start_mixer_thread(); + + g_vu_meter_timer_is_active = 1; + Fl::add_timeout(0.01, &vu_meter_timer); + + return 0; + +cleanup2: + free(pa_pcm_buf2); + free(pa_mixer_buf2); + rb_free(&pa_pcm2_rb); + +cleanup1: + if (Pa_IsStreamStopped(&stream)) { // Primary stream has been opened but not started yet + Pa_CloseStream(&stream); + } + free(pa_pcm_buf); + free(pa_mixer_buf); + free(stream_buf); + free(record_buf); + free(encode_buf); + free(srconv_opus_stream.data_out); + free(srconv_opus_record.data_out); + free(srconv_dev2.data_out); + rb_free(&rec_rb); + rb_free(&stream_rb); + rb_free(&pa_pcm_rb); + + return ret; +} + +// this function is called by PortAudio when new audio data arrived +int snd_callback(const void *input, void *output, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, + void *userData) +{ + float *pcm_input = (float *)input; + + if (statusFlags != 0) { + printf("1 status: %lu\n", statusFlags); + } + + if (cfg.audio.channel == 1) { // User has selected mono + for (uint32_t i = 0; i < frameCount; i++) { + if (num_of_input_channels == 1) { // If the device has only one channel use that channel as mono input source + pa_pcm_buf[i] = pcm_input[i]; + } + else { // If the device has more than one channel, average the user selected left and right channel into a mono channel + float left_sample, right_sample; + float mono_sample; + left_sample = pcm_input[num_of_input_channels * i + (cfg.audio.left_ch - 1)]; + right_sample = pcm_input[num_of_input_channels * i + (cfg.audio.right_ch - 1)]; + mono_sample = (left_sample + right_sample) / 2.0; + pa_pcm_buf[i] = mono_sample; + } + } + rb_write(&pa_pcm_rb, (char *)pa_pcm_buf, (int)(1 * frameCount * sizeof(float))); + } + else { // User has selected stereo + for (uint32_t i = 0; i < frameCount; i++) { + if (num_of_input_channels == 1) { // If the device has only one channel, use the same channel for left and right + pa_pcm_buf[2 * i] = pcm_input[i]; + pa_pcm_buf[2 * i + 1] = pcm_input[i]; + } + else { // If the device has more than one channel, use the selected left and right channel as input source + pa_pcm_buf[2 * i] = pcm_input[num_of_input_channels * i + (cfg.audio.left_ch - 1)]; + pa_pcm_buf[2 * i + 1] = pcm_input[num_of_input_channels * i + (cfg.audio.right_ch - 1)]; + } + } + if (rb_write(&pa_pcm_rb, (char *)pa_pcm_buf, (int)(2 * frameCount * sizeof(float))) != 0) { + printf("Write to pa_pcm_rb failed\n"); + } + } + + /* + samplerate_out = cfg.audio.samplerate; + + if (dsp->hasToProcessSamples()) { + if (reset_compressor == true) { + dsp->reset_compressor(); + reset_compressor = false; + } + + dsp->processSamples(pa_pcm_buf); + } + + if (streaming) { + if ((!strcmp(cfg.audio.codec, "opus")) && (cfg.audio.samplerate != 48000)) { + convert_stream = true; + samplerate_out = 48000; + } + + if (convert_stream == true) { + srconv_stream.end_of_input = 0; + srconv_stream.src_ratio = (float)samplerate_out / cfg.audio.samplerate; + srconv_stream.input_frames = frameCount; + srconv_stream.output_frames = frameCount * cfg.audio.channel * (srconv_stream.src_ratio + 1) * sizeof(float); + + memcpy((float *)srconv_stream.data_in, pa_pcm_buf, frameCount * cfg.audio.channel * sizeof(float)); + + // The actual resample process + src_process(srconv_state_stream, &srconv_stream); + + memcpy(stream_buf, srconv_stream.data_out, srconv_stream.output_frames_gen * cfg.audio.channel * sizeof(float)); + + rb_write(&stream_rb, (char *)stream_buf, srconv_stream.output_frames_gen * cfg.audio.channel * sizeof(float)); + } + else { + rb_write(&stream_rb, (char *)pa_pcm_buf, frameCount * cfg.audio.channel * sizeof(float)); + } + + atom_cond_signal(&stream_cond); + } + + if (recording) { + if ((!strcmp(cfg.rec.codec, "opus")) && (cfg.audio.samplerate != 48000)) { + convert_record = true; + samplerate_out = 48000; + } + + if (convert_record == true) { + srconv_record.end_of_input = 0; + srconv_record.src_ratio = (float)samplerate_out / cfg.audio.samplerate; + srconv_record.input_frames = frameCount; + srconv_record.output_frames = frameCount * cfg.audio.channel * (srconv_record.src_ratio + 1) * sizeof(float); + + memcpy((float *)srconv_record.data_in, pa_pcm_buf, frameCount * cfg.audio.channel * sizeof(float)); + + // The actual resample process + src_process(srconv_state_record, &srconv_record); + + memcpy(record_buf, srconv_record.data_out, srconv_record.output_frames_gen * cfg.audio.channel * sizeof(float)); + + rb_write(&rec_rb, (char *)record_buf, srconv_record.output_frames_gen * cfg.audio.channel * sizeof(float)); + } + else { + rb_write(&rec_rb, (char *)pa_pcm_buf, frameCount * cfg.audio.channel * sizeof(float)); + } + + atom_cond_signal(&rec_cond); + } + + // tell snd_update_vu() that there is new audio data + pa_new_frames = 1; +*/ + + return paContinue; +} + +int snd_callback2(const void *input, void *output, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, + void *userData) +{ + float *pcm_input = (float *)input; + if (statusFlags != 0) { + printf("2 status: %lu\n", statusFlags); + } + + if (cfg.audio.channel == 1) { // User has selected mono + for (uint32_t i = 0; i < frameCount; i++) { + if (num_of_input_channels2 == 1) { // If the device has only one channel use that channel as mono input source + pa_pcm_buf2[i] = pcm_input[i]; + } + else { // If the device has more than one channel, average the user selected left and right channel into a mono channel + float left_sample, right_sample; + float mono_sample; + left_sample = pcm_input[num_of_input_channels2 * i + (cfg.audio.left_ch2 - 1)]; + right_sample = pcm_input[num_of_input_channels2 * i + (cfg.audio.right_ch2 - 1)]; + mono_sample = (left_sample + right_sample) / 2.0; + pa_pcm_buf2[i] = mono_sample; + } + } + } + else { // User has selected stereo + for (uint32_t i = 0; i < frameCount; i++) { + if (num_of_input_channels2 == 1) { // If the device has only one channel, use the same channel for left and right + pa_pcm_buf2[2 * i] = pcm_input[i]; + pa_pcm_buf2[2 * i + 1] = pcm_input[i]; + } + else { // If the device has more than one channel, use the selected left and right channel as input source + pa_pcm_buf2[2 * i] = pcm_input[num_of_input_channels2 * i + (cfg.audio.left_ch2 - 1)]; + pa_pcm_buf2[2 * i + 1] = pcm_input[num_of_input_channels2 * i + (cfg.audio.right_ch2 - 1)]; + } + } + } + + if (samplerate_dev2 != cfg.audio.samplerate) { + // srconv_dev2.input_frames is equal to frameCount + // srconv_dev2.output_frames_gen is equal to pa_frames + src_process(srconv_state_dev2, &srconv_dev2); + memcpy(pa_pcm_buf2, srconv_dev2.data_out, srconv_dev2.output_frames_gen * cfg.audio.channel * sizeof(float)); + } + + if (rb_write(&pa_pcm2_rb, (char *)pa_pcm_buf2, pa_frames * cfg.audio.channel * sizeof(float)) != 0) { + printf("Write to pa_pcm_rb2 failed\n"); + } + + return paContinue; +} + +void snd_start_streaming_thread(void) +{ + atom_cond_init(&stream_cond); + + kbytes_sent = 0; + streaming = 1; + if (pthread_create(&stream_thread_detached, NULL, snd_stream_thread, NULL) != 0) { + print_info("Fatal error: Could not launch streaming thread. Please restart BUTT", 1); + streaming = 0; + return; + } +} + +void snd_start_mixer_thread(void) +{ + atom_set_int(&close_mixer_thread, 0); + rb_clear(&pa_pcm_rb); + + if (cfg.audio.dev2_num >= 0) { + rb_clear(&pa_pcm2_rb); + } + + snd_reset_samplerate_conv(SND_STREAM); + snd_reset_samplerate_conv(SND_REC); + + if (pthread_create(&mixer_thread_joinable, NULL, snd_mixer_thread, NULL) != 0) { + print_info("Fatal error: Could not launch mixer thread. Please restart BUTT", 1); + return; + } +} + +void snd_stop_mixer_thread(void) +{ + atom_set_int(&close_mixer_thread, 1); + pthread_join(mixer_thread_joinable, NULL); +} + +void *snd_mixer_thread(void *data) +{ + int frame_size = pa_frames * cfg.audio.channel * sizeof(float); + int frame_len = frame_size / sizeof(float); + + int filled1, filled2; + + for (;;) { + if (cfg.audio.dev2_num < 0) { // Only primary audio device is active + do { + filled1 = rb_filled(&pa_pcm_rb); + if (atom_get_int(&close_mixer_thread) == 1) { + break; + } + Pa_Sleep(1); // ms + } while (filled1 < frame_size); + + if (atom_get_int(&close_mixer_thread) == 1) { + break; + } + + rb_read_len(&pa_pcm_rb, (char *)pa_mixer_buf, frame_size); + + // Apply gain to primary device + for (int i = 0; i < frame_len; i++) { + // Apply gain to primary device + if (cfg.mixer.primary_device_muted == 1) { + pa_mixer_buf[i] = 0; + } + else if (cfg.mixer.primary_device_gain != 1) { + pa_mixer_buf[i] *= cfg.mixer.primary_device_gain; + } + + if (cfg.mixer.cross_fader != 0) { + pa_mixer_buf[i] *= cfg.mixer.primary_X_fader; + } + } + } + else { // Secondary audio device is active as well + do { + filled1 = rb_filled(&pa_pcm_rb); + filled2 = rb_filled(&pa_pcm2_rb); + if (atom_get_int(&close_mixer_thread) == 1) { + break; + } + Pa_Sleep(1); // ms + } while (filled1 < frame_size || filled2 < frame_size); + + if (atom_get_int(&close_mixer_thread) == 1) { + break; + } + + /* cnt++; + if (cnt == 21) { + printf("filled1: %d\nfilled2: %d\n\n", filled1, filled2); + cnt = 0; + }*/ + + rb_read_len(&pa_pcm_rb, (char *)pa_mixer_buf, frame_size); + rb_read_len(&pa_pcm2_rb, (char *)pa_mixer_buf2, frame_size); + + for (int i = 0; i < frame_len; i++) { + // Apply gain to primary device + if (cfg.mixer.primary_device_muted == 1) { + pa_mixer_buf[i] = 0; + } + else if (cfg.mixer.primary_device_gain != 1) { + pa_mixer_buf[i] *= cfg.mixer.primary_device_gain; + } + + // Apply gain to secondary device + if (cfg.mixer.secondary_device_muted == 1) { + pa_mixer_buf2[i] = 0; + } + else if (cfg.mixer.secondary_device_gain != 1) { + pa_mixer_buf2[i] *= cfg.mixer.secondary_device_gain; + } + + if (cfg.mixer.cross_fader != 0) { + pa_mixer_buf[i] *= cfg.mixer.primary_X_fader; + pa_mixer_buf2[i] *= cfg.mixer.secondary_X_fader; + } + + pa_mixer_buf[i] = (pa_mixer_buf[i] + pa_mixer_buf2[i]); + } + } + + // To my future self: Do not move this part into the "if (streaming)" block below + // because the VU meter displays the contents of "stream_buf" + memcpy(stream_buf, pa_mixer_buf, frame_size); + if (cfg.mixer.streaming_gain != 1) { + for (int i = 0; i < frame_len; i++) { + stream_buf[i] *= cfg.mixer.streaming_gain; + } + } + + streaming_dsp->eq_active = cfg.dsp.equalizer_stream; + streaming_dsp->drc_active = cfg.dsp.compressor_stream; + if (streaming_dsp->hasToProcessSamples()) { + // printf("stream: \n"); + if (reset_streaming_compressor == true) { + streaming_dsp->reset_compressor(); + reset_streaming_compressor = false; + } + streaming_dsp->processSamples(stream_buf); + } + if (streaming) { + if ((!strcmp(cfg.audio.codec, "opus")) && (cfg.audio.samplerate != 48000)) { + srconv_opus_stream.data_in = stream_buf; + src_process(srconv_state_opus_stream, &srconv_opus_stream); + rb_write(&stream_rb, (char *)srconv_opus_stream.data_out, (int)(srconv_opus_stream.output_frames_gen * cfg.audio.channel * sizeof(float))); + } + else { + rb_write(&stream_rb, (char *)stream_buf, frame_size); + } + atom_cond_signal(&stream_cond); + } + + memcpy(record_buf, pa_mixer_buf, frame_size); + if (cfg.mixer.recording_gain != 1) { + for (int i = 0; i < frame_len; i++) { + record_buf[i] *= cfg.mixer.recording_gain; + } + } + + recording_dsp->eq_active = cfg.dsp.equalizer_rec; + recording_dsp->drc_active = cfg.dsp.compressor_rec; + if (recording_dsp->hasToProcessSamples()) { + // printf("rec: \n"); + if (reset_recording_compressor == true) { + recording_dsp->reset_compressor(); + reset_recording_compressor = false; + } + recording_dsp->processSamples(record_buf); + } + + if (recording) { + if ((!strcmp(cfg.rec.codec, "opus")) && (cfg.audio.samplerate != 48000)) { + src_process(srconv_state_opus_record, &srconv_opus_record); + rb_write(&rec_rb, (char *)srconv_opus_record.data_out, (int)(srconv_opus_record.output_frames_gen * cfg.audio.channel * sizeof(float))); + } + else { + rb_write(&rec_rb, (char *)record_buf, frame_size); + } + atom_cond_signal(&rec_cond); + } + + pa_new_frames = 1; + } + + return NULL; +} + +void *snd_stream_thread(void *data) +{ + int sent; + int rb_bytes_read; + int encode_bytes_read = 0; + int bytes_to_read; + + char *enc_buf = (char *)malloc(stream_rb.size * sizeof(char) * 10); + char *audio_buf = (char *)malloc(stream_rb.size * sizeof(char) * 10); + + int (*xc_send)(char *buf, int buf_len) = NULL; + + static int new_stream = 0; + + if (cfg.srv[cfg.selected_srv]->type == ICECAST) { + xc_send = &ic_send; + } +#ifdef HAVE_LIBDATACHANNEL + else if (cfg.srv[cfg.selected_srv]->type == WEBRTC) { + xc_send = &webrtc_send; + } +#endif + else { // Shoutcast + xc_send = &sc_send; + } + + set_max_thread_priority(); + while (connected) { + atom_cond_wait(&stream_cond); + if (!connected) { + break; + } + + if (!strcmp(cfg.audio.codec, "opus")) { + // Read always chunks of OPUS_FRAME_SIZE frames from the audio ringbuffer to be + // compatible with OPUS + bytes_to_read = OPUS_FRAME_SIZE * cfg.audio.channel * sizeof(float); + + while ((rb_filled(&stream_rb)) >= bytes_to_read) { + if (opus_stream.state == OPUS_STATE_NEW_SONG_AVAILABLE) { + opus_stream.state = OPUS_STATE_LAST_FRAME; + } + + if (opus_stream.state == OPUS_STATE_NEW_STREAM) { + opus_enc_reinit(&opus_stream); + opus_enc_write_header(&opus_stream); + encode_bytes_read = opus_enc_encode(&opus_stream, opus_stream.last_pcm_packet, enc_buf); + if (xc_send(enc_buf, encode_bytes_read) == -1) { + connected = 0; + break; + } + } + + rb_read_len(&stream_rb, audio_buf, bytes_to_read); + encode_bytes_read = opus_enc_encode(&opus_stream, (float *)audio_buf, enc_buf); + + if (xc_send(enc_buf, encode_bytes_read) == -1) { + connected = 0; + } + else { + kbytes_sent += encode_bytes_read / 1024.0; + } + } + } +#ifdef HAVE_LIBFDK_AAC + else if (!strcmp(cfg.audio.codec, "aac")) { + bytes_to_read = aac_stream.info.frameLength * cfg.audio.channel * sizeof(float); + while ((rb_filled(&stream_rb)) >= bytes_to_read) { + rb_read_len(&stream_rb, audio_buf, bytes_to_read); + encode_bytes_read = + aac_enc_encode(&aac_stream, (float *)audio_buf, enc_buf, bytes_to_read / (cfg.audio.channel * sizeof(float)), stream_rb.size * 10); + + if (xc_send(enc_buf, encode_bytes_read) == -1) { + connected = 0; + } + else { + kbytes_sent += encode_bytes_read / 1024.0; + } + } + } +#endif + else // ogg, mp3 and flac need more data than opus in order to compress the audio data + { + if (rb_filled(&stream_rb) < (int)(framepacket_size * sizeof(float))) { + continue; + } + + rb_bytes_read = rb_read(&stream_rb, audio_buf); + if (rb_bytes_read == 0) { + continue; + } + + if (!strcmp(cfg.audio.codec, "mp3")) { + encode_bytes_read = + lame_enc_encode(&lame_stream, (float *)audio_buf, enc_buf, rb_bytes_read / (cfg.audio.channel * sizeof(float)), stream_rb.size * 10); + } + + if (!strcmp(cfg.audio.codec, "ogg")) { + encode_bytes_read = vorbis_enc_encode(&vorbis_stream, (float *)audio_buf, enc_buf, rb_bytes_read / (cfg.audio.channel * sizeof(float))); + } + + if (!strcmp(cfg.audio.codec, "flac")) { + encode_bytes_read = flac_enc_encode_stream(&flac_stream, (float *)audio_buf, (uint8_t *)enc_buf, + rb_bytes_read / (cfg.audio.channel * sizeof(float)), cfg.audio.channel, new_stream); + + if (flac_stream.state == FLAC_STATE_UPDATE_META_DATA) { + flac_enc_init_ogg_stream(&flac_stream); + } + + if (encode_bytes_read == 0) { + continue; + } + } + + if (xc_send(enc_buf, encode_bytes_read) == -1) { + connected = 0; + } + else { + kbytes_sent += encode_bytes_read / 1024.0; + } + } + } + + free(enc_buf); + free(audio_buf); + + // Detach thread (free ressources) because no one will call pthread_join() on it + pthread_detach(pthread_self()); + + return NULL; +} + +void snd_stop_streaming_thread(void) +{ + connected = 0; + streaming = 0; + + atom_cond_signal(&stream_cond); + atom_cond_destroy(&stream_cond); + + print_info(_("disconnected\n"), 0); +} + +void snd_start_recording_thread(void) +{ + next_file = 0; + kbytes_written = 0; + recording = 1; + + atom_cond_init(&rec_cond); + + if (pthread_create(&rec_thread_detached, NULL, snd_rec_thread, NULL) != 0) { + print_info("Fatal error: Could not launch recording thread. Please restart BUTT", 1); + recording = 0; + return; + } + + print_info(_("Recording to:"), 0); + print_info(cfg.rec.path, 0); +} + +void snd_stop_recording_thread(void) +{ + recording = 0; + + atom_cond_signal(&rec_cond); + atom_cond_destroy(&rec_cond); + + print_info(_("recording stopped"), 0); +} + +// The recording stuff runs in its own thread +// this prevents dropouts in the recording in case the +// bandwidth is smaller than the selected streaming bitrate +void *snd_rec_thread(void *data) +{ + int rb_bytes_read; + int bytes_to_read; + int opus_header_written; + int enc_bytes_read; + int buf_size = rec_rb.size * sizeof(char) * 10; + + char *enc_buf = (char *)malloc(buf_size); + char *audio_buf = (char *)malloc(buf_size); + + opus_header_written = 0; + + set_max_thread_priority(); + + while (recording) { + atom_cond_wait(&rec_cond); + + if (next_file == 1) { +#ifdef HAVE_LIBFDK_AAC + if (!strcmp(cfg.rec.codec, "aac")) { + aac_enc_flush_file(&aac_rec, cfg.rec.fd); + aac_enc_reinit(&aac_rec); + + fclose(cfg.rec.fd); + cfg.rec.fd = next_fd; + next_file = 0; + } +#endif + if (!strcmp(cfg.rec.codec, "ogg")) { + // Flush encoder + enc_bytes_read = vorbis_enc_encode(&vorbis_rec, NULL, enc_buf, 0); + printf("flushed %d bytes\n", enc_bytes_read); + fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd); + fclose(cfg.rec.fd); + cfg.rec.fd = next_fd; + next_file = 0; + + // Re-init encoder for new file + vorbis_enc_reinit(&vorbis_rec); + } + if (!strcmp(cfg.rec.codec, "opus")) { + opus_rec.state = OPUS_STATE_LAST_FRAME; + next_file = 0; + } + if (!strcmp(cfg.rec.codec, "flac")) { + flac_enc_close_file(&flac_rec); + flac_enc_reinit(&flac_rec); + flac_enc_init_FILE(&flac_rec, next_fd); + cfg.rec.fd = next_fd; + next_file = 0; + } + if (!strcmp(cfg.rec.codec, "mp3")) { + lame_enc_flush_file(&lame_rec, cfg.rec.fd); + lame_enc_reinit(&lame_rec); + fclose(cfg.rec.fd); + cfg.rec.fd = next_fd; + next_file = 0; + } + if (!strcmp(cfg.rec.codec, "wav")) { + wav_write_header(cfg.rec.fd, cfg.audio.channel, cfg.audio.samplerate, cfg.wav_codec_rec.bit_depth); + fclose(cfg.rec.fd); + cfg.rec.fd = next_fd; + next_file = 0; + } + } + + // Opus and aac need special treatments + // The encoders need a predefined number of frames + // Therefore we don't feed the encoder with all data we have in the + // ringbuffer at once + if (!strcmp(cfg.rec.codec, "opus")) { + bytes_to_read = OPUS_FRAME_SIZE * cfg.audio.channel * sizeof(float); + while ((rb_filled(&rec_rb)) >= bytes_to_read) { + rb_read_len(&rec_rb, audio_buf, bytes_to_read); + + if (!opus_header_written) { + opus_enc_write_header(&opus_rec); + opus_header_written = 1; + } + + enc_bytes_read = opus_enc_encode(&opus_rec, (float *)audio_buf, enc_buf); + kbytes_written += fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd) / 1024.0; + + if (opus_rec.state == OPUS_STATE_NEW_STREAM) { + fclose(cfg.rec.fd); + cfg.rec.fd = next_fd; + opus_enc_reinit(&opus_rec); + opus_enc_write_header(&opus_rec); + opus_header_written = 1; + enc_bytes_read = opus_enc_encode(&opus_rec, opus_rec.last_pcm_packet, enc_buf); + kbytes_written += fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd) / 1024.0; + } + } + } +#ifdef HAVE_LIBFDK_AAC + else if (!strcmp(cfg.rec.codec, "aac")) { + bytes_to_read = aac_rec.info.frameLength * cfg.audio.channel * sizeof(float); + while ((rb_filled(&rec_rb)) >= bytes_to_read) { + rb_read_len(&rec_rb, audio_buf, bytes_to_read); + + enc_bytes_read = aac_enc_encode(&aac_rec, (float *)audio_buf, enc_buf, bytes_to_read / (cfg.audio.channel * sizeof(float)), buf_size); + kbytes_written += fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd) / 1024.0; + } + } +#endif + else { + if (rb_filled(&rec_rb) < (int)(framepacket_size * sizeof(float))) { + continue; + } + + rb_bytes_read = rb_read(&rec_rb, audio_buf); + if (rb_bytes_read == 0) { + continue; + } + + if (!strcmp(cfg.rec.codec, "mp3")) { + enc_bytes_read = lame_enc_encode(&lame_rec, (float *)audio_buf, enc_buf, rb_bytes_read / (cfg.audio.channel * sizeof(float)), buf_size); + kbytes_written += fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd) / 1024.0; + } + + if (!strcmp(cfg.rec.codec, "ogg")) { + if (vorbis_rec.header_written == 0) { + vorbis_enc_write_header(&vorbis_rec); + } + + enc_bytes_read = vorbis_enc_encode(&vorbis_rec, (float *)audio_buf, enc_buf, rb_bytes_read / (cfg.audio.channel * sizeof(float))); + kbytes_written += fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd) / 1024.0; + } + + if (!strcmp(cfg.rec.codec, "flac")) { + flac_enc_encode(&flac_rec, (float *)audio_buf, rb_bytes_read / (cfg.audio.channel * sizeof(float)), cfg.audio.channel); + kbytes_written = flac_enc_get_bytes_written() / 1024.0; + } + + if (!strcmp(cfg.rec.codec, "wav")) { + // Permanently update the WAV header + // so in case of a crash we still have a valid WAV file + wav_write_header(cfg.rec.fd, cfg.audio.channel, cfg.audio.samplerate, cfg.wav_codec_rec.bit_depth); + + // Convert float to samples to int16 samples + float *pcm_float = (float *)audio_buf; + int16_t *pcm_int16 = (int16_t *)audio_buf; + int32_t *pcm_int32 = (int32_t *)audio_buf; + + for (uint32_t i = 0; i < rb_bytes_read / sizeof(float); i++) { + if (pcm_float[i] > 0) { + if (cfg.wav_codec_rec.bit_depth == 16) { + pcm_int16[i] = (int16_t)round(fmin(pcm_float[i] * INT16_MAX, INT16_MAX)); + } + else if (cfg.wav_codec_rec.bit_depth == 24) { + pcm_int32[i] = (int32_t)round(fmin(pcm_float[i] * INT24_MAX, INT24_MAX)); + + audio_buf[i * 3 + 0] = audio_buf[i * 4 + 0]; // lsb + audio_buf[i * 3 + 1] = audio_buf[i * 4 + 1]; // center byte + audio_buf[i * 3 + 2] = audio_buf[i * 4 + 2]; // msb + } + else { // cfg.wav_codec_rec.bit_depth == 32 + pcm_int32[i] = (int32_t)round(fmin(pcm_float[i] * INT32_MAX, INT32_MAX)); + } + } + else { + if (cfg.wav_codec_rec.bit_depth == 16) { + pcm_int16[i] = (int16_t)round(fmax(-pcm_float[i] * INT16_MIN, INT16_MIN)); + } + else if (cfg.wav_codec_rec.bit_depth == 24) { + pcm_int32[i] = (int32_t)round(fmax(-pcm_float[i] * INT24_MIN, INT24_MIN)); + + audio_buf[i * 3 + 0] = audio_buf[i * 4 + 0]; // lsb + audio_buf[i * 3 + 1] = audio_buf[i * 4 + 1]; // center byte + audio_buf[i * 3 + 2] = audio_buf[i * 4 + 2]; // msb + } + else { // cfg.wav_codec_rec.bit_depth == 32 + pcm_int32[i] = (int32_t)round(fmax(-pcm_float[i] * INT32_MIN, INT32_MIN)); + } + } + } + + kbytes_written += fwrite(audio_buf, cfg.wav_codec_rec.bit_depth / 8, rb_bytes_read / sizeof(float), cfg.rec.fd) / 1024.0; + } + } + } + + if (!strcmp(cfg.rec.codec, "wav")) { + wav_write_header(cfg.rec.fd, cfg.audio.channel, cfg.audio.samplerate, cfg.wav_codec_rec.bit_depth); + } + else if (!strcmp(cfg.rec.codec, "flac")) { // The flac encoder closes the file + flac_enc_close_file(&flac_rec); + } + else if (!strcmp(cfg.rec.codec, "mp3")) { + lame_enc_flush_file(&lame_rec, cfg.rec.fd); + lame_enc_reinit(&lame_rec); // Prepare for next recording + fclose(cfg.rec.fd); + } + else if (!strcmp(cfg.rec.codec, "ogg")) { + enc_bytes_read = vorbis_enc_encode(&vorbis_rec, NULL, enc_buf, 0); + vorbis_enc_reinit(&vorbis_rec); + fwrite(enc_buf, 1, enc_bytes_read, cfg.rec.fd); + fclose(cfg.rec.fd); + } + +#ifdef HAVE_LIBFDK_AAC + else if (!strcmp(cfg.rec.codec, "aac")) { + aac_enc_flush_file(&aac_rec, cfg.rec.fd); + aac_enc_reinit(&aac_rec); + fclose(cfg.rec.fd); + } +#endif + else if (!strcmp(cfg.rec.codec, "opus")) { + opus_enc_reinit(&opus_rec); + fclose(cfg.rec.fd); + } + else { + fclose(cfg.rec.fd); + } + + free(enc_buf); + free(audio_buf); + + // Detach thread (free ressources) because no one will call pthread_join() on it + pthread_detach(pthread_self()); + + return NULL; +} + +void snd_update_vu(int reset) +{ + int i; + float decay = cfg.audio.samplerate < 88200 ? 0.5 : 0.7; + static float stream_lpeak = 0; + static float stream_rpeak = 0; + static float rec_lpeak = 0; + static float rec_rpeak = 0; + static int call_cnt = 1; + static double stream_lavg = 0; + static double stream_ravg = 0; + static double rec_lavg = 0; + static double rec_ravg = 0; + + if (reset == 1) { + memset(stream_buf, 0, framepacket_size * sizeof(float) * cfg.audio.channel); + memset(record_buf, 0, framepacket_size * sizeof(float) * cfg.audio.channel); + + vu_init(); // Reset peak indicators + call_cnt = 1; + stream_lpeak = 0; + stream_rpeak = 0; + rec_lpeak = 0; + rec_rpeak = 0; + stream_lavg = 0; + stream_ravg = 0; + rec_lavg = 0; + rec_ravg = 0; + } + + for (i = 0; i < framepacket_size; i += cfg.audio.channel) { + if (abs(stream_buf[i]) > stream_lpeak) { + stream_lpeak = abs(stream_buf[i]); + } + if (abs(stream_buf[i + (cfg.audio.channel - 1)]) > stream_rpeak) { + stream_rpeak = abs(stream_buf[i + (cfg.audio.channel - 1)]); + } + + if (abs(record_buf[i]) > rec_lpeak) { + rec_lpeak = abs(record_buf[i]); + } + if (abs(record_buf[i + (cfg.audio.channel - 1)]) > rec_rpeak) { + rec_rpeak = abs(record_buf[i + (cfg.audio.channel - 1)]); + } + } + + float mean_stream_peak = stream_lpeak / 2 + stream_rpeak / 2; + float mean_stream_peak_dB = 20 * log10(mean_stream_peak); + + if (mean_stream_peak_dB < -cfg.audio.silence_level) { + silence_detected = true; + } + else { + silence_detected = false; + } + + if (mean_stream_peak_dB > -cfg.audio.signal_level) { + signal_detected = true; + } + else { + signal_detected = false; + } + + stream_lavg = (decay * stream_lpeak) + (1.0 - decay) * stream_lavg; + stream_ravg = (decay * stream_rpeak) + (1.0 - decay) * stream_ravg; + rec_lavg = (decay * rec_lpeak) + (1.0 - decay) * rec_lavg; + rec_ravg = (decay * rec_rpeak) + (1.0 - decay) * rec_ravg; + + // Update the vu meter UI only every second call of this function. + // This reduces the CPU usage without not missing any samples + if (call_cnt == 1) { + if (vu_level_type == SND_STREAM) { + vu_meter(stream_lavg, stream_ravg, stream_lpeak, stream_rpeak); + } + else { + vu_meter(rec_lavg, rec_ravg, rec_lpeak, rec_rpeak); + } + + if (cfg.dsp.compressor_stream == 1) { + fl_g->LED_comp_threshold->set_state(streaming_dsp->is_compressing == true ? LED::LED_ON : LED::LED_OFF); + } + else if (cfg.dsp.compressor_rec == 1) { + fl_g->LED_comp_threshold->set_state(recording_dsp->is_compressing == true ? LED::LED_ON : LED::LED_OFF); + } + + call_cnt = 0; + } + else { + call_cnt++; + stream_lpeak = 0; + stream_rpeak = 0; + rec_lpeak = 0; + rec_rpeak = 0; + } + + pa_new_frames = 0; +} + +void snd_free_device_list(snd_dev_t **dev_list, int dev_count) +{ + if (dev_count == 0) { + return; + } + + for (int i = 0; i < SND_MAX_DEVICES; i++) { + if (i < dev_count) { + free(dev_list[i]->name); + } + + free(dev_list[i]); + } + free(dev_list); +} + +snd_dev_t **snd_get_devices(int *dev_count) +{ + int available_devices, sr_count, dev_num; + bool sr_supported = 0; + bool has_default_input_devices = 0; + const PaDeviceInfo *p_di; + char info_buf[256]; + PaStreamParameters pa_params; + + int sr[] = {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000}; + + snd_dev_t **dev_list; + dev_list = (snd_dev_t **)malloc(SND_MAX_DEVICES * sizeof(snd_dev_t *)); + + for (int i = 0; i < SND_MAX_DEVICES; i++) { + dev_list[i] = (snd_dev_t *)malloc(sizeof(snd_dev_t)); + } + + dev_num = 0; + if (Pa_GetDefaultInputDevice() != paNoDevice) { + dev_list[dev_num]->name = (char *)malloc(strlen(_("Default PCM device (default)")) + 1); + strcpy(dev_list[dev_num]->name, _("Default PCM device (default)")); + dev_list[dev_num]->dev_id = Pa_GetDefaultInputDevice(); + has_default_input_devices = 1; + dev_num = 1; + } + + available_devices = Pa_GetDeviceCount(); + if (available_devices < 0) { + snprintf(info_buf, sizeof(info_buf), "PaError: %s", Pa_GetErrorText(available_devices)); + print_info(info_buf, 1); + } + + for (int i = 0; i < available_devices && i < SND_MAX_DEVICES - 1; i++) { + sr_count = 0; + p_di = Pa_GetDeviceInfo(i); + if (p_di == NULL) { + snprintf(info_buf, sizeof(info_buf), _("Error getting device Info (%d)"), i); + print_info(info_buf, 1); + continue; + } + + // Save only devices which have input Channels + if (p_di->maxInputChannels <= 0) { + continue; + } + + const PaHostApiInfo *pa_hostapi = Pa_GetHostApiInfo(p_di->hostApi); + pa_params.device = i; + pa_params.channelCount = p_di->maxInputChannels; + pa_params.sampleFormat = paFloat32; + pa_params.suggestedLatency = p_di->defaultHighInputLatency; + pa_params.hostApiSpecificStreamInfo = NULL; + + // add the supported samplerates to the device structure + for (uint32_t j = 0; j < sizeof(sr) / sizeof(sr[0]); j++) { + if (Pa_IsFormatSupported(&pa_params, NULL, sr[j]) == paFormatIsSupported) { + dev_list[dev_num]->sr_list[sr_count] = sr[j]; + sr_count++; + sr_supported = 1; + } + } + // Go to the next device if this one doesn't support at least one of our samplerates + if (!sr_supported) { + continue; + } + + dev_list[dev_num]->num_of_sr = sr_count; + + // Mark the end of the samplerate list for this device with a 0 + dev_list[dev_num]->sr_list[sr_count] = 0; + + dev_list[dev_num]->name = (char *)malloc(strlen(p_di->name) + strlen(pa_hostapi->name) + 10); + dev_list[dev_num]->dev_id = i; + dev_list[dev_num]->num_of_channels = p_di->maxInputChannels; + dev_list[dev_num]->is_asio = pa_hostapi->type == paASIO; + snprintf(dev_list[dev_num]->name, strlen(p_di->name) + strlen(pa_hostapi->name) + 10, "%s [%s]", p_di->name, pa_hostapi->name); + + // copy the sr_list from the device where the + // virtual default device points to + if (has_default_input_devices == 1) { + if (dev_list[0]->dev_id == dev_list[dev_num]->dev_id) { + memcpy(dev_list[0]->sr_list, dev_list[dev_num]->sr_list, sizeof(dev_list[dev_num]->sr_list)); + dev_list[0]->num_of_sr = dev_list[dev_num]->num_of_sr; + dev_list[0]->num_of_channels = dev_list[dev_num]->num_of_channels; + dev_list[0]->is_asio = dev_list[dev_num]->is_asio; + } + } + + // Replace characters from the device name that have a special meaning to FLTK + strrpl(&dev_list[dev_num]->name, (char *)"\\", (char *)" ", MODE_ALL); // Must come first + strrpl(&dev_list[dev_num]->name, (char *)"/", (char *)"\\/", MODE_ALL); + strrpl(&dev_list[dev_num]->name, (char *)"|", (char *)" ", MODE_ALL); + strrpl(&dev_list[dev_num]->name, (char *)"\t", (char *)" ", MODE_ALL); + strrpl(&dev_list[dev_num]->name, (char *)"_", (char *)" ", MODE_ALL); + strrpl(&dev_list[dev_num]->name, (char *)"&", (char *)"+", MODE_ALL); + + dev_num++; + } // for(i = 0; i < devcount && i < 100; i++) + + *dev_count = dev_num; + + return dev_list; +} + +void snd_print_devices(void) +{ + PaError err; + const PaDeviceInfo *di; + + if ((err = Pa_Initialize()) != paNoError) { + printf("PortAudio init failed:\n%s\n", Pa_GetErrorText(err)); + return; + } + + int dev_count; + snd_dev_t **dev_list; + dev_list = snd_get_devices(&dev_count); + + if (dev_count == 0) { + printf("No input audio device available\n"); + return; + } + + for (int i = 0; i < dev_count; i++) { + printf("Device ID: %d\n", i); + printf("Device name: %s\n", dev_list[i]->name); + printf("Number of channels: %d\n", dev_list[i]->num_of_channels); + printf("Supported sample rates: "); + for (int j = 0; j < dev_list[i]->num_of_sr; j++) { + if (j < dev_list[i]->num_of_sr - 1) { + printf("%d Hz, ", dev_list[i]->sr_list[j]); + } + else { + printf("%d Hz", dev_list[i]->sr_list[j]); + } + } + + printf("\n\n"); + } + + snd_free_device_list(dev_list, dev_count); + + Pa_Terminate(); +} + +void snd_reset_samplerate_conv(int rec_or_stream) +{ + int error; + + if (rec_or_stream == SND_STREAM) { + if (srconv_state_opus_stream != NULL) { + src_delete(srconv_state_opus_stream); + srconv_state_opus_stream = NULL; + } + + srconv_state_opus_stream = src_new(cfg.audio.resample_mode, cfg.audio.channel, &error); + if (srconv_state_opus_stream == NULL) { + print_info(_("ERROR: Could not initialize samplerate converter"), 0); + } + + srconv_opus_stream.end_of_input = 0; + srconv_opus_stream.src_ratio = 48000.0 / cfg.audio.samplerate; + srconv_opus_stream.input_frames = pa_frames; + srconv_opus_stream.output_frames = pa_frames * (1 + srconv_opus_stream.src_ratio); + } + + if (rec_or_stream == SND_REC) { + if (srconv_state_opus_record != NULL) { + src_delete(srconv_state_opus_record); + srconv_state_opus_record = NULL; + } + + srconv_state_opus_record = src_new(cfg.audio.resample_mode, cfg.audio.channel, &error); + if (srconv_state_opus_record == NULL) { + print_info(_("ERROR: Could not initialize samplerate converter"), 0); + } + + srconv_opus_record.end_of_input = 0; + srconv_opus_record.src_ratio = 48000.0 / cfg.audio.samplerate; + srconv_opus_record.input_frames = pa_frames; + srconv_opus_record.output_frames = pa_frames * (1 + srconv_opus_record.src_ratio); + } +} + +char *snd_get_device_name(int id) +{ + const PaDeviceInfo *pa_dev_info; + + pa_dev_info = Pa_GetDeviceInfo(id); + if (pa_dev_info == NULL) { + return NULL; + } + else { + return strdup(pa_dev_info->name); // Note: Make sure it will be free'd on the caller side + } +} + +int snd_get_number_of_channels(int id) +{ + const PaDeviceInfo *pa_dev_info; + + pa_dev_info = Pa_GetDeviceInfo(id); + if (pa_dev_info == NULL) { + return 0; + } + else { + return pa_dev_info->maxInputChannels; + } +} + +int snd_get_dev_num_by_name(char *name) +{ + if (name != NULL) { + for (int i = 0; i < cfg.audio.dev_count; i++) { + if (!strcmp(name, cfg.audio.pcm_list[i]->name)) { + return i; + } + } + } + + return -1; // Device not found +} + +void snd_close_streams(void) +{ + int stream_is_active = Pa_IsStreamActive(stream); + int stream2_is_active = Pa_IsStreamActive(stream2); + + if (stream2_is_active == 1) { + Pa_AbortStream(stream2); + Pa_CloseStream(stream2); + } + + if (stream_is_active == 1) { + snd_stop_mixer_thread(); + Pa_AbortStream(stream); + Pa_CloseStream(stream); + g_stop_vu_meter_timer = 1; + while (g_vu_meter_timer_is_active == 1) { + Fl::check(); + Pa_Sleep(1); + } + g_stop_vu_meter_timer = 0; + snd_update_vu(1); + + free(pa_pcm_buf); + free(pa_mixer_buf); + free(encode_buf); + free(stream_buf); + free(record_buf); + free(srconv_opus_stream.data_out); + free(srconv_opus_record.data_out); + free(srconv_dev2.data_out); + + rb_free(&pa_pcm_rb); + rb_free(&rec_rb); + rb_free(&stream_rb); + } + + if (stream2_is_active == 1) { + free(pa_pcm_buf2); + free(pa_mixer_buf2); + rb_free(&pa_pcm2_rb); + } +} + +void snd_close_portaudio(void) +{ + Pa_Terminate(); +} diff --git a/src/port_audio.h b/src/port_audio.h new file mode 100644 index 0000000..cd96d29 --- /dev/null +++ b/src/port_audio.h @@ -0,0 +1,95 @@ +// audio functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef PORT_AUDIO_H +#define PORT_AUDIO_H + +#include +#include + +#include + +#include "lame_encode.h" +#include "dsp.hpp" + +#define SND_MAX_DEVICES (256) + +#define INT24_MAX ((1 << 23) - 1) +#define INT24_MIN (-(1 << 23)) + +extern DSPEffects *streaming_dsp; +extern DSPEffects *recording_dsp; + +typedef struct { + char *name; + int dev_id; + int sr_list[12]; // 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, 0 + int num_of_sr; + int num_of_channels; + int left_ch; + int right_ch; + int is_asio; +} snd_dev_t; + +enum { + SND_STREAM = 0, + SND_REC = 1, +}; + +extern bool pa_new_frames; +extern bool reconnect; +extern bool next_file; +extern bool silence_detected; +extern bool signal_detected; + +extern FILE *next_fd; + +int *snd_get_samplerates(int *sr_count); +void snd_free_device_list(snd_dev_t **dev_list, int dev_count); +snd_dev_t **snd_get_devices(int *dev_count); +void *snd_rec_thread(void *data); +void *snd_stream_thread(void *data); +void *snd_mixer_thread(void *data); + +void snd_update_vu(int reset); +void snd_start_streaming_thread(void); +void snd_stop_streaming_thread(void); +void snd_start_recording_thread(void); +void snd_stop_recording_thread(void); +void snd_start_mixer_thread(void); +void snd_stop_mixer_thread(void); + +void snd_set_vu_level_type(int type); + +int snd_init(void); +void snd_init_dsp(void); +int snd_open_streams(void); +int snd_reopen_streams(void); +void snd_close_streams(void); +void snd_close_portaudio(void); +void snd_print_devices(void); +int snd_write_buf(void); +void snd_reset_samplerate_conv(int rec_or_stream); + +int snd_callback(const void *input, void *output, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, + void *userData); +int snd_callback2(const void *input, void *output, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, + void *userData); + +void snd_reset_streaming_compressor(void); +void snd_reset_recording_compressor(void); +int snd_get_dev_num_by_name(char *name); + +#endif diff --git a/src/port_midi.cpp b/src/port_midi.cpp new file mode 100644 index 0000000..232a79a --- /dev/null +++ b/src/port_midi.cpp @@ -0,0 +1,362 @@ +// +// port_midi.cpp +// butt +// +// Created by Daniel Nöthen on 03.02.24. +// Copyright © 2024 Daniel Nöthen. All rights reserved. +// + +#include +#include + +#include "port_midi.h" +#include "atom.h" +#include "strfuncs.h" +#include "fl_funcs.h" +#include "fl_timer_funcs.h" +#include "flgui.h" + +#define INPUT_BUFFER_SIZE 100 +#define TIME_PROC ((int32_t(*)(void *))Pt_Time) +#define TIME_INFO NULL + +PortMidiStream *midi_stream; +pthread_t midi_poll_thread_joinable; +ATOM_NEW_INT(stop_midi_thread, 0); +ATOM_NEW_INT(learning_active, 0); +ATOM_NEW_INT(polling_is_active, 0); +int is_initialized = 0; + +int get_dev_list_elem_count(midi_dev_t **dev_list) +{ + if (dev_list == NULL) { + return 0; + } + + int elem_count = 0; + while (dev_list[elem_count] != NULL) { + elem_count++; + } + + return elem_count; +} + +void *midi_poll_thread_func(void *data) +{ + int LED_counter = 0; + PmEvent buffer[INPUT_BUFFER_SIZE]; + atom_set_int(&stop_midi_thread, 0); + atom_set_int(&polling_is_active, 1); + + // Pm_SetChannelMask(midi_stream, Pm_Channel(0)); + + // Main loop to listen for MIDI events + while (atom_get_int(&stop_midi_thread) == 0) { + int numEvents = Pm_Read(midi_stream, buffer, INPUT_BUFFER_SIZE); + if (numEvents > 0) { + LED_counter = 0; + Fl::lock(); + fl_g->LED_midi_command->set_state(LED::LED_ON); + Fl::unlock(); + Fl::awake(); + + for (int i = 0; i < numEvents; i++) { + PmMessage message = buffer[i].message; + uint8_t channel = (Pm_MessageStatus(message) & 0x0F) + 1; + uint8_t msg_type = Pm_MessageStatus(message) & 0xF0; + uint8_t msg_num = Pm_MessageData1(message); + uint8_t val = Pm_MessageData2(message); + + // Ignore NOTE_ON messages with values lower than 64 because + // some devices send NOTE_ON with value 0 for a button release. + // Usually devices send NOTE_ON with value 0x7F when a button is pressed down. + // We do only want to react on NOTE_ON messages for button presses and ignore button releases + if (msg_type == MIDI_MSG_TYPE_NOTE_ON && val < 64) { + continue; + } + + if (atom_get_int(&learning_active) == 1) { + if (msg_type != MIDI_MSG_TYPE_CC && msg_type != MIDI_MSG_TYPE_NOTE_ON) { // Allow only CC and NOTE ON messages for now + break; + } + + Fl::lock(); + int command = fl_g->browser_midi_command->value() - 1; + cfg.midi.commands[command].channel = channel; + cfg.midi.commands[command].msg_type = msg_type; + cfg.midi.commands[command].msg_num = msg_num; + fl_g->choice_midi_channel->value(channel); + fl_g->input_midi_msg_num->value(msg_num); + fl_g->button_midi_learn->value(0); + fl_g->button_midi_learn->do_callback(); + Fl::unlock(); + midi_set_learning(0); + break; + } + + for (int j = 0; j < MIDI_COMMANDS_COUNT; j++) { + if ((cfg.midi.commands[j].channel == MIDI_ANY_CHANNEL || cfg.midi.commands[j].channel == channel) && // + cfg.midi.commands[j].msg_type == msg_type && // + cfg.midi.commands[j].msg_num == msg_num && // + cfg.midi.commands[j].enabled == 1) { + exec_midi_command(j, msg_type, val); + } + } + + /* if (type == MIDI_MSG_TYPE_CC) { + Fl::lock(); + + double min = fl_g->slider_gain->minimum(); + double max = fl_g->slider_gain->maximum(); + double new_val = min + val * (max-min) / 127; + fl_g->slider_gain->value(new_val); + fl_g->slider_gain->do_callback(); + printf("Channel: %u, Type: %u, CC: %u, Val: %u\n", channel, type, msg_num, val); + Fl::unlock(); + }*/ + } + } + else if (LED_counter++ >= 10) { + LED_counter = 0; + Fl::lock(); + fl_g->LED_midi_command->set_state(LED::LED_OFF); + Fl::unlock(); + Fl::awake(); + } + + Pt_Sleep(10); + } + + // Cleanup + Pm_Close(midi_stream); + + atom_set_int(&polling_is_active, 0); + return NULL; +} + +PmError midi_init(void) +{ + PmError res = Pm_Initialize(); + if (res != pmNoError) { + return res; + } + + is_initialized = 1; + atom_set_int(&polling_is_active, 0); + return res; +} + +midi_dev_t **midi_get_devices(int *dev_count) +{ + if (is_initialized == 0) { + print_info(_("Error: PortMidi was not initialized."), 1); + return NULL; + } + + int available_devices; + int dev_num = 0; + PmDeviceInfo *device_info; + char info_buf[256]; + + available_devices = Pm_CountDevices(); + if (available_devices <= 0) { + *dev_count = 0; + return NULL; + } + + midi_dev_t **dev_list; + dev_list = (midi_dev_t **)malloc(MIDI_MAX_DEVICES * sizeof(midi_dev_t *)); + + for (int i = 0; i < MIDI_MAX_DEVICES; i++) { + dev_list[i] = (midi_dev_t *)malloc(sizeof(midi_dev_t)); + } + + for (int i = 0; i < available_devices && i < MIDI_MAX_DEVICES - 1; i++) { + device_info = (PmDeviceInfo *)Pm_GetDeviceInfo(i); + if (device_info == NULL) { + snprintf(info_buf, sizeof(info_buf), _("Error getting device Info (%d)"), i); + print_info(info_buf, 1); + continue; + } + + // Save only input devices + if (device_info->input == 0) { + continue; + } + + dev_list[dev_num]->name = (char *)malloc(strlen(device_info->name) + strlen(device_info->interf) + 10); + dev_list[dev_num]->dev_id = i; + snprintf(dev_list[dev_num]->name, strlen(device_info->name) + strlen(device_info->interf) + 10, "%s [%s]", device_info->name, device_info->interf); + + // Replace characters from the device name that have a special meaning to FLTK + strrpl(&dev_list[dev_num]->name, (char *)"\\", (char *)" ", MODE_ALL); // Must come first + strrpl(&dev_list[dev_num]->name, (char *)"/", (char *)"\\/", MODE_ALL); + strrpl(&dev_list[dev_num]->name, (char *)"|", (char *)" ", MODE_ALL); + strrpl(&dev_list[dev_num]->name, (char *)"\t", (char *)" ", MODE_ALL); + strrpl(&dev_list[dev_num]->name, (char *)"_", (char *)" ", MODE_ALL); + strrpl(&dev_list[dev_num]->name, (char *)"&", (char *)"+", MODE_ALL); + + dev_num++; + } + + dev_list[dev_num] = NULL; + + *dev_count = dev_num; + return dev_list; +} + +void midi_free_device_list(midi_dev_t **dev_list) +{ + if (is_initialized == 0) { + print_info(_("Error: PortMidi was not initialized."), 1); + return; + } + + int dev_count = get_dev_list_elem_count(dev_list); + if (dev_count == 0) { + return; + } + + for (int i = 0; i < MIDI_MAX_DEVICES; i++) { + if (i < dev_count) { + free(dev_list[i]->name); + } + + free(dev_list[i]); + } + free(dev_list); +} + +int midi_open_device(int device_id) +{ + if (is_initialized == 0) { + print_info(_("Error: PortMidi was not initialized."), 1); + return -1; + } + + PmError result; + Pt_Start(1, NULL, NULL); + + result = Pm_OpenInput(&midi_stream, device_id, NULL, INPUT_BUFFER_SIZE, NULL, NULL); + if (result != pmNoError) { + printf("device id: %d\n", device_id); + printf("Error opening MIDI input: %s\n", Pm_GetErrorText(result)); + return -1; + } + + return 0; +} + +int midi_open_device(char *device_name) +{ + char info_buf[256]; + + if (is_initialized == 0) { + print_info(_("Error: PortMidi was not initialized."), 1); + return -1; + } + + int dev_count; + midi_dev_t **dev_list = midi_get_devices(&dev_count); + if (dev_list == NULL) { + snprintf(info_buf, sizeof(info_buf), _("Error: MIDI device %s could not be opened because no MIDI devices were found."), device_name); + print_info(info_buf, 1); + return -1; + } + + int dev_num = midi_get_dev_num_by_name(dev_list, device_name); + if (dev_num == -1) { + snprintf(info_buf, sizeof(info_buf), _("Error: MIDI device %s could not be found."), device_name); + print_info(info_buf, 1); + return -1; + } + + int dev_id = dev_list[dev_num]->dev_id; + + return midi_open_device(dev_id); +} + +int midi_start_polling(void) +{ + if (is_initialized == 0) { + print_info(_("Error: PortMidi was not initialized."), 1); + return -1; + } + if (atom_get_int(&polling_is_active) == 1) { + print_info(_("Error: MIDI thread already active."), 1); + return -1; + } + + if (pthread_create(&midi_poll_thread_joinable, NULL, midi_poll_thread_func, NULL) != 0) { + print_info(_("Error: Could not start MIDI thread."), 1); + return -1; + } + + return 0; +} + +int midi_stop_polling(void) +{ + if (is_initialized == 0) { + print_info(_("Error: PortMidi was not initialized."), 1); + return -1; + } + + if (atom_get_int(&polling_is_active) == 1) { + atom_set_int(&stop_midi_thread, 1); + pthread_join(midi_poll_thread_joinable, NULL); + } + + return 0; +} + +int midi_get_dev_num_by_name(midi_dev_t **dev_list, char *dev_name) +{ + if (is_initialized == 0) { + print_info(_("Error: PortMidi was not initialized."), 1); + return -1; + } + + if (dev_list == NULL || dev_name == NULL) { + return -1; + } + + int dev_count = get_dev_list_elem_count(dev_list); + if (dev_count == 0) { + return -1; + } + + for (int i = 0; i < dev_count; i++) { + if (!strcmp(dev_name, dev_list[i]->name)) { + return i; + } + } + + return -1; // Device not found +} + +void midi_close(void) +{ + if (is_initialized == 0) { + print_info(_("Error: PortMidi was not initialized."), 1); + return; + } + + midi_stop_polling(); + Pm_Close(midi_stream); +} + +void midi_terminate(void) +{ + if (is_initialized == 0) { + print_info(_("Error: PortMidi was not initialized."), 1); + return; + } + Pm_Terminate(); + is_initialized = 0; +} + +void midi_set_learning(int is_active) +{ + atom_set_int(&learning_active, is_active); +} diff --git a/src/port_midi.h b/src/port_midi.h new file mode 100644 index 0000000..dd6095d --- /dev/null +++ b/src/port_midi.h @@ -0,0 +1,77 @@ +// +// port_midi.hpp +// butt +// +// Created by Daniel Nöthen on 03.02.24. +// Copyright © 2024 Daniel Nöthen. All rights reserved. +// + +#ifndef MIDI_H +#define MIDI_H + +#include "portmidi.h" +#include "porttime.h" + +#define MIDI_MAX_DEVICES (256) + +typedef struct { + char *name; + int dev_id; +} midi_dev_t; + +enum { + MIDI_MSG_TYPE_NOTE_OFF = 0x80, + MIDI_MSG_TYPE_NOTE_ON = 0x90, + MIDI_MSG_TYPE_POLY_PRESSURE = 0xA0, + MIDI_MSG_TYPE_CC = 0xB0, + MIDI_MSG_TYPE_PC = 0xC0, + MIDI_MSG_TYPE_CHANNEL_PRESSURE = 0xD0, + MIDI_MSG_TYPE_PITCH_BEND = 0xE0, +}; + +enum { + MIDI_ANY_CHANNEL = 0, +}; + +enum { + MIDI_MODE_ABSOLUTE = 0, + MIDI_MODE_RELATIVE_TWOS_COMPLEMENT = 1, + MIDI_MODE_RELATIVE_BINARY_OFFSET = 2, + MIDI_MODE_RELATIVE_SIGN_MAGNITUDE = 3, +}; + +enum { + MIDI_CMD_START_STOP_BROADCASTING = 0, + MIDI_CMD_START_STOP_RECORDING = 1, + MIDI_CMD_MASTER_GAIN = 2, + MIDI_CMD_STREAMING_GAIN = 3, + MIDI_CMD_RECORDING_GAIN = 4, + MIDI_CMD_PRIMARY_DEV_VOL = 5, + MIDI_CMD_SECONDARY_DEV_VOL = 6, + MIDI_CMD_CROSS_FADER = 7, + MIDI_CMD_PRIMARY_DEV_MUTE_UNMUTE = 8, + MIDI_CMD_SECONDARY_DEV_MUTE_UNMUTE = 9, + MIDI_CMD_START_BROADCASTING = 10, + MIDI_CMD_STOP_BROADCASTING = 11, + MIDI_CMD_START_RECORDING = 12, + MIDI_CMD_STOP_RECORDING = 13, +}; + +enum { + MIDI_CTRL_TYPE_KNOB = 0, + MIDI_CTRL_TYPE_BUTTON = 1, +}; + +PmError midi_init(void); +int midi_open_device(int device_num); +int midi_open_device(char *device_name); +int midi_start_polling(void); +int midi_stop_polling(void); +void midi_set_learning(int is_active); +midi_dev_t **midi_get_devices(int *dev_count); +int midi_get_dev_num_by_name(midi_dev_t **dev_list, char *dev_name); +void midi_free_device_list(midi_dev_t **dev_list); +void midi_close(void); +void midi_terminate(void); + +#endif // MIDI_H diff --git a/src/resource.rc b/src/resource.rc new file mode 100644 index 0000000..e2623ff --- /dev/null +++ b/src/resource.rc @@ -0,0 +1,6 @@ +#include "winuser.h" +#define IDI_ICON 101 +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "butt.manifest" +IDI_ICON ICON DISCARDABLE "../icons/butt.ico" + + diff --git a/src/ringbuffer.cpp b/src/ringbuffer.cpp new file mode 100644 index 0000000..75b717c --- /dev/null +++ b/src/ringbuffer.cpp @@ -0,0 +1,224 @@ +// ringbuffer functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// +#include +#include +#include +#include +#include "ringbuffer.h" + +int rb_init(ringbuf_t *rb, unsigned int len) +{ + rb->buf = (char *)malloc(len * sizeof(char)); + if (!rb->buf) { + return -1; + } + + rb->r_ptr = rb->buf; + rb->w_ptr = rb->buf; + rb->size = len; + rb->full = 0; + + pthread_mutex_init(&rb->mutex, NULL); + + return 0; +} + +int rb_filled(ringbuf_t *rb) +{ + int filled; + char *end_ptr; + + pthread_mutex_lock(&rb->mutex); + + if (rb->w_ptr == rb->r_ptr && rb->full) { + filled = rb->size; + } + else if (rb->w_ptr == rb->r_ptr && !rb->full) { + filled = 0; + } + else if (rb->w_ptr > rb->r_ptr) { + filled = rb->w_ptr - rb->r_ptr; + } + else { + end_ptr = rb->buf + rb->size; + filled = end_ptr - rb->r_ptr; + filled += rb->w_ptr - rb->buf; + } + + pthread_mutex_unlock(&rb->mutex); + + return filled; +} + +int rb_space(ringbuf_t *rb) +{ + int space; + char *end_ptr; + + pthread_mutex_lock(&rb->mutex); + + if (rb->r_ptr == rb->w_ptr && rb->full) { + space = 0; + } + else if (rb->r_ptr == rb->w_ptr && !rb->full) { + space = rb->size; + } + else if (rb->r_ptr > rb->w_ptr) { + space = rb->r_ptr - rb->w_ptr; + } + else { + end_ptr = rb->buf + rb->size; + space = end_ptr - rb->w_ptr; + space += rb->r_ptr - rb->buf; + } + + pthread_mutex_unlock(&rb->mutex); + + return space; +} + +unsigned int rb_read(ringbuf_t *rb, char *dest) +{ + unsigned int len = 0; + char *end_ptr; + + if (!dest || !rb->buf) { + return 0; + } + if (len > rb->size) { + return 0; + } + + len = rb_filled(rb); + + pthread_mutex_lock(&rb->mutex); + + end_ptr = rb->buf + rb->size; + + if (rb->r_ptr + len < end_ptr) { + memcpy(dest, rb->r_ptr, len); + rb->r_ptr += len; + } + /*buf content crosses the start point of the ring*/ + else { + /*copy from r_ptr to start of ringbuffer*/ + memcpy(dest, rb->r_ptr, end_ptr - rb->r_ptr); + /*copy from start of ringbuffer to w_ptr*/ + memcpy(dest + (end_ptr - rb->r_ptr), rb->buf, len - (end_ptr - rb->r_ptr)); + rb->r_ptr = rb->buf + (len - (end_ptr - rb->r_ptr)); + } + + pthread_mutex_unlock(&rb->mutex); + + if (rb->w_ptr == rb->r_ptr) { + rb->full = 0; + } + + return len; +} + +unsigned int rb_read_len(ringbuf_t *rb, char *dest, unsigned int len) +{ + char *end_ptr; + + if (!dest || !rb->buf) { + return 0; + } + if (len > rb->size) { + return 0; + } + + pthread_mutex_lock(&rb->mutex); + + end_ptr = rb->buf + rb->size; + // len = rb_filled(rb); + + if (rb->r_ptr + len < end_ptr) { + memcpy(dest, rb->r_ptr, len); + rb->r_ptr += len; + } + /*buf content crosses the start point of the ring*/ + else { + /*copy from r_ptr to start of ringbuffer*/ + memcpy(dest, rb->r_ptr, end_ptr - rb->r_ptr); + /*copy from start of ringbuffer to w_ptr*/ + memcpy(dest + (end_ptr - rb->r_ptr), rb->buf, len - (end_ptr - rb->r_ptr)); + rb->r_ptr = rb->buf + (len - (end_ptr - rb->r_ptr)); + } + + pthread_mutex_unlock(&rb->mutex); + + if (rb->w_ptr == rb->r_ptr) { + rb->full = 0; + } + + return len; +} + +int rb_write(ringbuf_t *rb, char *src, unsigned int len) +{ + char *end_ptr; + + if (!src || !rb->buf) { + return -1; + } + if (len > rb->size) { + return -1; + } + if (len == 0) { + return 0; + } + + pthread_mutex_lock(&rb->mutex); + + end_ptr = rb->buf + rb->size; + + if (rb->w_ptr + len < end_ptr) { + memcpy(rb->w_ptr, src, len); + rb->w_ptr += len; + } + else { + memcpy(rb->w_ptr, src, end_ptr - rb->w_ptr); + memcpy(rb->buf, src + (end_ptr - rb->w_ptr), len - (end_ptr - rb->w_ptr)); + rb->w_ptr = rb->buf + (len - (end_ptr - rb->w_ptr)); + } + + if (rb->w_ptr == rb->r_ptr) { + rb->full = 1; + } + + pthread_mutex_unlock(&rb->mutex); + + return 0; +} + +int rb_clear(ringbuf_t *rb) +{ + pthread_mutex_lock(&rb->mutex); + rb->r_ptr = rb->buf; + rb->w_ptr = rb->buf; + rb->full = 0; + pthread_mutex_unlock(&rb->mutex); + + return 0; +} + +int rb_free(ringbuf_t *rb) +{ + free(rb->buf); + pthread_mutex_destroy(&rb->mutex); + return 0; +} diff --git a/src/ringbuffer.h b/src/ringbuffer.h new file mode 100644 index 0000000..30d9f1b --- /dev/null +++ b/src/ringbuffer.h @@ -0,0 +1,39 @@ +// ringbuffer functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// +#ifndef RINGBUFFER_H +#define RINGBUFFER_H + +#include + +typedef struct ringbuf { + char *buf; + char *w_ptr; + char *r_ptr; + unsigned int size; + unsigned int full; + pthread_mutex_t mutex; +} ringbuf_t; + +int rb_init(ringbuf_t *rb, unsigned int size); +int rb_filled(ringbuf_t *rb); +int rb_space(ringbuf_t *rb); +unsigned int rb_read(ringbuf_t *rb, char *dest); +unsigned int rb_read_len(ringbuf_t *rb, char *dest, unsigned int len); +int rb_write(ringbuf_t *rb, char *src, unsigned int size); +int rb_clear(ringbuf_t *rb); +int rb_free(ringbuf_t *rb); + +#endif /*RINGBUFFER_H*/ diff --git a/src/sha256.cpp b/src/sha256.cpp new file mode 100644 index 0000000..17229f3 --- /dev/null +++ b/src/sha256.cpp @@ -0,0 +1,72 @@ +// +// sha256.cpp +// butt +// +// Created by Daniel Nöthen on 17.03.21. +// Copyright © 2021 Daniel Nöthen. All rights reserved. +// +// +#ifdef WIN32 + +#include +#include +#include +#include + +#include "sha256.h" + +void sha256_string(char *string, char outputBuffer[65], int salt) +{ + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256_CTX sha256; + SHA256_Init(&sha256); + SHA256_Update(&sha256, string, strlen(string)); + SHA256_Final(hash, &sha256); + + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + sprintf(outputBuffer + (i * 2), "%02x", hash[i]); + } + outputBuffer[64] = 0; +} + +int sha256_file(char *path, char outputBuffer[65], int salt) +{ + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256_CTX sha256; + const int buf_size = 32768; + unsigned char *buffer; + size_t bytes_read = 0; + + FILE *file = fopen(path, "rb"); + if (!file) { + return -1; + } + + buffer = (unsigned char *)malloc(buf_size); + if (!buffer) { + return -1; + } + + SHA256_Init(&sha256); + + if (salt > 0) { + SHA256_Update(&sha256, &salt, sizeof(int)); + } + + while ((bytes_read = fread(buffer, 1, buf_size, file))) { + SHA256_Update(&sha256, buffer, bytes_read); + } + SHA256_Final(hash, &sha256); + + // sha256_hash_string(hash, outputBuffer); + + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + sprintf(outputBuffer + (i * 2), "%02x", hash[i]); + } + outputBuffer[64] = 0; + + fclose(file); + free(buffer); + return 0; +} +#endif diff --git a/src/sha256.h b/src/sha256.h new file mode 100644 index 0000000..deec898 --- /dev/null +++ b/src/sha256.h @@ -0,0 +1,21 @@ +// sha256 functions for butt +// +// Copyright 2007-2021 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +#ifndef SHA256_H +#define SHA256_H + +void sha256_string(char *string, char outputBuffer[65], int salt); +int sha256_file(char *path, char outputBuffer[65], int salt); + +#endif // SHA256_H diff --git a/src/shoutcast.cpp b/src/shoutcast.cpp new file mode 100644 index 0000000..6f35279 --- /dev/null +++ b/src/shoutcast.cpp @@ -0,0 +1,403 @@ +// shoutcast functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include +#include + +#ifdef WIN32 +#define usleep(us) Sleep(us / 1000) +#else +#include +#include +#include +#include //defines IPPROTO_TCP on BSD +#include +#endif + +#include + +#include "gettext.h" + +#include "cfg.h" +#include "butt.h" +#include "timer.h" +#include "strfuncs.h" +#include "shoutcast.h" +#include "parseconfig.h" +#include "sockfuncs.h" +#include "flgui.h" +#include "fl_funcs.h" +#include "url.h" +#include "uri_encode.h" + +int server_version = SC_VERSION_UNKNOWN; + +void send_icy_header(char *key, char *val) +{ + char *icy_line; + int len; + + if ((val == NULL) || (strlen(val) == 0)) { + return; + } + + len = strlen(key) + strlen(val) + strlen(":\r\n") + 1; + icy_line = (char *)malloc(len * sizeof(char) + 1); + snprintf(icy_line, len, "%s:%s\r\n", key, val); + + sock_send(stream_socket, icy_line, strlen(icy_line), SEND_TIMEOUT); + + free(icy_line); +} + +int sc_connect(void) +{ + int ret; + char recv_buf[100]; + char send_buf[100]; + static bool error_printed = 0; + server_version = SC_VERSION_UNKNOWN; + + stream_socket = sock_connect(cfg.srv[cfg.selected_srv]->addr, cfg.srv[cfg.selected_srv]->port + 1, SOCK_PROTO_TCP, CONN_TIMEOUT); + + if (stream_socket < 0) { + switch (stream_socket) { + case SOCK_ERR_CREATE: + if (!error_printed) { + print_info(_("\nConnect: Could not create network socket"), 1); + } + if (cfg.main.force_reconnecting == 1) { + error_printed = 1; + ret = SC_RETRY; + } + else { + ret = SC_ABORT; + } + break; + case SOCK_ERR_RESOLVE: + if (!error_printed) { + print_info(_("\nConnect: Error resolving server address"), 1); + error_printed = 1; + } + ret = SC_RETRY; + break; + case SOCK_TIMEOUT: + case SOCK_INVALID: + ret = SC_RETRY; + break; + default: + if (cfg.main.force_reconnecting == 1) { + ret = SC_RETRY; + } + else { + ret = SC_ABORT; + } + } + + return ret; + } + + snprintf(send_buf, sizeof(send_buf), "%s%s", cfg.srv[cfg.selected_srv]->pwd, "\r\n"); + sock_send(stream_socket, send_buf, strlen(send_buf), SEND_TIMEOUT); + + // Make butt compatible to proxies/load balancers. Thanks to boyska + if (cfg.srv[cfg.selected_srv]->port == 80) { + snprintf(send_buf, sizeof(send_buf), "Host: %s\r\n", cfg.srv[cfg.selected_srv]->addr); + } + else { + snprintf(send_buf, sizeof(send_buf), "Host: %s:%d\r\n", cfg.srv[cfg.selected_srv]->addr, cfg.srv[cfg.selected_srv]->port); + } + sock_send(stream_socket, send_buf, strlen(send_buf), SEND_TIMEOUT); + + if (cfg.main.num_of_icy > 0) { + char *icy_name = strdup(cfg.icy[cfg.selected_icy]->name); + if (cfg.icy[cfg.selected_icy]->expand_variables == 1) { + expand_string(&icy_name); + strrpl(&icy_name, (char *)"%N", cfg.srv[cfg.selected_srv]->name, MODE_ALL); + } + snprintf(send_buf + strlen(send_buf), sizeof(send_buf) - strlen(send_buf), "ice-name: %s\r\n", icy_name); + send_icy_header((char *)"icy-name", icy_name); + send_icy_header((char *)"icy-genre", cfg.icy[cfg.selected_icy]->genre); + send_icy_header((char *)"icy-url", cfg.icy[cfg.selected_icy]->url); + send_icy_header((char *)"icy-irc", cfg.icy[cfg.selected_icy]->irc); + send_icy_header((char *)"icy-icq", cfg.icy[cfg.selected_icy]->icq); + send_icy_header((char *)"icy-aim", cfg.icy[cfg.selected_icy]->aim); + send_icy_header((char *)"icy-pub", cfg.icy[cfg.selected_icy]->pub); + free(icy_name); + } + else { + send_icy_header((char *)"icy-name", (char *)"No Name"); + send_icy_header((char *)"icy-pub", (char *)"0"); + } + + snprintf(send_buf, sizeof(send_buf), "%u", cfg.audio.bitrate); + send_icy_header((char *)"icy-br", send_buf); + + sock_send(stream_socket, "content-type:", 13, SEND_TIMEOUT); + + if (!strcmp(cfg.audio.codec, "mp3")) { + strcpy(send_buf, "audio/mpeg"); + } + else if (!strcmp(cfg.audio.codec, "aac")) { + strcpy(send_buf, "audio/aac"); + } + else { + strcpy(send_buf, "audio/ogg"); + } + + sock_send(stream_socket, send_buf, strlen(send_buf), SEND_TIMEOUT); + + sock_send(stream_socket, "\r\n\r\n", 4, SEND_TIMEOUT); + + if ((ret = sock_recv(stream_socket, recv_buf, sizeof(recv_buf) - 1, 5 * RECV_TIMEOUT)) == 0) { + usleep(100 * 1000); + sc_disconnect(); + return SC_RETRY; + } + + if (ret == SOCK_TIMEOUT) { + print_info(_("\nconnect: connection timed out. Trying again...\n"), 1); + usleep(100 * 1000); + sc_disconnect(); + return SC_RETRY; + } + + if (ret < 0) { + usleep(100 * 1000); + sc_disconnect(); + return SC_RETRY; + } + + recv_buf[ret] = '\0'; + + if ((recv_buf[0] != 'O') || (recv_buf[1] != 'K') || (ret <= 2)) { + if (strstr(strtolower(recv_buf), "invalid password") != NULL) { + if (!error_printed) { + print_info(_("\nConnect: Invalid password!\n"), 1); + } + sc_disconnect(); + if (cfg.main.force_reconnecting == 1) { + error_printed = 1; + return SC_RETRY; + } + else { + return SC_ABORT; + } + } + + sc_disconnect(); + return SC_RETRY; + } + + connected = 1; + error_printed = 0; + + timer_init(&stream_timer, 1); // starts the "online" timer + timer_start(&stream_timer); + + return SC_OK; +} + +int sc_send(char *buf, int buf_len) +{ + int ret; + ret = sock_send(stream_socket, buf, buf_len, SEND_TIMEOUT); + + if (ret == SOCK_TIMEOUT) { + ret = -1; + } + + return ret; +} + +int sc_update_song(char *song_name) +{ + int ret; + int web_socket; + char send_buf[1024]; + char *song_buf; + + web_socket = sock_connect(cfg.srv[cfg.selected_srv]->addr, cfg.srv[cfg.selected_srv]->port, SOCK_PROTO_TCP, CONN_TIMEOUT); + + if (web_socket < 0) { + switch (web_socket) { + case SOCK_ERR_CREATE: + print_info(_("\nUpdate song: Could not create network socket"), 1); + ret = SC_ABORT; + break; + case SOCK_ERR_RESOLVE: + print_info(_("\nUpdate song: Error resolving server address"), 1); + ret = SC_ABORT; + break; + case SOCK_TIMEOUT: + case SOCK_INVALID: + ret = SC_RETRY; + break; + default: + ret = SC_ABORT; + } + + return ret; + } + + song_buf = (char *)malloc(strlen(song_name) * 3 + 1); + uri_encode(song_name, strlen(song_name), song_buf); + + snprintf(send_buf, sizeof(send_buf), + "GET /admin.cgi?pass=%s&mode=updinfo&song=%s&url= HTTP/1.0\r\n" + "User-Agent: ShoutcastDSP (Mozilla Compatible)\r\n", + cfg.srv[cfg.selected_srv]->pwd, song_buf); + + sock_send(web_socket, send_buf, strlen(send_buf), SEND_TIMEOUT); + + if (cfg.srv[cfg.selected_srv]->port == 80) { + snprintf(send_buf, sizeof(send_buf), "Host: %s\r\n\r\n", cfg.srv[cfg.selected_srv]->addr); + } + else { + snprintf(send_buf, sizeof(send_buf), "Host: %s:%d\r\n\r\n", cfg.srv[cfg.selected_srv]->addr, cfg.srv[cfg.selected_srv]->port); + } + + sock_send(web_socket, send_buf, strlen(send_buf), SEND_TIMEOUT); + + sock_close(web_socket); + free(song_buf); + + return SC_OK; +} + +void sc_disconnect(void) +{ + sock_close(stream_socket); +} + +int sc_parse_sc1_response(char *response) +{ + char *listeners; + char *listeners_start; + char *listeners_end; + + // 0,1,1,25,0,128, + // Numbers in comma list mean: + // current_listeners,server_online,peak_listers,max_allowed_isteners,uniq,bitrate,songname + listeners_start = strstr(strtolower(response), ""); + if (listeners_start != NULL) { + listeners_end = strchr(listeners_start, ','); + if (listeners_end != NULL) { + listeners = listeners_start + strlen(""); + *listeners_end = '\0'; + return atoi(listeners); + } + } + + return -1; +} + +int sc_parse_sc2_response(char *response) +{ + char *listeners; + char *listeners_start; + char *listeners_end; + + listeners_start = strstr(strtoupper(response), ""); + listeners_end = strstr(strtoupper(response), ""); + if (listeners_start != NULL && listeners_end != NULL) { + listeners = listeners_start + strlen(""); + *listeners_end = '\0'; + return atoi(listeners); + } + + return -1; +} + +int sc_get_listener_count_from_url(char *url) +{ + uint32_t data_size; + char recv_buf[100 * 1024]; + if (strstr(cfg.srv[cfg.selected_srv]->custom_listener_url, "/stats?sid") != NULL) { + data_size = url_get_listener_count(url, recv_buf, sizeof(recv_buf)); + if (data_size > 0) { + return sc_parse_sc2_response(recv_buf); + } + } + else if (strstr(cfg.srv[cfg.selected_srv]->custom_listener_url, "/7.html") != NULL) { + data_size = url_get_listener_count(url, recv_buf, sizeof(recv_buf)); + if (data_size > 0) { + return sc_parse_sc1_response(recv_buf); + } + } + + return -1; +} + +int sc_get_listener_count(void) +{ + uint32_t data_size; + char *sid; + char url[256]; + char proto[8]; + char recv_buf[100 * 1024]; + + /* + if (cfg.srv[cfg.selected_srv]->tls == 1) { + strncpy(proto, "https", sizeof(proto)); + } + else { + strncpy(proto, "http", sizeof(proto)); + } + */ + strncpy(proto, "http", sizeof(proto)); + + if (server_version == SC_VERSION_2 || server_version == SC_VERSION_UNKNOWN) { + sid = strstr(cfg.srv[cfg.selected_srv]->pwd, ":#"); + if (sid != NULL) { + sid += 2; + snprintf(url, sizeof(url), "%s://%s:%d/stats?sid=%s", proto, cfg.srv[cfg.selected_srv]->addr, cfg.srv[cfg.selected_srv]->port, sid); + } + else { + snprintf(url, sizeof(url), "%s://%s:%d/stats?sid=1", proto, cfg.srv[cfg.selected_srv]->addr, cfg.srv[cfg.selected_srv]->port); + } + + data_size = url_get_listener_count(url, recv_buf, sizeof(recv_buf)); + if (data_size > 0) { + int listener = sc_parse_sc2_response(recv_buf); + if (listener != -1) { + server_version = SC_VERSION_2; + } + return listener; + } + } + + if (server_version == SC_VERSION_1 || server_version == SC_VERSION_UNKNOWN) { + if (cfg.srv[cfg.selected_srv]->custom_listener_url == NULL || strlen(cfg.srv[cfg.selected_srv]->custom_listener_url) == 0) { + snprintf(url, sizeof(url), "%s://%s:%d/7.html", proto, cfg.srv[cfg.selected_srv]->addr, cfg.srv[cfg.selected_srv]->port); + } + else { + snprintf(url, sizeof(url), "%s", cfg.srv[cfg.selected_srv]->custom_listener_url); + } + + data_size = url_get_listener_count(url, recv_buf, sizeof(recv_buf)); + + if (data_size > 0) { + int listener = sc_parse_sc1_response(recv_buf); + if (listener != -1) { + server_version = SC_VERSION_1; + } + return listener; + } + } + + return -1; +} diff --git a/src/shoutcast.h b/src/shoutcast.h new file mode 100644 index 0000000..672bcd4 --- /dev/null +++ b/src/shoutcast.h @@ -0,0 +1,39 @@ +// shoutcast functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef SHOUTCAST_H +#define SHOUTCAST_H + +enum { + SC_OK = 0, + SC_RETRY = 1, + SC_ABORT = 2, + SC_ASK = 3, +}; + +enum { + SC_VERSION_UNKNOWN = 0, + SC_VERSION_1 = 1, + SC_VERSION_2 = 2, +}; + +int sc_update_song(char *song_name); +int sc_connect(void); +int sc_send(char *buf, int buf_len); +void sc_disconnect(void); +int sc_get_listener_count(void); +int sc_get_listener_count_from_url(char *url); + +#endif diff --git a/src/sockfuncs.cpp b/src/sockfuncs.cpp new file mode 100644 index 0000000..11f8653 --- /dev/null +++ b/src/sockfuncs.cpp @@ -0,0 +1,357 @@ +// socket functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include +#include +#include + +#ifdef WIN32 +#include +#include +#undef errno +#undef EWOULDBLOCK +#undef ECONNRESET +#define errno WSAGetLastError() +#define EWOULDBLOCK WSAEWOULDBLOCK +#define ECONNRESET WSAECONNRESET +#else +#include +#include +#include +#include //defines IPPROTO_TCP on BSD +#include +#include +#include +#endif + +#include "sockfuncs.h" + +void sock_init(void) +{ +#ifdef WIN32 + WSADATA wsa; + WSAStartup(MAKEWORD(2, 2), &wsa); +#endif +} + +int sock_connect(const char *addr, unsigned int port, sock_proto_t proto, int timout_ms) +{ + int sock = -1; + int ret; + char port_str[8]; + struct addrinfo hints, *infoptr, *p; // So no need to use memset global variables + + snprintf(port_str, sizeof(port_str), "%d", port); + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == SOCK_PROTO_TCP ? SOCK_STREAM : SOCK_DGRAM; + + if (getaddrinfo(addr, port_str, &hints, &infoptr) != 0) { + return SOCK_ERR_RESOLVE; + } + + for (p = infoptr; p != NULL; p = p->ai_next) { + sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + if (sock == -1) { + continue; + } + + ret = connect(sock, p->ai_addr, p->ai_addrlen); + if (ret == -1) { + sock_close(sock); + continue; + } + + break; + } + + if (sock == -1) { + freeaddrinfo(infoptr); + return SOCK_ERR_CREATE; + } + + if (ret == -1) { + freeaddrinfo(infoptr); + return SOCK_TIMEOUT; + } + + sock_nonblock(sock); + if (sock_select(sock, timout_ms, WRITE) <= 0) { + sock_close(sock); + freeaddrinfo(infoptr); + return SOCK_TIMEOUT; + } + + if (!sock_isvalid(sock)) { + sock_close(sock); + freeaddrinfo(infoptr); + return SOCK_INVALID; + } + + freeaddrinfo(infoptr); + return sock; +} + +int sock_setbufsize(int s, int send_size, int recv_size) +{ + int ret; + socklen_t len = sizeof(send_size); + + if (send_size > 0) { + ret = setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)(&send_size), len); + if (ret) { + return SOCK_ERR_SET_SBUF; + } + } + if (recv_size > 0) { + ret = setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)(&recv_size), len); + if (ret) { + return SOCK_ERR_SET_RBUF; + } + } + + return 0; +} + +int sock_send(int s, const char *buf, int len, int timout_ms) +{ + int rc; + int sent = 0; + + while (sent < len) { + rc = sock_select(s, 10000, WRITE); // check if socket is connected + + if (rc == 0) { + return SOCK_TIMEOUT; + } + + if (rc == -1) { + return SOCK_TIMEOUT; + } + + if ((rc = send(s, buf + sent, len - sent, 0)) < 0) { + if (errno != EWOULDBLOCK) { + return SOCK_TIMEOUT; + } + rc = 0; + } + + sent += rc; + } + return sent; +} + +int sock_recv(int s, char *buf, int len, int timout_ms) +{ + int rc; + + if (sock_select(s, timout_ms, READ) <= 0) { + return SOCK_TIMEOUT; + } + + rc = recv(s, buf, len, 0); + + if (rc == -1 && errno == ECONNRESET) { + return SOCK_ERR_RECV; // The other end has closed the connection with RST + } + if (rc == 0) { + return SOCK_ERR_RECV; // The other end has closed the connection with FIN + } + + return rc; +} + +int sock_recvfrom(int s, char *buf, int len, sock_udp_conn_t *udp_conn, int timout_ms) +{ + int rc; + + if (sock_select(s, timout_ms, READ) <= 0) { + return SOCK_TIMEOUT; + } + + udp_conn->addr_len = sizeof(udp_conn->addr); + rc = recvfrom(s, buf, len, 0, &udp_conn->addr, &udp_conn->addr_len); + + if (rc == -1) { + return SOCK_ERR_RECV; + } + + return rc; +} + +int sock_sendto(int s, const char *buf, int len, sock_udp_conn_t *udp_conn, int timout_ms) +{ + int rc; + int sent = 0; + + while (sent < len) { + rc = sock_select(s, 10000, WRITE); // check if socket is connected + + if (rc == 0) { + return SOCK_TIMEOUT; + } + + if (rc == -1) { + return SOCK_TIMEOUT; + } + + if ((rc = sendto(s, buf + sent, len - sent, 0, &udp_conn->addr, udp_conn->addr_len)) < 0) { + if (errno != EWOULDBLOCK) { + return SOCK_TIMEOUT; + } + rc = 0; + } + + sent += rc; + } + return sent; +} + +int sock_nonblock(int s) +{ +#ifndef WIN32 + long arg; + + arg = fcntl(s, F_GETFL); + arg |= O_NONBLOCK; + + return fcntl(s, F_SETFL, arg); +#else + unsigned long arg = 1; + return ioctlsocket(s, FIONBIO, &arg); +#endif +} + +int sock_block(int s) +{ +#ifndef WIN32 + long arg; + + arg = fcntl(s, F_GETFL); + arg &= ~O_NONBLOCK; + + return fcntl(s, F_SETFL, arg); +#else + unsigned long arg = 0; + return ioctlsocket(s, FIONBIO, &arg); +#endif +} + +int sock_select(int s, int timout_ms, int mode) +{ + struct timeval tv; + fd_set fd_wr, fd_rd; + + FD_ZERO(&fd_wr); + FD_ZERO(&fd_rd); + FD_SET(s, &fd_wr); + FD_SET(s, &fd_rd); + + tv.tv_sec = timout_ms / 1000; + tv.tv_usec = (timout_ms % 1000) * 1000; + + switch (mode) { + case READ: + return select(s + 1, &fd_rd, NULL, NULL, &tv); + break; + case WRITE: + return select(s + 1, NULL, &fd_wr, NULL, &tv); + break; + case RW: + return select(s + 1, &fd_rd, &fd_wr, NULL, &tv); + break; + default: + return SOCK_NO_MODE; + } +} + +int sock_isvalid(int s) +{ + int optval; + socklen_t len = sizeof(optval); + + getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)(&optval), &len); + + if (optval) { + return 0; + } + + return 1; +} + +int sock_listen(int port, int *listen_sock) +{ + int conn_sock; + int val = 1; + + struct sockaddr_in servaddr; + + *listen_sock = socket(AF_INET, SOCK_STREAM, 0); + if (*listen_sock == -1) { + return SOCK_ERR_CREATE; + } + + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(port); + + // Make sure the port can be re-used without waiting for the TIME_WAIT period is over + //(https://stackoverflow.com/questions/3229860/what-is-the-meaning-of-so-reuseaddr-setsockopt-option-linux) + setsockopt(*listen_sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(int)); + + if (bind(*listen_sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) { + return SOCK_ERR_BIND; + } + + if ((listen(*listen_sock, 1)) != 0) { + return SOCK_ERR_LISTEN; + } + + conn_sock = accept(*listen_sock, NULL, NULL); + + if (conn_sock >= 0) { + sock_close(*listen_sock); + } + + return conn_sock; +} + +void sock_close(int s) +{ +#ifdef WIN32 + closesocket(s); +#else + close(s); +#endif +} + +int sock_get_errno(void) +{ + return errno; +} + +// Sends RST instead of FIN +void sock_rst_close(int s) +{ + struct linger ling; + ling.l_onoff = 1; + ling.l_linger = 0; + + setsockopt(s, SOL_SOCKET, SO_LINGER, (const char *)&ling, sizeof(ling)); + + sock_close(s); +} diff --git a/src/sockfuncs.h b/src/sockfuncs.h new file mode 100644 index 0000000..631b92b --- /dev/null +++ b/src/sockfuncs.h @@ -0,0 +1,82 @@ +// socket functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef SOCKFUNCS_H +#define SOCKFUNCS_H + +#ifdef WIN32 +#include +typedef int socklen_t; +#else +#include +#endif + +#define SOCK_MAX_DATAGRAM_SIZE 65535 + +enum { + READ = 0, + WRITE = 1, + RW = 2, +}; + +enum { + SOCK_ERR_CREATE = -1, + SOCK_ERR_RESOLVE = -2, + SOCK_TIMEOUT = -3, + SOCK_INVALID = -4, + SOCK_NO_MODE = -5, + SOCK_ERR_SET_SBUF = -6, + SOCK_ERR_SET_RBUF = -7, + SOCK_ERR_BIND = -8, + SOCK_ERR_LISTEN = -9, + SOCK_ERR_RECV = -10, +}; + +enum { + CONN_TIMEOUT = 1000, + SEND_TIMEOUT = 3000, + RECV_TIMEOUT = 1000, +}; + +typedef enum sock_proto { SOCK_PROTO_TCP = 0, SOCK_PROTO_UDP = 1 } sock_proto_t; + +typedef struct sock_udp_conn { + struct sockaddr addr; + socklen_t addr_len; + +} sock_udp_conn_t; + +void sock_init(void); +int sock_init_udp_server(sock_udp_conn_t *udp_conn); +int sock_connect(const char *addr, unsigned int port, sock_proto_t proto, int timout_ms); +int sock_listen(int port, int *listen_sock); +int sock_setbufsize(int s, int send_size, int recv_size); +int sock_isdisconnected(int s); +int sock_send(int s, const char *buf, int len, int timout_ms); +int sock_sendto(int s, const char *buf, int len, sock_udp_conn_t *udp_conn, int timout_ms); +int sock_recv(int s, char *buf, int len, int timout_ms); +int sock_recvfrom(int s, char *buf, int len, sock_udp_conn_t *udp_conn, int timout_ms); +int sock_select(int s, int timout_ms, int mode); +int sock_nonblock(int s); +int sock_block(int s); +int sock_isvalid(int s); +void sock_close(int s); +void sock_rst_close(int s); +void sock_fdinit(int s); +void sock_fdclr(int s); +void sock_fdzero(void); +int sock_get_errno(void); + +#endif diff --git a/src/strfuncs.cpp b/src/strfuncs.cpp new file mode 100644 index 0000000..64031f8 --- /dev/null +++ b/src/strfuncs.cpp @@ -0,0 +1,227 @@ +// string manipulation functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include +#include +#include +#include "strfuncs.h" + +int strinsrt(char **dest, char *insert, char *pos) +{ + char *pre; + char *post; + char *temp; + int pre_len; + int post_len; + int new_len; + + new_len = strlen(*dest) + strlen(insert); + pre_len = strlen(*dest) - strlen(pos); + post_len = strlen(pos); + + pre = (char *)malloc(pre_len * sizeof(char) + 1); + post = (char *)malloc(post_len * sizeof(char) + 1); + temp = (char *)malloc(new_len * sizeof(char) + 1); + + memcpy(pre, *dest, pre_len); + pre[pre_len] = '\0'; + + memcpy(post, *dest + pre_len, post_len); + post[post_len] = '\0'; + + sprintf(temp, "%s%s%s", pre, insert, post); + + *dest = (char *)realloc(*dest, new_len * sizeof(char) + 1); + strcpy(*dest, temp); + + free(pre); + free(post); + free(temp); + + return 0; +} + +// returns a pointer to the last occurance of string "needle" in string "haystack" +char *strrstr(char *haystack, char *needle) +{ + char *last; + char *found = NULL; + + do { + last = found; + found = strstr(haystack, needle); + + if (found != NULL) { + haystack = found + strlen(needle); + } + + } while (found != NULL); + + return last; +} + +// replaces all strings named by search with strings named by replace in dest +int strrpl(char **dest, char *search, char *replace, int mode) +{ + char *loc; + char *temp; + char *orig; + char *result; + int search_len, repl_len, diff; + int size; + int count; + + // do nothing if there is not at least one string of "search" in "*dest" + if (strstr(*dest, search) == NULL) { + return -1; + } + + search_len = strlen(search); + repl_len = strlen(replace); + diff = repl_len - search_len; + + // how many strings do we need to replace? + if (mode == MODE_ALL) { + temp = *dest; + for (count = 0; (temp = strstr(temp, search)); count++) { + temp += search_len; + } + } + else { + count = 1; + } + + // length of the new string + size = strlen(*dest) + (diff * count); + + temp = strdup(*dest); + orig = temp; + + result = (char *)malloc(size * sizeof(char) + 1); + if (!result) { + free(orig); + return -1; + } + memset(result, 0, size); + + // build the new string + switch (mode) { + case MODE_ALL: + while ((loc = strstr(temp, search))) { + strncat(result, temp, loc - temp); + strcat(result, replace); + temp = loc + strlen(search); + } + // append remaining characaters (if any) + if (strlen(temp) > 0) { + strcat(result, temp); + } + break; + + case MODE_FIRST: + loc = strstr(temp, search); + strncat(result, temp, loc - temp); + strcat(result, replace); + + temp = loc + strlen(search); + // append remaining characters + if (strlen(temp) > 0) { + strcat(result, temp); + } + break; + case MODE_LAST: + loc = strrstr(temp, search); + strncat(result, temp, loc - temp); + strcat(result, replace); + + temp = loc + strlen(search); + // append remaininc characaters (if any) + if (strlen(temp) > 0) { + strcat(result, temp); + } + + break; + default: + return -1; + } + + if (strlen(result) > strlen(*dest)) { + *dest = (char *)realloc(*dest, size * sizeof(char) + 1); + if (!*dest) { + free(result); + free(orig); + return -1; + } + } + + // save the new string back to orig position in memory + strcpy(*dest, result); + + free(orig); + free(result); + + return 0; +} + +char *strtolower(char *str) +{ + if (str != NULL) { + for (int i = 0; i < strlen(str); i++) { + str[i] = tolower(str[i]); + } + } + + return str; +} + +char *strtoupper(char *str) +{ + if (str != NULL) { + for (int i = 0; i < strlen(str); i++) { + str[i] = toupper(str[i]); + } + } + + return str; +} + +// "Percent encode" reserved characters according to RFC3986 section 2.2 for use in URIs +void strencoderfc3986(char **buf) +{ + /* Reserved characters: % :/?#[]@!$&'()*+,;= */ + /* Results in: %3d%20%3a%2f%3f%23%5b%5d%40%21%24%26%27%28%29%2a%2b%2c%3b%25 */ + + strrpl(buf, (char *)"%", (char *)"%25", MODE_ALL); // this must come first + strrpl(buf, (char *)" ", (char *)"%20", MODE_ALL); + strrpl(buf, (char *)":", (char *)"%3a", MODE_ALL); + strrpl(buf, (char *)"/", (char *)"%2f", MODE_ALL); + strrpl(buf, (char *)"?", (char *)"%3f", MODE_ALL); + strrpl(buf, (char *)"#", (char *)"%23", MODE_ALL); + strrpl(buf, (char *)"[", (char *)"%5b", MODE_ALL); + strrpl(buf, (char *)"]", (char *)"%5d", MODE_ALL); + strrpl(buf, (char *)"@", (char *)"%40", MODE_ALL); + strrpl(buf, (char *)"!", (char *)"%21", MODE_ALL); + strrpl(buf, (char *)"$", (char *)"%24", MODE_ALL); + strrpl(buf, (char *)"&", (char *)"%26", MODE_ALL); + strrpl(buf, (char *)"'", (char *)"%27", MODE_ALL); + strrpl(buf, (char *)"(", (char *)"%28", MODE_ALL); + strrpl(buf, (char *)")", (char *)"%29", MODE_ALL); + strrpl(buf, (char *)"*", (char *)"%2a", MODE_ALL); + strrpl(buf, (char *)"+", (char *)"%2b", MODE_ALL); + strrpl(buf, (char *)",", (char *)"%2c", MODE_ALL); + strrpl(buf, (char *)";", (char *)"%3b", MODE_ALL); + strrpl(buf, (char *)"=", (char *)"%3d", MODE_ALL); +} diff --git a/src/strfuncs.h b/src/strfuncs.h new file mode 100644 index 0000000..639a758 --- /dev/null +++ b/src/strfuncs.h @@ -0,0 +1,43 @@ +// string manipulation functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef STRFUNCS_H +#define STRFUNCS_H + +enum { + MODE_ALL = 0, + MODE_FIRST = 1, + MODE_LAST = 2, +}; + +// replaces all strings "replace" with "search" in "dest" +int strrpl(char **dest, char *search, char *replace, int mode); + +// inserts string "insert" at position "pos" +int strinsrt(char **dest, char *insert, char *pos); + +// finds last occurrence of substring "needle" in string "haystack" +char *strrstr(char *haystack, char *needle); + +// "Percent encode" reserved characters according to RFC3986 section 2.2 for use in URIs +void strencoderfc3986(char **buf); + +// Converts string "str" to lower case variant +char *strtolower(char *str); + +// Converts string "str" to upper case variant +char *strtoupper(char *str); + +#endif diff --git a/src/timer.cpp b/src/timer.cpp new file mode 100644 index 0000000..74f4e67 --- /dev/null +++ b/src/timer.cpp @@ -0,0 +1,90 @@ +// timer related functions +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include + +#include "timer.h" + +void timer_init(timer_ms_t *t, float duration) +{ + t->duration = duration; + t->is_running = false; +} + +void timer_start(timer_ms_t *t) +{ + t->start_time = timer_get_cur_time(); + t->new_time = t->start_time; + t->is_running = true; +} + +int timer_is_elapsed(timer_ms_t *t) +{ + uint64_t cur_time = timer_get_cur_time(); + uint64_t duration = t->duration * 1000; + + if (cur_time >= t->new_time + duration) { + t->new_time = timer_get_cur_time(); + return 1; + } + else { + return 0; + } +} + +char *timer_get_time_str(timer_ms_t *t) +{ + static char time_str[64]; + long hour = 0, min = 0, sec = 0; + uint64_t cur_time = timer_get_cur_time(); + + sec = (cur_time - t->start_time) / 1000; + + min = sec / 60; + hour = min / 60; + min %= 60; + sec %= 60; + + snprintf(time_str, sizeof(time_str), "%02ld:%02ld:%02ld", hour, min, sec); + + return time_str; +} + +float timer_get_elapsed_time(timer_ms_t *t) +{ + uint64_t diff_time = timer_get_cur_time() - t->start_time; + return float(diff_time / 1000.0); +} + +void timer_reset(timer_ms_t *t) +{ + t->is_running = false; + t->start_time = timer_get_cur_time(); + t->new_time = t->start_time; +} + +void timer_stop(timer_ms_t *t) +{ + t->is_running = false; +} + +uint64_t timer_get_cur_time(void) +{ + struct timeval time; + gettimeofday(&time, NULL); + + return (uint64_t)time.tv_sec * 1000 + time.tv_usec / 1000; +} diff --git a/src/timer.h b/src/timer.h new file mode 100644 index 0000000..59ef3de --- /dev/null +++ b/src/timer.h @@ -0,0 +1,39 @@ +// timer related functions +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef TIMER_H +#define TIMER_H + +#include +#include +#include + +typedef struct timer_ms { + uint64_t start_time; + uint64_t new_time; + float duration; + bool is_running = false; +} timer_ms_t; + +void timer_init(timer_ms_t *t, float duration); +void timer_start(timer_ms_t *t); +int timer_is_elapsed(timer_ms_t *t); +char *timer_get_time_str(timer_ms_t *t); +float timer_get_elapsed_time(timer_ms_t *t); +uint64_t timer_get_cur_time(void); +void timer_reset(timer_ms_t *t); +void timer_stop(timer_ms_t *t); + +#endif diff --git a/src/tls.cpp b/src/tls.cpp new file mode 100644 index 0000000..e649ccb --- /dev/null +++ b/src/tls.cpp @@ -0,0 +1,461 @@ +// OpenSSL functions for butt +// +// Copyright 2020 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +// This OpenSSL implementation is based on the implementation of libshout 2.4.3 https://icecast.org/download/ + +#include "gettext.h" +#include "config.h" + +#ifdef HAVE_LIBSSL + +#include +#include +#include +#ifndef WIN32 +#include +#endif + +#ifdef __APPLE__ +#include // for dirname +#include // for _NSGetExecutablePath +#endif + +#include +#include + +#include + +#include "tls.h" +#include "sockfuncs.h" + +// #define DEBUG 1 + +// https://en.wikibooks.org/wiki/OpenSSL/Error_handling +// #undef HAVE_X509_CHECK_HOST + +#ifdef DEBUG +FILE *fd; +static void key_log_cb(const SSL *ssl, const char *line) +{ + fprintf(fd, "%s\n", line); +} +#endif + +static void set_error(tls_t *tls, const char *err_msg) +{ + int len = (int)strlen(err_msg) + 1; + tls->last_err = (char *)realloc(tls->last_err, len); + snprintf(tls->last_err, len, "%s", err_msg); +} + +static void clr_error(tls_t *tls) +{ + set_error(tls, "No error"); +} + +/* +static void print_error_stack(void) +{ + BIO *bio = BIO_new(BIO_s_mem ()); + ERR_print_errors(bio); + char *buf = NULL; + BIO_get_mem_data(bio, &buf); + printf("%s\n", buf); + BIO_free (bio); +} + + +static int get_peer_certificate_chain(tls_t *tls, char **buf) +{ + int certs; + unsigned char *data; + unsigned int len; + BIO *bio; + STACK_OF(X509) *chain; + + chain = SSL_get_peer_cert_chain(tls->ssl); + certs = sk_X509_num(chain); + + if (certs == 0) { + return TLS_NOCERT; + } + + bio = BIO_new(BIO_s_mem()); + if (bio == 0) { + return TLS_MALLOC; + } + + for (int i = 0; i < certs; i++) + { + X509 *cert = sk_X509_value(chain, i); + PEM_write_bio_X509(bio, cert); + } + + len = (unsigned int)BIO_get_mem_data(bio, &data); + + if (len) { + *buf = (char*)malloc(len + 1); + memcpy(*buf, data, len); + (*buf)[len] = 0; + } + + BIO_free(bio); + return TLS_OK; +} +*/ + +#ifndef HAVE_X509_CHECK_HOST +static int check_pattern(const char *key, const char *pattern) +{ + for (; *key && *pattern; key++) { + if (*pattern == '*') { + for (; *pattern == '*'; pattern++) + ; + + for (; *key && *key != '.'; key++) + ; + + if (!*pattern && !*key) { + return 1; + } + if (!*pattern || !*key) { + return 0; + } + } + + if (tolower(*key) != tolower(*pattern)) { + return 0; + } + pattern++; + } + return *key == 0 && *pattern == 0; +} +#endif + +#ifndef HAVE_X509_CHECK_HOST +static int check_host(tls_t *tls, X509 *cert) +{ + char common_name[256] = ""; + X509_NAME *xname = X509_get_subject_name(cert); + X509_NAME_ENTRY *xentry; + ASN1_STRING *sdata; + int i, j; + int ret; + + ret = X509_NAME_get_text_by_NID(xname, NID_commonName, common_name, sizeof(common_name)); + if (ret < 1 || (size_t)ret >= (sizeof(common_name) - 1)) { + set_error(tls, _("check_host: could not read host name from cert")); + return TLS_HOSTERR; + } + + if (!check_pattern(tls->host, common_name)) { + return TLS_HOSTERR; + } + + /* check for inlined \0, + * see https://www.blackhat.com/html/bh-usa-09/bh-usa-09-archives.html#Marlinspike + */ + for (i = -1;; i = j) { + j = X509_NAME_get_index_by_NID(xname, NID_commonName, i); + if (j == -1) { + break; + } + } + + xentry = X509_NAME_get_entry(xname, i); + sdata = X509_NAME_ENTRY_get_data(xentry); + + if ((size_t)ASN1_STRING_length(sdata) != strlen(common_name)) { + return TLS_HOSTERR; + } + + return TLS_OK; +} +#endif + +static int check_cert(tls_t *tls) +{ + long ret; + X509 *cert = SSL_get_peer_certificate(tls->ssl); + + if (cert == NULL) { + set_error(tls, _("check_cert: No peer certificate available")); + return TLS_NOCERT; + } + + if ((ret = SSL_get_verify_result(tls->ssl)) != X509_V_OK) { + X509_free(cert); + set_error(tls, X509_verify_cert_error_string(ret)); + return TLS_CHECK_CERT; + } + +#ifdef HAVE_X509_CHECK_HOST + if (X509_check_host(cert, tls->host, 0, 0, NULL) != 1) { + X509_free(cert); + set_error(tls, _("check_cert: X509_check_host failed")); + return TLS_CHECK_HOST; + } +#else + if (check_host(tls, cert) != TLS_OK) { + X509_free(cert); + set_error(tls, _("check_cert: check_host failed")); + return TLS_CHECK_HOST; + } +#endif + + X509_free(cert); + return TLS_OK; +} + +static int calc_cert_hash(tls_t *tls) +{ + const uint32_t len = 32; + char byte[3]; + uint8_t sha256_val[len]; + X509 *cert = SSL_get_peer_certificate(tls->ssl); + if (cert == NULL) { + set_error(tls, _("calc_cert_hash: No peer certificate available")); + return TLS_NOCERT; + } + + // Calc hash + if (X509_digest(cert, EVP_get_digestbyname("sha256"), sha256_val, NULL) != 1) { + X509_free(cert); + set_error(tls, _("calc_cert_hash: Hash calculation failed")); + return TLS_CERTERR; + } + + // Convert hash to a char array + memset(tls->sha256, 0, sizeof(tls->sha256)); + for (uint32_t i = 0; i < len; ++i) { + snprintf(byte, sizeof(byte), "%02X", sha256_val[i]); + memcpy(tls->sha256 + 2 * i, byte, 2); + } + + X509_free(cert); + return TLS_OK; +} + +int tls_setup(tls_t *tls) +{ + int ret = 0; + long ssl_opts = 0; + + tls->ssl = NULL; + tls->ssl_ctx = NULL; + tls->last_err = NULL; + +// Checks for OpenSSL version < 1.1.x +#if OPENSSL_VERSION_NUMBER < 0x10100000L + SSL_library_init(); + SSL_load_error_strings(); + // SSLeay_add_all_algorithms(); + // SSLeay_add_ssl_algorithms(); + + tls->ssl_ctx = SSL_CTX_new(TLSv1_client_method()); + ssl_opts |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; +#else + tls->ssl_ctx = SSL_CTX_new(TLS_client_method()); + SSL_CTX_set_min_proto_version(tls->ssl_ctx, TLS1_VERSION); +#endif + + // Compression is dangerous -> https://en.wikipedia.org/wiki/CRIME + ssl_opts |= SSL_OP_NO_COMPRESSION; + + SSL_CTX_set_options(tls->ssl_ctx, ssl_opts); + SSL_CTX_set_default_verify_paths(tls->ssl_ctx); + + // Add cert file and directory separately. + // So in case one contains a invalid path, the other will still work + SSL_CTX_load_verify_locations(tls->ssl_ctx, tls->cert_file, NULL); + SSL_CTX_load_verify_locations(tls->ssl_ctx, NULL, tls->cert_dir); + +#ifdef __APPLE__ + char path_to_executeable[PATH_MAX]; + char path_to_ca_file[PATH_MAX]; + + uint32_t path_len = (uint32_t)sizeof(path_to_executeable); + if (_NSGetExecutablePath(path_to_executeable, &path_len) == 0) { + char *folder_of_executable = strdup(dirname(path_to_executeable)); + snprintf(path_to_ca_file, PATH_MAX, "%s%s", folder_of_executable, "/../Resources/cacert.pem"); + free(folder_of_executable); + SSL_CTX_load_verify_locations(tls->ssl_ctx, path_to_ca_file, NULL); + } +#endif +#ifdef WIN32 + SSL_CTX_load_verify_locations(tls->ssl_ctx, "cacert.pem", NULL); +#endif + + // We verify by ourself later + SSL_CTX_set_verify(tls->ssl_ctx, SSL_VERIFY_NONE, NULL); + + if (SSL_CTX_set_cipher_list(tls->ssl_ctx, ALLOWED_CIPHERS) != 1) { + set_error(tls, _("tls_setup: Could not set cipher list")); + return TLS_UNSPECIFICERR; + } + + SSL_CTX_set_mode(tls->ssl_ctx, SSL_MODE_AUTO_RETRY); + +#ifdef DEBUG + fd = fopen("/Users/bip/tls_key.txt", "ab"); + SSL_CTX_set_keylog_callback(tls->ssl_ctx, key_log_cb); +#endif + + tls->ssl = SSL_new(tls->ssl_ctx); + if (tls->ssl == NULL) { + set_error(tls, _("tls_setup: SSL_new failed")); + return TLS_UNSPECIFICERR; + } + + // Connect ssl to our socket (creates an internal BIO and inherits blocking/non-blocking from the socket) + if (SSL_set_fd(tls->ssl, tls->socket) == 0) { + set_error(tls, _("tls_setup: Could not bind socket to SSL")); + return TLS_UNSPECIFICERR; + } + + SSL_set_tlsext_host_name(tls->ssl, tls->host); + + // Set SSL to client mode + SSL_set_connect_state(tls->ssl); + + while ((ret = SSL_connect(tls->ssl)) != 1) { + int err; + switch (err = SSL_get_error(tls->ssl, ret)) { + case SSL_ERROR_WANT_READ: + if (sock_select(tls->socket, 5000, READ) <= 0) { + set_error(tls, _("tls_setup: SSL_connect read timeout")); + return TLS_TIMEOUT; + } + break; + case SSL_ERROR_WANT_WRITE: + if (sock_select(tls->socket, 5000, WRITE) <= 0) { + set_error(tls, _("tls_setup: SSL_connect write timeout")); + return TLS_TIMEOUT; + } + break; + case SSL_ERROR_SYSCALL: // Can occour if the server goes down and a reconnection attempt fails + return TLS_TIMEOUT; // Try again + break; + default: + printf("SSL_connect error: %d\n", err); + fflush(stdout); + // print_error_stack(); + set_error(tls, ERR_error_string(err, NULL)); + return TLS_CONNETERR; + } + } + + if (calc_cert_hash(tls) != TLS_OK) { + set_error(tls, _("tls_setup: Cert hash could not be calculated")); + return TLS_CERTERR; + } + + if ((tls->skip_verification == 0) && ((ret = check_cert(tls)) != TLS_OK)) { + return ret; + } + +#ifdef DEBUG + fclose(fd); +#endif + clr_error(tls); + return TLS_OK; +} + +int tls_send(tls_t *tls, char *buf, int len, int timeout_ms) +{ + int ret; + tls->state = TLS_STATE_SENDING; + while ((tls->ssl != NULL) && ((ret = SSL_write(tls->ssl, buf, len)) <= 0)) { + int err; + switch (err = SSL_get_error(tls->ssl, ret)) { + case SSL_ERROR_WANT_READ: + if (sock_select(tls->socket, timeout_ms, READ) <= 0) { + set_error(tls, _("tls_send: read timeout")); + tls->state = TLS_STATE_IDLE; + return TLS_TIMEOUT; + } + break; + case SSL_ERROR_WANT_WRITE: + if (sock_select(tls->socket, timeout_ms, WRITE) <= 0) { + set_error(tls, _("tls_send: write timeout")); + tls->state = TLS_STATE_IDLE; + return TLS_TIMEOUT; + } + break; + default: + // Occurs if server goes down. Reconnection will be initiated + set_error(tls, ERR_error_string(err, NULL)); + tls->state = TLS_STATE_IDLE; + return TLS_SENDERR; + } + } + + tls->state = TLS_STATE_IDLE; + return TLS_OK; +} + +int tls_recv(tls_t *tls, char *buf, int len, int timeout_ms) +{ + int ret; + tls->state = TLS_STATE_RECEIVING; + while ((ret = SSL_read(tls->ssl, buf, len)) <= 0) { + int err; + switch (err = SSL_get_error(tls->ssl, ret)) { + case SSL_ERROR_WANT_READ: + if (sock_select(tls->socket, timeout_ms, READ) <= 0) { + set_error(tls, _("tls_recv: read timeout")); + tls->state = TLS_STATE_IDLE; + return TLS_TIMEOUT; + } + break; + case SSL_ERROR_WANT_WRITE: + if (sock_select(tls->socket, timeout_ms, WRITE) <= 0) { + set_error(tls, _("tls_recv: write timeout")); + tls->state = TLS_STATE_IDLE; + return TLS_TIMEOUT; + } + break; + default: + set_error(tls, ERR_error_string(err, NULL)); + tls->state = TLS_STATE_IDLE; + return TLS_RECVERR; + } + } + + tls->state = TLS_STATE_IDLE; + return ret; +} + +void tls_close(tls_t *tls) +{ + // Make sure we don't free anything while the tls system is working + while (tls->state != TLS_STATE_IDLE) + ; + + if (tls->ssl) { + SSL_shutdown(tls->ssl); + SSL_free(tls->ssl); + tls->ssl = NULL; + } + if (tls->ssl_ctx) { + SSL_CTX_free(tls->ssl_ctx); + tls->ssl_ctx = NULL; + } + if (tls->last_err != NULL) { + free(tls->last_err); + tls->last_err = NULL; + } +} +#endif diff --git a/src/tls.h b/src/tls.h new file mode 100644 index 0000000..72b2a61 --- /dev/null +++ b/src/tls.h @@ -0,0 +1,65 @@ +// OpenSSL functions for butt +// +// Copyright 2020 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// + +#ifndef TLS_H +#define TLS_H + +#include + +/* Mozilla's 'Intermediate' list as of 2015-04-19 */ +#define ALLOWED_CIPHERS \ + "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA" + +enum err { + TLS_OK = 0, + TLS_MALLOC = -1, + TLS_NOCERT = -2, + TLS_CERTERR = -3, + TLS_HOSTERR = -4, + TLS_UNSPECIFICERR = -5, + TLS_CONNETERR = -6, + TLS_SENDERR = -7, + TLS_RECVERR = -8, + TLS_TIMEOUT = -9, + TLS_CHECK_HOST = -10, + TLS_CHECK_CERT = -11, +}; + +enum state { + TLS_STATE_IDLE = 0, + TLS_STATE_SENDING = 1, + TLS_STATE_RECEIVING = 2, +}; + +typedef struct tls { + SSL_CTX *ssl_ctx; + SSL *ssl; + char *host; + char *last_err; + char *cert_file; + char *cert_dir; + char sha256[65]; + int socket; + int skip_verification; + int state; +} tls_t; + +int tls_setup(tls_t *tls); +int tls_send(tls_t *tls, char *buf, int len, int timeout_ms); +int tls_recv(tls_t *tls, char *buf, int len, int timeout_ms); +void tls_close(tls_t *tls); + +#endif diff --git a/src/tray_agent.cpp b/src/tray_agent.cpp new file mode 100644 index 0000000..e33c00c --- /dev/null +++ b/src/tray_agent.cpp @@ -0,0 +1,237 @@ + +// tray agent functions for butt +// +// Copyright 2007-2021 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifdef WIN32 +#include +#include +#include + +#include "flgui.h" +#include "cfg.h" +#include "config.h" +#include "butt.h" +#include "sha256.h" +#include "tray_agent.h" + +#define AGENT_CLASS "AutoHotkeyGUI" +#define AGENT_TITLE "buttTrayAgent11-03-2021" +#define AGENT_SHA256 "80015491aabc0b6a3470cd375d8304a5b4446b2ee88929e552c03676ca877f53" +#define AGENT_EXECUTABLE "butt_agent.exe" + +static char song_buf[512]; + +static int check_hash(void) +{ + char agent_sha256[65]; + const int salt = 0xA50D; + + if (sha256_file((char *)AGENT_EXECUTABLE, agent_sha256, salt) == 0) { + // #warning "REMOVE THIS RETURN FOR PRODUCTION" + // printf("agent hash: %s\n", agent_sha256); + // return 0; + // #warning "REMOVE THIS RETURN FOR PRODUCTION" + + if (strncmp(agent_sha256, AGENT_SHA256, 64) == 0) { + return 0; // correct hash found + } + } + + return 1; // error +} + +static int send_msg(char *cmsg) +{ + COPYDATASTRUCT MyCDS; + wchar_t wmsg[512]; + + // Convert normal char array to wide char array + mbstowcs(wmsg, cmsg, 512); + + MyCDS.dwData = 0; + MyCDS.cbData = sizeof(wmsg); + MyCDS.lpData = &wmsg; + + // Get handle of butt main window + HWND hwButt = fl_xid(fl_g->window_main); + HWND hwAgent; + + if (tray_agent_is_running(&hwAgent) == 1) { + SendMessage(hwAgent, WM_COPYDATA, (WPARAM)(HWND)hwButt, (LPARAM)(LPVOID)&MyCDS); + return 0; + } + else { + return 1; + } +} + +int tray_agent_start(void) +{ + char command[32]; + STARTUPINFOA si; + PROCESS_INFORMATION pi; + + // Do not start if it is already running + if (tray_agent_is_running(NULL) == 1) { + return 1; + } + + if (check_hash() != 0) { + return 1; // agent has wrong hash. Do not execute it! + } + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + + snprintf(command, sizeof(command), "%s -s", AGENT_EXECUTABLE); + + if (CreateProcessA(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) != 0) { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + struct timespec wait_50ms; + wait_50ms.tv_sec = 0; + wait_50ms.tv_nsec = (50 * 1000 * 1000); + + // Wait max 40*50 ms = 2 seconds until agent has been started + int timed_out = 1; + for (int i = 0; i < 40; i++) { + if (tray_agent_is_running(NULL) == 1) { + timed_out = 0; + break; + } + nanosleep(&wait_50ms, NULL); + } + if (timed_out == 1) { + return 1; // error: tray agent still not running + } + else { + return 0; + } + } + else { + return 1; + } +} + +int tray_agent_is_running(HWND *hwAgent) +{ + HWND hwWindow = FindWindow(AGENT_CLASS, AGENT_TITLE); + + if (hwWindow != NULL) { + if (hwAgent != NULL) { + *hwAgent = hwWindow; + } + + return 1; + } + else { + return 0; + } +} + +void tray_agent_set_song(char *song) +{ + snprintf(song_buf, sizeof(song_buf), "%s", song); +} + +int tray_agent_send_cmd(int cmd) +{ + char msg[512]; + char tray_title[128]; + char custom_window_title[128]; + int minimize; + + int pid = GetCurrentProcessId(); + + if (cfg.gui.window_title[0] != '\0') { + snprintf(custom_window_title, sizeof(custom_window_title), "%s", cfg.gui.window_title); + } + else { + snprintf(custom_window_title, sizeof(custom_window_title), "dummy"); + } + + if (cfg.main.num_of_srv > 0) { + snprintf(tray_title, sizeof(tray_title), "%s", cfg.srv[cfg.selected_srv]->name); + } + else { + snprintf(tray_title, sizeof(tray_title), "%s", "no server"); + } + + switch (cmd) { + case TA_MINIMIZE: + // Start agent when minimizing and agent is not running yet + if (tray_agent_is_running(NULL) == 0) { + if (tray_agent_start() != 0) { + return 1; // Tray agent could not be started + } + } + minimize = 1; + snprintf(msg, sizeof(msg), "%s\t%d\t%d\t%s\t%d\t%s", VERSION, minimize, pid, tray_title, connected, custom_window_title); + break; + case TA_START: + case TA_SERVER_NAME: + case TA_CONNECT_STATE: + minimize = 0; + snprintf(msg, sizeof(msg), "%s\t%d\t%d\t%s\t%d\t%s", VERSION, minimize, pid, tray_title, connected, custom_window_title); + break; + case TA_SONG_UPDATE: + minimize = 0; + snprintf(msg, sizeof(msg), "%s\t%d\t%d\t%s\t%d\t%s\t%s", VERSION, minimize, pid, tray_title, connected, custom_window_title, song_buf); + break; + default: + return 1; + } + + int ret = send_msg(msg); + if ((ret == 0) && (minimize == 1)) { + if (fl_g->window_cfg->shown()) // Close settings window when minimizing to tray + { + fl_g->window_cfg->hide(); + Fl::remove_timeout(&cfg_win_pos_timer); + } + } + + return ret; +} + +int tray_agent_stop(void) +{ + char command[32]; + STARTUPINFOA si; + PROCESS_INFORMATION pi; + + if (check_hash() != 0) { + return 1; // Agent has wrong hash. Do not execute it! + } + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + + snprintf(command, sizeof(command), "%s -q", AGENT_EXECUTABLE); + + if (CreateProcessA(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) != 0) { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return 0; + } + else { + return 1; // CreateProcessA failed + } +} + +#endif // ifdef WIN32 diff --git a/src/tray_agent.h b/src/tray_agent.h new file mode 100644 index 0000000..03d497c --- /dev/null +++ b/src/tray_agent.h @@ -0,0 +1,36 @@ +// tray agent functions for butt +// +// Copyright 2007-2021 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +#ifndef TRAY_AGENT_H +#define TRAY_AGENT_H + +#ifdef WIN32 +#include + +enum tray_agent_cmd { + TA_START = 0, + TA_MINIMIZE = 1, + TA_SERVER_NAME = 2, + TA_CONNECT_STATE = 3, + TA_SONG_UPDATE = 4, +}; + +int tray_agent_start(void); +int tray_agent_stop(void); +int tray_agent_send_cmd(int cmd); +int tray_agent_is_running(HWND *hwAgent); +void tray_agent_set_song(char *song); + +#endif // ifdef WIN32 +#endif // ifndef TRAY_AGENT_H diff --git a/src/update.cpp b/src/update.cpp new file mode 100644 index 0000000..fd65b90 --- /dev/null +++ b/src/update.cpp @@ -0,0 +1,54 @@ +#include +#include + +#include "config.h" +#include "update.h" +#include "sockfuncs.h" +#include "url.h" + +char new_version[16]; + +int update_check_for_new_version(void) +{ + int ret; + char response[1024]; + + memset(new_version, 0, sizeof(new_version)); + + ret = url_get("http://danielnoethen.de/latest_butt", NULL, response, sizeof(response)); + + if (ret <= 0) { + return UPDATE_ILLEGAL_ANSWER; + } + + response[ret] = '\0'; + + char *p = strstr(response, "version: "); + if (p == NULL) { + return UPDATE_ILLEGAL_ANSWER; + } + + p += strlen("version: "); + + if (p[strlen(p) - 1] == '\n') { + p[strlen(p) - 1] = '\0'; + } + + int major_cur, minor_cur, patch_cur; + int major_new, minor_new, patch_new; + sscanf(VERSION, "%d.%d.%d", &major_cur, &minor_cur, &patch_cur); + sscanf(p, "%d.%d.%d", &major_new, &minor_new, &patch_new); + + if ((major_new > major_cur) || (major_new == major_cur && minor_new > minor_cur) || + (major_new == major_cur && minor_new == minor_cur && patch_new > patch_cur)) { + snprintf(new_version, sizeof(new_version) - 1, "%s", p); + return UPDATE_NEW_VERSION; + } + + return UPDATE_UP_TO_DATE; +} + +char *update_get_version(void) +{ + return new_version; +} diff --git a/src/update.h b/src/update.h new file mode 100644 index 0000000..1fcaaa2 --- /dev/null +++ b/src/update.h @@ -0,0 +1,14 @@ +#ifndef UPDATE_H +#define UPDATE_H + +int update_check_for_new_version(void); +char *update_get_version(void); + +enum { + UPDATE_NEW_VERSION = 0, + UPDATE_SOCKET_ERROR = -1, + UPDATE_ILLEGAL_ANSWER = -2, + UPDATE_UP_TO_DATE = -3, +}; + +#endif diff --git a/src/uri_encode.cpp b/src/uri_encode.cpp new file mode 100644 index 0000000..0597065 --- /dev/null +++ b/src/uri_encode.cpp @@ -0,0 +1,53 @@ +#include +#include +#include +#include "uri_encode.h" + +/* + uri_encode.c - functions for URI percent encoding / decoding +*/ + +size_t uri_encode(const char *src, const size_t len, char *dst) +{ + size_t i = 0, j = 0; + while (i < len) { + const char octet = src[i++]; + const int32_t code = ((int32_t *)uri_encode_tbl)[(unsigned char)octet]; + if (code) { + dst[j++] = (char)((code >> 0) & 0xFF); + dst[j++] = (char)((code >> 8) & 0xFF); + dst[j++] = (char)((code >> 16) & 0xFF); + } + else + dst[j++] = octet; + } + dst[j] = '\0'; + return j; +} + +size_t uri_decode(const char *src, const size_t len, char *dst) +{ + size_t i = 0, j = 0; + while (i < len) { + int copy_char = 1; + if (src[i] == '%' && i + 2 < len) { + const unsigned char v1 = hexval[(unsigned char)src[i + 1]]; + const unsigned char v2 = hexval[(unsigned char)src[i + 2]]; + + /* skip invalid hex sequences */ + if ((v1 | v2) != 0xFF) { + dst[j] = (v1 << 4) | v2; + j++; + i += 3; + copy_char = 0; + } + } + if (copy_char) { + dst[j] = src[i]; + i++; + j++; + } + } + dst[j] = '\0'; + return j; +} diff --git a/src/uri_encode.h b/src/uri_encode.h new file mode 100644 index 0000000..a94bf35 --- /dev/null +++ b/src/uri_encode.h @@ -0,0 +1,50 @@ +#include +#include + +// clang-format off +#define _______ "\0\0\0\0" +static const char uri_encode_tbl[ sizeof(int32_t) * 257 ] = { +/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + "%00\0" "%01\0" "%02\0" "%03\0" "%04\0" "%05\0" "%06\0" "%07\0" "%08\0" "%09\0" "%0A\0" "%0B\0" "%0C\0" "%0D\0" "%0E\0" "%0F\0" /* 0: 0 ~ 15 */ + "%10\0" "%11\0" "%12\0" "%13\0" "%14\0" "%15\0" "%16\0" "%17\0" "%18\0" "%19\0" "%1A\0" "%1B\0" "%1C\0" "%1D\0" "%1E\0" "%1F\0" /* 1: 16 ~ 31 */ + "%20\0" "%21\0" "%22\0" "%23\0" "%24\0" "%25\0" "%26\0" "%27\0" "%28\0" "%29\0" "%2A\0" "%2B\0" "%2C\0" _______ _______ "%2F\0" /* 2: 32 ~ 47 */ + _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ "%3A\0" "%3B\0" "%3C\0" "%3D\0" "%3E\0" "%3F\0" /* 3: 48 ~ 63 */ + "%40\0" _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ /* 4: 64 ~ 79 */ + _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ "%5B\0" "%5C\0" "%5D\0" "%5E\0" _______ /* 5: 80 ~ 95 */ + "%60\0" _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ /* 6: 96 ~ 111 */ + _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ _______ "%7B\0" "%7C\0" "%7D\0" _______ "%7F\0" /* 7: 112 ~ 127 */ + "%80\0" "%81\0" "%82\0" "%83\0" "%84\0" "%85\0" "%86\0" "%87\0" "%88\0" "%89\0" "%8A\0" "%8B\0" "%8C\0" "%8D\0" "%8E\0" "%8F\0" /* 8: 128 ~ 143 */ + "%90\0" "%91\0" "%92\0" "%93\0" "%94\0" "%95\0" "%96\0" "%97\0" "%98\0" "%99\0" "%9A\0" "%9B\0" "%9C\0" "%9D\0" "%9E\0" "%9F\0" /* 9: 144 ~ 159 */ + "%A0\0" "%A1\0" "%A2\0" "%A3\0" "%A4\0" "%A5\0" "%A6\0" "%A7\0" "%A8\0" "%A9\0" "%AA\0" "%AB\0" "%AC\0" "%AD\0" "%AE\0" "%AF\0" /* A: 160 ~ 175 */ + "%B0\0" "%B1\0" "%B2\0" "%B3\0" "%B4\0" "%B5\0" "%B6\0" "%B7\0" "%B8\0" "%B9\0" "%BA\0" "%BB\0" "%BC\0" "%BD\0" "%BE\0" "%BF\0" /* B: 176 ~ 191 */ + "%C0\0" "%C1\0" "%C2\0" "%C3\0" "%C4\0" "%C5\0" "%C6\0" "%C7\0" "%C8\0" "%C9\0" "%CA\0" "%CB\0" "%CC\0" "%CD\0" "%CE\0" "%CF\0" /* C: 192 ~ 207 */ + "%D0\0" "%D1\0" "%D2\0" "%D3\0" "%D4\0" "%D5\0" "%D6\0" "%D7\0" "%D8\0" "%D9\0" "%DA\0" "%DB\0" "%DC\0" "%DD\0" "%DE\0" "%DF\0" /* D: 208 ~ 223 */ + "%E0\0" "%E1\0" "%E2\0" "%E3\0" "%E4\0" "%E5\0" "%E6\0" "%E7\0" "%E8\0" "%E9\0" "%EA\0" "%EB\0" "%EC\0" "%ED\0" "%EE\0" "%EF\0" /* E: 224 ~ 239 */ + "%F0\0" "%F1\0" "%F2\0" "%F3\0" "%F4\0" "%F5\0" "%F6\0" "%F7\0" "%F8\0" "%F9\0" "%FA\0" "%FB\0" "%FC\0" "%FD\0" "%FE\0" "%FF\0" /* F: 240 ~ 255 */ +}; +#undef _______ + +#define __ 0xFF +static const unsigned char hexval[0x100] = { + __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* 00-0F */ + __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* 10-1F */ + __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* 20-2F */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,__,__,__,__,__,__, /* 30-3F */ + __,10,11,12,13,14,15,__,__,__,__,__,__,__,__,__, /* 40-4F */ + __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* 50-5F */ + __,10,11,12,13,14,15,__,__,__,__,__,__,__,__,__, /* 60-6F */ + __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* 70-7F */ + __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* 80-8F */ + __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* 90-9F */ + __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* A0-AF */ + __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* B0-BF */ + __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* C0-CF */ + __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* D0-DF */ + __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* E0-EF */ + __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__, /* F0-FF */ +}; +#undef __ + +// clang-format on +size_t uri_encode(const char *src, const size_t len, char *dst); +size_t uri_decode(const char *src, const size_t len, char *dst); diff --git a/src/url.cpp b/src/url.cpp new file mode 100644 index 0000000..a5d6e67 --- /dev/null +++ b/src/url.cpp @@ -0,0 +1,584 @@ +// +// url.c +// iziCast +// +// Created by Daniel Nöthen on 29.05.19. +// Copyright © 2019 Daniel Nöthen. All rights reserved. +// + +#include +#include +#include +#include +#include + +#include "url.h" +#include "fl_funcs.h" // write_log() +#include "config.h" // VERSION + +int write_logfile = 0; +int print_log = 0; +int curl_initialized = 0; +static char log_buf[100 * 1024]; + +struct MemoryStruct { + char *memory; + uint32_t size; +}; + +struct data { + char trace_ascii; /* 1 or 0 */ +}; + +static void dump(const char *text, FILE *stream, unsigned char *ptr, size_t size, char nohex) +{ + size_t i; + size_t c; + + unsigned int width = 0x10; + + if (nohex) { + /* without the hex output, we can fit more on screen */ + width = 0x40; + } + + if (print_log == 1) { + fprintf(stream, "%s, %10.10lu bytes (0x%8.8lx)\n", text, (unsigned long)size, (unsigned long)size); + } + + if (write_logfile == 1) { + snprintf(log_buf, sizeof(log_buf), "%s, %10.10lu bytes (0x%8.8lx)\n", text, (unsigned long)size, (unsigned long)size); + write_log(log_buf); + } + + for (i = 0; i < size; i += width) { + if (print_log == 1) { + fprintf(stream, "%4.4lx: ", (unsigned long)i); + } + if (write_logfile == 1) { + snprintf(log_buf, sizeof(log_buf), "%4.4lx: ", (unsigned long)i); + write_log(log_buf); + } + + if (!nohex) { + /* hex not disabled, show it */ + for (c = 0; c < width; c++) + if (i + c < size) { + if (print_log == 1) { + fprintf(stream, "%02x ", ptr[i + c]); + } + + if (write_logfile == 1) { + snprintf(log_buf, sizeof(log_buf), "%02x ", ptr[i + c]); + write_log(log_buf); + } + } + else { + if (print_log == 1) { + fputs(" ", stream); + } + if (write_logfile == 1) { + write_log(" "); + } + } + } + + for (c = 0; (c < width) && (i + c < size); c++) { + /* check for 0D0A; if found, skip past and start a new line of output */ + if (nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D && ptr[i + c + 1] == 0x0A) { + i += (c + 2 - width); + break; + } + // fprintf(stream, "%c", (ptr[i + c] >= 0x20) && (ptr[i + c]<0x80) ? ptr[i + c] : '.'); + if (print_log == 1) { + fprintf(stream, "%c", ptr[i + c]); + } + + if (write_logfile == 1) { + snprintf(log_buf, sizeof(log_buf), "%c", ptr[i + c]); + write_log(log_buf); + } + + /* check again for 0D0A, to avoid an extra \n if it's at width */ + if (nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D && ptr[i + c + 2] == 0x0A) { + i += (c + 3 - width); + break; + } + } + if (print_log == 1) { + fputc('\n', stream); /* newline */ + } + + if (write_logfile == 1) { + write_log("\n"); + } + } + if (print_log == 1) { + fflush(stream); + } +} + +static int my_trace(CURL *handle, curl_infotype type, char *data, size_t size, void *userp) +{ + struct data *config = (struct data *)userp; + const char *text; + (void)handle; /* prevent compiler warning */ + + switch (type) { + case CURLINFO_TEXT: + if (print_log == 1) { + fprintf(stderr, "== Info: %s", data); + } + + if (write_logfile == 1) { + snprintf(log_buf, sizeof(log_buf), "== Info: %s", data); + write_log(log_buf); + } + /* FALLTHROUGH */ + default: /* in case a new one is introduced to shock us */ + return 0; + + case CURLINFO_HEADER_OUT: + text = "=> Send header"; + break; + case CURLINFO_DATA_OUT: + text = "=> Send data"; + break; + case CURLINFO_SSL_DATA_OUT: + text = "=> Send SSL data"; + break; + case CURLINFO_HEADER_IN: + text = "<= Recv header"; + break; + case CURLINFO_DATA_IN: + text = "<= Recv data"; + break; + case CURLINFO_SSL_DATA_IN: + text = "<= Recv SSL data"; + break; + } + + dump(text, stderr, (unsigned char *)data, size, config->trace_ascii); + return 0; +} + +static size_t callback_for_curl(void *contents, size_t size, size_t nmemb, void *userp) +{ + size_t realsize = size * nmemb; + struct MemoryStruct *mem = (struct MemoryStruct *)userp; + + char *ptr = (char *)realloc(mem->memory, mem->size + realsize + 1); + if (ptr == NULL) { + /* out of memory! */ + printf("%s\n", "not enough memory (realloc returned NULL)"); + return 0; + } + + mem->memory = ptr; + memcpy(&(mem->memory[mem->size]), contents, realsize); + mem->size += realsize; + mem->memory[mem->size] = 0; + + return realsize; +} + +void url_init_curl(void) +{ + if (curl_initialized == 1) { + return; + } + curl_global_init(CURL_GLOBAL_DEFAULT); + curl_initialized = 1; +} + +uint32_t url_post_json(const char *url, char *post_data, char *answer, uint32_t max_answer_size) +{ + if (curl_initialized == 0) { + url_init_curl(); + } + + struct MemoryStruct chunk; + + chunk.memory = (char *)malloc(1); /* will be grown as needed by the realloc */ + chunk.size = 0; /* no data at this point */ + + CURL *curl; + CURLcode res; + + struct data config; + config.trace_ascii = 1; /* enable ascii tracing for debug */ + + struct curl_slist *headers = NULL; + headers = curl_slist_append(headers, "Accept: application/json"); + headers = curl_slist_append(headers, "Content-Type: application/json"); + headers = curl_slist_append(headers, "charset: utf-8"); + + curl = curl_easy_init(); + if (curl) { + if (print_log || write_logfile) { + curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); + curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &config); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + } + + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); + curl_easy_setopt(curl, CURLOPT_USERAGENT, "butt"); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 7L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback_for_curl); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); + + /* Perform the request, res will get the return code */ + res = curl_easy_perform(curl); + if (res != CURLE_OK) { + printf("URL request failed: %s\n", curl_easy_strerror(res)); + chunk.size = 0; + } + else { + long response_code; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + + if (chunk.size > max_answer_size) { + printf("%s\n", "buffer too small"); + chunk.size = 0; + } + /* else if (response_code != 200) { + printf("http response = %ld\n", response_code); + chunk.size = 0; + } + else if (strstr(chunk.memory, "Invalid resource")) { // Shoutcast v1 response with http_code = 200 but "Invalid ressource" + // if a wrong url is requested + printf("%s\n", "Invalid resource"); + chunk.size = 0; + }*/ + else { + memcpy(answer, chunk.memory, chunk.size); + answer[chunk.size] = '\0'; + } + } + + curl_easy_cleanup(curl); + } + + free(chunk.memory); + + return chunk.size; +} + +uint32_t url_post_sdp(const char *url, const char *bearer_token, char *post_data, char *answer, uint32_t max_answer_size) +{ + if (curl_initialized == 0) { + url_init_curl(); + } + + struct MemoryStruct chunk; + + chunk.memory = (char *)malloc(1); /* will be grown as needed by the realloc */ + chunk.size = 0; /* no data at this point */ + + CURL *curl; + CURLcode res; + + struct data config; + config.trace_ascii = 1; /* enable ascii tracing for debug */ + + struct curl_slist *headers = NULL; + headers = curl_slist_append(headers, "Accept: application/sdp"); + headers = curl_slist_append(headers, "Content-Type: application/sdp"); + headers = curl_slist_append(headers, "Charset: utf-8"); + if (bearer_token) { + char auth_header[256]; + snprintf(auth_header, sizeof(auth_header), "Authorization: Bearer %s", bearer_token); + headers = curl_slist_append(headers, auth_header); + } + + curl = curl_easy_init(); + if (curl) { + char user_agent[32]; + snprintf(user_agent, sizeof(user_agent), "butt %s", VERSION); + if (print_log || write_logfile) { + curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); + curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &config); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + } + + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); + curl_easy_setopt(curl, CURLOPT_USERAGENT, user_agent); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 7L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback_for_curl); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); + + /* Perform the request, res will get the return code */ + res = curl_easy_perform(curl); + if (res != CURLE_OK) { + printf("URL request failed: %s\n", curl_easy_strerror(res)); + chunk.size = 0; + } + else { + long response_code; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + + if (chunk.size > max_answer_size) { + printf("%s\n", "buffer too small"); + chunk.size = 0; + } + /* else if (response_code != 200) { + printf("http response = %ld\n", response_code); + chunk.size = 0; + } + else if (strstr(chunk.memory, "Invalid resource")) { // Shoutcast v1 response with http_code = 200 but "Invalid ressource" + // if a wrong url is requested + printf("%s\n", "Invalid resource"); + chunk.size = 0; + }*/ + else { + memcpy(answer, chunk.memory, chunk.size); + answer[chunk.size] = '\0'; + } + } + + curl_easy_cleanup(curl); + } + + free(chunk.memory); + + return chunk.size; +} + +uint32_t url_post(const char *url, char *post_data, char *answer, uint32_t max_answer_size) +{ + if (curl_initialized == 0) { + url_init_curl(); + } + + struct MemoryStruct chunk; + + chunk.memory = (char *)malloc(1); /* will be grown as needed by the realloc */ + chunk.size = 0; /* no data at this point */ + + CURL *curl; + CURLcode res; + + struct data config; + config.trace_ascii = 1; /* enable ascii tracing for debug */ + + curl = curl_easy_init(); + if (curl) { + if (print_log || write_logfile) { + curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); + curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &config); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + } + + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); + curl_easy_setopt(curl, CURLOPT_USERAGENT, "butt"); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 7L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback_for_curl); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); + + /* Perform the request, res will get the return code */ + res = curl_easy_perform(curl); + if (res != CURLE_OK) { + printf("URL post failed: %s\n", curl_easy_strerror(res)); + write_log("url_post: URL post failed: "); + write_log(curl_easy_strerror(res)); + write_log("\n"); + + chunk.size = 0; + } + else { + long response_code; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + + if (chunk.size > max_answer_size) { + printf("%s\n", "buffer too small"); + write_log("url_post: buffer too small"); + chunk.size = 0; + } + /* else if (response_code != 200) { + printf("http response = %ld\n", response_code); + chunk.size = 0; + } + else if (strstr(chunk.memory, "Invalid resource")) { // Shoutcast v1 response with http_code = 200 but "Invalid ressource" + // if a wrong url is requested + printf("%s\n", "Invalid resource"); + chunk.size = 0; + }*/ + else { + memcpy(answer, chunk.memory, chunk.size); + answer[chunk.size] = '\0'; + } + } + + curl_easy_cleanup(curl); + } + + free(chunk.memory); + + return chunk.size; +} + +uint32_t url_get(const char *url, const char *custom_hdr, char *answer, uint32_t data_size) +{ + if (curl_initialized == 0) { + url_init_curl(); + } + + struct MemoryStruct chunk; + + chunk.memory = (char *)malloc(1); /* will be grown as needed by the realloc */ + chunk.size = 0; /* no data at this point */ + + CURL *curl; + CURLcode res; + + struct data config; + config.trace_ascii = 1; /* enable ascii tracing for debug */ + + struct curl_slist *hdr = NULL; + if (custom_hdr != NULL) { + hdr = curl_slist_append(hdr, custom_hdr); + } + + curl = curl_easy_init(); + + if (curl) { + char user_agent[32]; + snprintf(user_agent, sizeof(user_agent), "butt %s", VERSION); + if (print_log || write_logfile) { + curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); + curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &config); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + } + + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_USERAGENT, user_agent); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback_for_curl); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); + + if (hdr != NULL) { + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, hdr); + } + + /* Perform the request, res will get the return code */ + res = curl_easy_perform(curl); + if (res != CURLE_OK) { + printf("URL request failed: %s\n", curl_easy_strerror(res)); + write_log("url_get: URL get failed: "); + write_log(curl_easy_strerror(res)); + write_log("\n"); + chunk.size = 0; + } + else { + long response_code; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + + if (chunk.size > data_size) { + printf("%s\n", "buffer too small"); + write_log("url_get: buffer too small"); + chunk.size = 0; + } + else { + memcpy(answer, chunk.memory, chunk.size); + answer[chunk.size] = '\0'; + } + } + + curl_easy_cleanup(curl); + } + + free(chunk.memory); + + return chunk.size; +} + +// Same as url_get() with a few icecast/shoutcast specific changes +uint32_t url_get_listener_count(const char *url, char *data, uint32_t data_size) +{ + if (curl_initialized == 0) { + url_init_curl(); + } + + struct MemoryStruct chunk; + + chunk.memory = (char *)malloc(1); /* will be grown as needed by the realloc */ + chunk.size = 0; /* no data at this point */ + + CURL *curl; + CURLcode res; + + curl = curl_easy_init(); + if (curl) { + curl_easy_setopt(curl, CURLOPT_URL, url); + // User Agent has to be set to "Mozilla". Otherwise Shoutcast v1 responses with 404 + curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla"); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 2L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback_for_curl); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); + + /* Perform the request, res will get the return code */ + res = curl_easy_perform(curl); + if (res != CURLE_OK) { + // printf("url_get_listener: URL request failed: %s\n", curl_easy_strerror(res)); + write_log("url_get_listener: failed with error: "); + write_log(curl_easy_strerror(res)); + write_log("\n"); + chunk.size = 0; + } + else if (chunk.size > 0) { + long response_code; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + + if (chunk.size > data_size) { + write_log("url_get_listener: buffer too small"); + chunk.size = 0; + } + else if (response_code != 200) { + // printf("url_get_listener: http response = %ld\n", response_code); + write_log("url_get_listener: http response != 200\n"); + chunk.size = 0; + } + else if (strstr(chunk.memory, "Invalid resource")) { // Shoutcast v1 response with http_code = 200 but "Invalid ressource" + // if a wrong url is requested + write_log("url_get_listener: Invalid resource\n"); + chunk.size = 0; + } + else { + memcpy(data, chunk.memory, chunk.size); + } + } + + curl_easy_cleanup(curl); + } + + free(chunk.memory); + + return chunk.size; +} + +void url_cleanup_curl(void) +{ + curl_global_cleanup(); +} diff --git a/src/url.h b/src/url.h new file mode 100644 index 0000000..4ba6fbb --- /dev/null +++ b/src/url.h @@ -0,0 +1,22 @@ +// +// url.h +// iziCast +// +// Created by Daniel Nöthen on 29.05.19. +// Copyright © 2019 Daniel Nöthen. All rights reserved. +// + +#ifndef URL_H +#define URL_H + +#include +#include + +void url_init_curl(void); +void url_cleanup_curl(void); +uint32_t url_get(const char *url, const char *custom_hdr, char *data, uint32_t data_size); +uint32_t url_get_listener_count(const char *url, char *data, uint32_t data_size); +uint32_t url_post(const char *url, char *post_data, char *answer, uint32_t max_answer_size); +uint32_t url_post_json(const char *url, char *post_data, char *answer, uint32_t max_answer_size); +uint32_t url_post_sdp(const char *url, const char *bearer_token, char *post_data, char *answer, uint32_t max_answer_size); +#endif /* URL_H */ diff --git a/src/util.cpp b/src/util.cpp new file mode 100644 index 0000000..c34e270 --- /dev/null +++ b/src/util.cpp @@ -0,0 +1,157 @@ +// utility functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" + +void set_max_thread_priority(void) +{ + int policy, max_prio; + pthread_attr_t attr; + struct sched_param param; + pthread_attr_init(&attr); + pthread_getschedparam(pthread_self(), &policy, ¶m); + policy = SCHED_RR; + max_prio = sched_get_priority_max(policy); + + // printf("max_prio: %d\n", max_prio); + + if (max_prio != -1) { + param.sched_priority = max_prio; + pthread_setschedparam(pthread_self(), policy, ¶m); + } + else { + printf("could not set priority\n"); + } +} + +char *util_base64_enc(char *data) +{ + int i, j; + int len; + int chunk; + char *b64_data; + static char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + len = strlen(data); + + b64_data = (char *)malloc(len * 4 / 3 + 4); + + j = 0; + for (i = 0; i < len; i += 3) { + chunk = (data[i] & 0xFC) >> 2; + b64_data[j] = b64[chunk]; + + chunk = ((data[i] & 0x03) << 4) | ((data[i + 1] & 0xF0) >> 4); + b64_data[j + 1] = b64[chunk]; + + if (i + 2 <= len) { + chunk = ((data[i + 1] & 0x0F) << 2) | ((data[i + 2] & 0xC0) >> 6); + b64_data[j + 2] = b64[chunk]; + } + else { + b64_data[j + 2] = '='; // padding + } + + if (i + 3 <= len) { + chunk = data[i + 2] & 0x3F; + b64_data[j + 3] = b64[chunk]; + } + else { + b64_data[j + 3] = '='; // padding + } + + j += 4; + } + + b64_data[j] = '\0'; + return b64_data; +} + +char *util_get_file_extension(char *filename) +{ + static char *ext; + // find the last occurence of '.' in the filename + ext = strrchr(filename, (int)'.'); + + // return NULL if no '.' was found or the '.' is the last char in the + // filename + if (ext == NULL || ext[1] == '\0') { + return NULL; + } + else { + return ++ext; + } +} + +float util_factor_to_db(float factor) +{ + return 20 * log10(factor); +} + +float util_db_to_factor(float dB) +{ + return pow(10, dB / 20); +} + +int util_mkpath(char *path) +{ + char *tmp; + char *p = NULL; + size_t len; + + tmp = strdup(path); + len = strlen(tmp); + + if (tmp[len - 1] == '/') { + tmp[len - 1] = 0; + } + + for (p = tmp + 1; *p != '\0'; p++) { +#ifdef WIN32 + // Executing fl_mkdir on a disk other than C:\ returns EACCESS instead of EEXIST + // Therefore we make sure fl_mkdir is not executed for C:\, D:\, etc. + if (*p == ':') { + p += 2; + } +#endif + if (*p == '/') { + *p = 0; + if (fl_mkdir(tmp, 0700) != 0 && errno != EEXIST) { + free(tmp); + return -1; + } + *p = '/'; + } + } + + if (fl_mkdir(tmp, 0777) != 0 && errno != EEXIST) { + free(tmp); + return -1; + } + + free(tmp); + return 0; +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..a51b726 --- /dev/null +++ b/src/util.h @@ -0,0 +1,26 @@ +// string manipulation functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// +#ifndef UTIL_H +#define UTIL_H + +char *util_base64_enc(char *data); +char *util_get_file_extension(char *filename); +float util_factor_to_db(float factor); +float util_db_to_factor(float dB); +void set_max_thread_priority(void); +int util_mkpath(char *path); + +#endif diff --git a/src/vorbis_encode.cpp b/src/vorbis_encode.cpp new file mode 100644 index 0000000..7f084ce --- /dev/null +++ b/src/vorbis_encode.cpp @@ -0,0 +1,200 @@ +// vorbis encoding functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include +#include +#include + +#include "config.h" +#include "cfg.h" +#include "vorbis_encode.h" + +int vorbis_enc_init(vorbis_enc *vorbis) +{ + int ret; + int min_bitrate, nominal_bitrate, max_bitrate; + + vorbis_info_init(&(vorbis->vi)); + + vorbis->os.body_data = NULL; + vorbis->header_written = 0; + + // CBR + if (vorbis->bitrate_mode == 0) { + min_bitrate = vorbis->bitrate * 1000; + nominal_bitrate = vorbis->bitrate * 1000; + max_bitrate = vorbis->bitrate * 1000; + } + + // VBR + if (vorbis->bitrate_mode == 1) { + min_bitrate = vorbis->vbr_min_bitrate * 1000; + nominal_bitrate = vorbis->bitrate * 1000; + max_bitrate = vorbis->vbr_min_bitrate * 1000; + } + + // ABR + if (vorbis->bitrate_mode == 2) { + min_bitrate = -1; + nominal_bitrate = vorbis->bitrate * 1000; + max_bitrate = -1; + } + + // CBR or ABR + if (vorbis->bitrate_mode == 0 || vorbis->bitrate_mode == 2) { + ret = vorbis_encode_init(&(vorbis->vi), vorbis->channel, vorbis->samplerate, min_bitrate, nominal_bitrate, max_bitrate); + if (ret) { + return ret; + } + } // VBR + else { + ret = vorbis_encode_init_vbr(&(vorbis->vi), vorbis->channel, vorbis->samplerate, vorbis->vbr_quality); + + if (ret) { + return ret; + } + } + + /* + printf("vorbis - bitrate_mode: %d\n", vorbis->bitrate_mode); + printf("vorbis - quality: %0.2f\n", vorbis->vbr_quality); + printf("vorbis - min_bitrate: %d\n", min_bitrate); + printf("vorbis - nominal_bitrate: %d\n", nominal_bitrate); + printf("vorbis - max_bitrate: %d\n\n", max_bitrate); + */ + + // printf("Vorbis bitrate: %d\n", vorbis->bitrate); + + vorbis_comment_init(&(vorbis->vc)); + vorbis_comment_add_tag(&(vorbis->vc), "ENCODER", PACKAGE_STRING); + + vorbis_analysis_init(&(vorbis->vd), &(vorbis->vi)); + vorbis_block_init(&(vorbis->vd), &(vorbis->vb)); + + return 0; +} + +// This function needs to be called before +// every connection +void vorbis_enc_write_header(vorbis_enc *vorbis) +{ + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + + ogg_stream_init(&(vorbis->os), rand()); + + vorbis_analysis_headerout(&(vorbis->vd), &(vorbis->vc), &header, &header_comm, &header_code); + + ogg_stream_packetin(&(vorbis->os), &header); + ogg_stream_packetin(&(vorbis->os), &header_comm); + ogg_stream_packetin(&(vorbis->os), &header_code); +} + +int vorbis_enc_reinit(vorbis_enc *vorbis) +{ + if (vorbis != NULL) { + vorbis_enc_close(vorbis); + return vorbis_enc_init(vorbis); + } + return 1; +} + +int vorbis_enc_encode(vorbis_enc *vorbis, float *pcm_buf, char *enc_buf, int size) +{ + int i, result; + int flush; + int eos = 0; + int w = 0; + float **vorbis_buf; + + flush = !size; + + if (vorbis->header_written == 0) { + while (ogg_stream_flush(&(vorbis->os), &(vorbis->og)) != 0) { + memcpy(enc_buf + w, vorbis->og.header, (size_t)vorbis->og.header_len); + w += vorbis->og.header_len; + memcpy(enc_buf + w, vorbis->og.body, (size_t)vorbis->og.body_len); + w += vorbis->og.body_len; + } + vorbis->header_written = 1; + } + + if (flush == 1) { + vorbis_analysis_wrote(&(vorbis->vd), 0); + } + else { + vorbis_buf = vorbis_analysis_buffer(&(vorbis->vd), size); + + // deinterlace audio data + // stereo + if (vorbis->channel == 2) { + for (i = 0; i < size; i++) { + vorbis_buf[0][i] = pcm_buf[i * 2]; + vorbis_buf[1][i] = pcm_buf[i * 2 + 1]; + } + } // mono + else { + for (i = 0; i < size; i++) { + vorbis_buf[0][i] = pcm_buf[i]; + } + } + + vorbis_analysis_wrote(&(vorbis->vd), size); + } + + while (vorbis_analysis_blockout(&(vorbis->vd), &(vorbis->vb)) == 1) { + vorbis_analysis(&(vorbis->vb), NULL); + vorbis_bitrate_addblock(&(vorbis->vb)); + + while (vorbis_bitrate_flushpacket(&(vorbis->vd), &(vorbis->op))) { + /* weld the packet into the bitstream */ + ogg_stream_packetin(&(vorbis->os), &(vorbis->op)); + + /* write out pages (if any) */ + while (!eos) { + result = ogg_stream_pageout(&(vorbis->os), &(vorbis->og)); + if (result == 0) { + break; + } + + memcpy(enc_buf + w, vorbis->og.header, vorbis->og.header_len); + w += vorbis->og.header_len; + memcpy(enc_buf + w, vorbis->og.body, vorbis->og.body_len); + w += vorbis->og.body_len; + eos = ogg_page_eos(&(vorbis->og)); + } + } + } + + return w; +} + +int vorbis_enc_get_samplerate(vorbis_enc *vorbis) +{ + return vorbis->vi.rate; +} + +void vorbis_enc_close(vorbis_enc *vorbis) +{ + if (vorbis->os.body_data != NULL) { + ogg_stream_clear(&(vorbis->os)); + } + + vorbis_block_clear(&(vorbis->vb)); + vorbis_dsp_clear(&(vorbis->vd)); + vorbis_comment_clear(&(vorbis->vc)); + vorbis_info_clear(&(vorbis->vi)); +} diff --git a/src/vorbis_encode.h b/src/vorbis_encode.h new file mode 100644 index 0000000..0edb5b5 --- /dev/null +++ b/src/vorbis_encode.h @@ -0,0 +1,61 @@ +// vorbis encoding functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef VORBIS_ENCODE_H +#define VORBIS_ENCODE_H + +#include + +struct vorbis_enc { + ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */ + ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ + ogg_packet op; /* one raw packet of data for decode */ + vorbis_info vi; + vorbis_comment vc; /* struct that stores all the user comments */ + vorbis_block vb; + vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ + + int header_written; + + int bitrate; + int samplerate; + int channel; + int state; + + int bitrate_mode; + float vbr_quality; + int vbr_min_bitrate; + int vbr_max_bitrate; +}; + +enum { + VORBIS_READY = 0, + VORBIS_BUSY = 1, +}; + +extern vorbis_info vorbis_vi; +extern char *vorbis_buf; + +int vorbis_enc_init(vorbis_enc *vorbis); +int vorbis_enc_encode(vorbis_enc *vorbis, float *pcm_buf, char *enc_buf, int size); + +int vorbis_enc_reinit(vorbis_enc *vorbis); + +void vorbis_enc_write_header(vorbis_enc *vorbis); +void vorbis_enc_close(vorbis_enc *vorbis); + +int vorbis_enc_get_samplerate(vorbis_enc *vorbis); + +#endif diff --git a/src/vu_meter.cpp b/src/vu_meter.cpp new file mode 100644 index 0000000..5e21714 --- /dev/null +++ b/src/vu_meter.cpp @@ -0,0 +1,68 @@ +// vu-meter functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// +#include +#include "flgui.h" + +#include "vu_meter.h" + +void vu_left_peak_timer(void *); +void vu_right_peak_timer(void *); + +float left_peak_dB; +float right_peak_dB; + +void vu_init(void) +{ + left_peak_dB = -90; + right_peak_dB = -90; +} +void vu_meter(float left, float right, float l_peak, float r_peak) +{ + float left_dB; + float right_dB; + float l_peak_dB; + float r_peak_dB; + + left_dB = left > 0 ? 20 * log10(left) : -90; + right_dB = right > 0 ? 20 * log10(right) : -90; + + l_peak_dB = l_peak > 0 ? 20 * log10(l_peak) : -90; + r_peak_dB = r_peak > 0 ? 20 * log10(r_peak) : -90; + + if (l_peak_dB > left_peak_dB) { + left_peak_dB = l_peak_dB; + Fl::remove_timeout(&vu_left_peak_timer); + Fl::add_timeout(1.5 /*second*/, &vu_left_peak_timer); + } + + if (r_peak_dB > right_peak_dB) { + right_peak_dB = r_peak_dB; + Fl::remove_timeout(&vu_right_peak_timer); + Fl::add_timeout(1.5 /*second*/, &vu_right_peak_timer); + } + + fl_g->vumeter->value(left_dB, right_dB, left_peak_dB, right_peak_dB); +} + +void vu_left_peak_timer(void *) +{ + left_peak_dB = -90; +} + +void vu_right_peak_timer(void *) +{ + right_peak_dB = -90; +} diff --git a/src/vu_meter.h b/src/vu_meter.h new file mode 100644 index 0000000..de9e768 --- /dev/null +++ b/src/vu_meter.h @@ -0,0 +1,38 @@ +// vu-meter functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef VU_METER +#define VU_METER + +#include + +enum LED_state { + OFF = 0, + ON = 1, +}; + +struct vu_led_t { + float thld; + + struct { + Fl_Widget *widget; + int is_peak; + } left, right; +}; + +void vu_init(void); +void vu_meter(float left, float right, float l_peak, float r_peak); + +#endif diff --git a/src/wav_header.cpp b/src/wav_header.cpp new file mode 100644 index 0000000..17c87e6 --- /dev/null +++ b/src/wav_header.cpp @@ -0,0 +1,60 @@ +// wav functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#define _FILE_OFFSET_BITS 64 + +#include +#include + +#include "wav_header.h" + +int wav_write_header(FILE *fd, short ch, int srate, short bps) +{ + off_t file_size; + uint32_t wav_size; + wav_hdr_t hdr; + + file_size = ftello(fd); + if (file_size == -1) { + return -1; + } + + wav_size = file_size > UINT32_MAX ? UINT32_MAX : (uint32_t)file_size; + + memcpy(&hdr.wav.riff_id, "RIFF", 4); + hdr.wav.riff_size = wav_size >= WAV_HDR_SIZE ? (uint32_t)(wav_size - 8) : 0; + memcpy(&hdr.wav.riff_format, "WAVE", 4); + memcpy(hdr.wav.fmt_id, "fmt ", 4); + + hdr.wav.fmt_size = 16; + hdr.wav.fmt_format = 1; + hdr.wav.fmt_channel = ch; + hdr.wav.fmt_samplerate = srate; + hdr.wav.fmt_byte_rate = srate * bps * ch / 8; + hdr.wav.fmt_block_align = bps * ch / 8; + hdr.wav.fmt_bps = bps; + + memcpy(&hdr.wav.data_id, "data", 4); + hdr.wav.data_size = wav_size >= WAV_HDR_SIZE ? (uint32_t)(wav_size - WAV_HDR_SIZE) : 0; + + // write header to the beginning of the file + rewind(fd); + fwrite(&hdr.data, 1, sizeof(wav_hdr_t), fd); + + // set the fd back to the fileend + fseeko(fd, 0, SEEK_END); + + return 0; +} diff --git a/src/wav_header.h b/src/wav_header.h new file mode 100644 index 0000000..ef83dcb --- /dev/null +++ b/src/wav_header.h @@ -0,0 +1,48 @@ +// wav header functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef WAV_HEADER_H +#define WAV_HEADER_H + +#include +#include + +#define WAV_HDR_SIZE 44 + +typedef union { + char data[WAV_HDR_SIZE]; + + struct wav_header { + char riff_id[4]; //"RIFF" + uint32_t riff_size; // file_length - 8 + char riff_format[4]; //"WAVE" + + char fmt_id[4]; //"FMT "(the space is essential + uint32_t fmt_size; // fmt data size (16 bits) + uint16_t fmt_format; // format (PCM = 1) + uint16_t fmt_channel; // 1 = mono; 2 = stereo + uint32_t fmt_samplerate; //... + uint32_t fmt_byte_rate; // samplerate * block_align + uint16_t fmt_block_align; // channels * bits_per_sample / 8 + uint16_t fmt_bps; // bits per sample = 16 + + char data_id[4]; //"data" + uint32_t data_size; // file_length - 44 + } wav; +} wav_hdr_t; + +int wav_write_header(FILE *fd, short ch, int srate, short bps); + +#endif diff --git a/src/webrtc.cpp b/src/webrtc.cpp new file mode 100644 index 0000000..6735bd5 --- /dev/null +++ b/src/webrtc.cpp @@ -0,0 +1,392 @@ +// webrtc functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#include + +#ifdef HAVE_LIBDATACHANNEL + +#include +#include "butt.h" +#include "cfg.h" +#include "timer.h" +#include "webrtc.h" +#include "gettext.h" +#include "fl_funcs.h" +#include "url.h" +#include "atom.h" + +ATOM_NEW_COND(gathering_cond); +ATOM_NEW_COND(track_cond); + +unsigned char _payloadType = 111; +unsigned int _ssrc = 1; +char _name[] = "audio-stream"; +char _msid[] = "stream1"; + +bool _logger_prepared = false; +void _prepare_logger(void); +void _logWindow(rtcLogLevel level, const char *message); +void _logFile(rtcLogLevel level, const char *message); + +int peer, track, packetiser; +float last_sample_time, last_report_time; + +void _on_state_change(int pc, rtcState state, void *ptr); +void _on_gathering_state_change(int pc, rtcGatheringState state, void *ptr); + +void _on_track_open(int id, void *ptr); +void _on_track_closed(int id, void *ptr); +void _on_track_error(int id, const char *error, void *ptr); +void _on_track_message(int id, const char *message, int size, void *ptr); + +int _negotiate(void); + +// TODO: handle trickled ICE candidates - rtcAddRemoteCandidate(...) + +int webrtc_connect(void) +{ + atom_cond_init(&gathering_cond); + atom_cond_init(&track_cond); + + // Make the libdatachannel logger print to the BUTT console + _prepare_logger(); + + // Create the peer connection + const char *iceServer = cfg.srv[cfg.selected_srv]->webrtc_ice; + + rtcConfiguration peer_config = {}; + + if (iceServer != NULL && strlen(iceServer) > 0) { + peer_config.iceServers = &iceServer; + peer_config.iceServersCount = 1; + peer_config.disableAutoNegotiation = true; + } + + peer = rtcCreatePeerConnection(&peer_config); + if (peer < 0) { + return WEBRTC_ABORT; + } + + rtcSetStateChangeCallback(peer, _on_state_change); + rtcSetGatheringStateChangeCallback(peer, _on_gathering_state_change); + + // Work out a good profile + // (mainly stereo or mono) + int is_stereo = (cfg.audio.channel == 2 ? 1 : 0); + + char profile[256]; + snprintf(profile, sizeof(profile), "minptime=10;stereo=%d;sprop-stereo=%d;useinbandfec=1", is_stereo, is_stereo); + + // Add an audio track + rtcTrackInit track_config = {}; + track_config.direction = RTC_DIRECTION_SENDONLY; + track_config.codec = RTC_CODEC_OPUS; + track_config.payloadType = _payloadType; + track_config.ssrc = _ssrc; + track_config.name = _name; + track_config.msid = _msid; + track_config.trackId = _name; + track_config.profile = profile; + + track = rtcAddTrackEx(peer, &track_config); + if (track < 0) { + return WEBRTC_ABORT; + } + + rtcSetOpenCallback(track, _on_track_open); + rtcSetClosedCallback(track, _on_track_closed); + rtcSetErrorCallback(track, _on_track_error); + rtcSetMessageCallback(track, _on_track_message); + + // Configure the packetiser chain + unsigned int sample_rate = opus_enc_get_samplerate(&opus_stream); + if (sample_rate != 48000) { + return WEBRTC_ABORT; // WebRTC using Opus must be 48k + } + + rtcPacketizerInit packetiser_config = {}; + packetiser_config.ssrc = _ssrc; + packetiser_config.cname = _name; + packetiser_config.payloadType = _payloadType; + packetiser_config.clockRate = sample_rate; + + packetiser = rtcSetOpusPacketizer(track, &packetiser_config); + if (packetiser < 0) { + return WEBRTC_ABORT; + } + + if (rtcChainRtcpSrReporter(track) < 0) { + return WEBRTC_ABORT; + } + + if (rtcChainRtcpNackResponder(track, 512 /* default nack size */) < 0) { + return WEBRTC_ABORT; + } + // Create the offer and wait to complete ICE gathering before negotiating + rtcSetLocalDescription(peer, "offer"); + atom_cond_wait(&gathering_cond); + + // Negotiate with the WHIP endpoint + int negotiation_ret = _negotiate(); + if (negotiation_ret > 0) { + return negotiation_ret; + } + + // Wait for the negotiation to complete and the track to open + atom_cond_wait(&track_cond); + + connected = 1; + + timer_init(&stream_timer, 1); // starts the "online" timer + timer_start(&stream_timer); + last_sample_time = last_report_time = timer_get_elapsed_time(&stream_timer); + + return WEBRTC_OK; +} + +int webrtc_send(char *buf, int buf_len) +{ + // Bail if the track isn't open + if (!rtcIsOpen(track)) { + print_info("WebRTC tried to send packets on closed track", 1); + return buf_len; + } + + // Increment the RTP timestamp + unsigned int track_timestamp; + rtcGetCurrentTrackTimestamp(track, &track_timestamp); + + unsigned int current_timestamp = track_timestamp + OPUS_FRAME_SIZE; + rtcSetTrackRtpTimestamp(track, current_timestamp); + + // Work out if we need to to send another RTCP sender report + unsigned int reported_timestamp; + rtcGetLastTrackSenderReportTimestamp(track, &reported_timestamp); + + unsigned int time_since_report = current_timestamp - reported_timestamp; + + double seconds_since_report; + rtcTransformTimestampToSeconds(track, time_since_report, &seconds_since_report); + + if (seconds_since_report > 1) { + rtcSetNeedsToSendRtcpSr(track); + } + + // Send the audio data + // NOTE: Shoutcast/Icecast need the Opus data wrapped in a container, and + // opus_enc_encode() does it with Ogg but WebRTC and RTP in general require + // the raw unwrapped Opus, so we'll grab that directly from opus_stream + // which gets set by opus_enc_encode() separately to the Ogg wrapping. + buf = (char *)opus_stream.buffer; + buf_len = opus_stream.buffer_len; + if (rtcSendMessage(track, buf, buf_len) < 0) { + return -1; + } + + return buf_len; +} + +int webrtc_update_song(char *song_name) +{ + // not supported + return WEBRTC_OK; +} + +int webrtc_get_listener_count(void) +{ + // not supported + return -1; +} + +void webrtc_disconnect(void) +{ + if (track > 0) { + rtcDeleteTrack(track); + } + if (peer > 0) { + rtcDeletePeerConnection(peer); + } +} + +void _prepare_logger(void) +{ + if (_logger_prepared) { + return; + } + else { + _logger_prepared = true; + } + + rtcInitLogger(RTC_LOG_NONE, _logFile); + rtcInitLogger(RTC_LOG_FATAL, _logWindow); + rtcInitLogger(RTC_LOG_ERROR, _logWindow); + rtcInitLogger(RTC_LOG_WARNING, _logFile); + // rtcInitLogger(RTC_LOG_INFO, _logFile); + // rtcInitLogger(RTC_LOG_DEBUG, _logFile); + // rtcInitLogger(RTC_LOG_VERBOSE, _logFile); +} + +void _logWindow(rtcLogLevel level, const char *message) +{ + print_info(message, level); +} + +void _logFile(rtcLogLevel level, const char *message) +{ + write_log(message); +} + +void _on_state_change(int pc, rtcState state, void *ptr) +{ + char log[256]; + + const char *state_str; + switch (state) { + case RTC_NEW: + state_str = "RTC_NEW"; + break; + case RTC_CONNECTING: + state_str = "RTC_CONNECTING"; + break; + case RTC_CONNECTED: + state_str = "RTC_CONNECTED"; + break; + case RTC_DISCONNECTED: + state_str = "RTC_DISCONNECTED"; + break; + case RTC_FAILED: + state_str = "RTC_FAILED"; + break; + case RTC_CLOSED: + state_str = "RTC_CLOSED"; + break; + default: + state_str = "??"; + break; + } + + // snprintf(log, sizeof(log), "WebRTC state change: %i %s", state, state_str); + // print_info(log, 1); + + if (state == RTC_DISCONNECTED || state == RTC_FAILED || state == RTC_CLOSED) { + connected = 0; + } +} + +void _on_gathering_state_change(int pc, rtcGatheringState state, void *ptr) +{ + char log[256]; + + const char *state_str; + switch (state) { + case RTC_GATHERING_NEW: + state_str = "RTC_GATHERING_NEW"; + break; + case RTC_GATHERING_INPROGRESS: + state_str = "RTC_GATHERING_INPROGRESS"; + break; + case RTC_GATHERING_COMPLETE: + state_str = "RTC_GATHERING_COMPLETE"; + break; + default: + state_str = "??"; + break; + } + + // snprintf(log, sizeof(log), "WebRTC gathering state change: %i %s", state, state_str); + // print_info(log, 1); + + if (state == RTC_GATHERING_COMPLETE) { + // Signal to webrtc_init() that the network's ready + atom_cond_signal(&gathering_cond); + atom_cond_destroy(&gathering_cond); + } +} + +void _on_track_open(int id, void *ptr) +{ + write_log("WebRTC track open"); + + atom_cond_signal(&track_cond); + atom_cond_destroy(&track_cond); +} + +void _on_track_closed(int id, void *ptr) +{ + write_log("WebRTC track closed"); +} + +void _on_track_error(int id, const char *error, void *ptr) +{ + char log[256]; + + snprintf(log, sizeof(log), "WebRTC track error: %s", error); + print_info(log, 1); +} + +void _on_track_message(int id, const char *message, int size, void *ptr) +{ + // char log[256]; + + // snprintf(log, sizeof(log), "WebRTC track message (%i): %s", size, message); + // print_info(log, 1); +} + +int _negotiate(void) +{ + // Get our local SDP out of the peer + char local_sdp[4096]; + if (rtcGetLocalDescription(peer, local_sdp, sizeof(local_sdp)) < 0) { + return WEBRTC_ABORT; + } + + // print_info("Local SDP offer:", 1); + // print_info(local_sdp, 1); + + // Send it to the WHIP endpoint and get their answer + char remote_sdp[4096] = {0}; + if (true) { + // Fetch the remote SDP answer from the WHIP endpoint + if (url_post_sdp(cfg.srv[cfg.selected_srv]->webrtc_whip, cfg.srv[cfg.selected_srv]->webrtc_auth, local_sdp, remote_sdp, sizeof(remote_sdp)) < 1) { + return WEBRTC_ABORT; + } + } + else { + // Ask the user to paste the remote SDP answer into console (useful for debug) + char remote_sdp_input[4096] = {0}; + while (true) { + if (fgets(remote_sdp_input, 4096, stdin) != NULL) { + int input_len = strlen(remote_sdp_input); + if (input_len > 1) { + strcat(remote_sdp, remote_sdp_input); + } + else { + break; + } + } + } + } + + // print_info("Remote SDP answer:", 1); + // print_info(remote_sdp, 1); + + // Plug the remote SDP into the peer + if (rtcSetRemoteDescription(peer, remote_sdp, "answer") < 0) { + return WEBRTC_ABORT; + } + + return WEBRTC_OK; +} +#endif diff --git a/src/webrtc.h b/src/webrtc.h new file mode 100644 index 0000000..ac340dd --- /dev/null +++ b/src/webrtc.h @@ -0,0 +1,32 @@ +// webrtc functions for butt +// +// Copyright 2007-2018 by Daniel Noethen. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// + +#ifndef WEBRTC_H +#define WEBRTC_H + +enum { + WEBRTC_OK = 0, + WEBRTC_RETRY = 1, + WEBRTC_ABORT = 2, + WEBRTC_ASK = 3, +}; + +int webrtc_update_song(char *song_name); +int webrtc_connect(void); +int webrtc_send(char *buf, int buf_len); +void webrtc_disconnect(void); +int webrtc_get_listener_count(void); + +#endif diff --git a/src/xpm/VU_text.png b/src/xpm/VU_text.png new file mode 100644 index 0000000..720af94 Binary files /dev/null and b/src/xpm/VU_text.png differ diff --git a/src/xpm/conn.xpm b/src/xpm/conn.xpm new file mode 100644 index 0000000..a8cb215 --- /dev/null +++ b/src/xpm/conn.xpm @@ -0,0 +1,77 @@ +/* XPM */ +static const char *conn_xpm[] = { +/* columns rows colors chars-per-pixel */ +"20 20 51 1 ", +" c None", +". c #099600", +"X c #099900", +"o c #099C00", +"O c #099D00", +"+ c #0A9F00", +"@ c #0AA000", +"# c #0AA200", +"$ c #0AA300", +"% c #0AA500", +"& c #0BA600", +"* c #0BA700", +"= c #0BA800", +"- c #0BA900", +"; c #0BAA00", +": c #0BAC00", +"> c #0BAD00", +", c #0CAE00", +"< c #0CB200", +"1 c #0CB300", +"2 c #0DB500", +"3 c #0DB701", +"4 c #0EB801", +"5 c #0EB901", +"6 c #0FBC01", +"7 c #0FBE01", +"8 c #0FBE02", +"9 c #10C102", +"0 c #11C302", +"q c #12C703", +"w c #13C803", +"e c #13CA04", +"r c #15CE04", +"t c #16D205", +"y c #17D406", +"u c #18D406", +"i c #18D606", +"p c #19D706", +"a c #1ADA07", +"s c #1DDF09", +"d c #20E40A", +"f c #23E80C", +"g c #25EB0E", +"h c #27EC0F", +"j c #27ED0F", +"k c #2BF011", +"l c #2CF212", +"z c #33F717", +"x c #35F918", +"c c #36F918", +"v c #36F919", +/* pixels */ +" ", +" ", +" f ", +" sf ", +" isl ", +" eydz ", +" qeyfc ", +" qqqilc ", +" 444qyfc ", +" 42244eia ", +" 222222442 ", +" :::::::: ", +" ::::::: ", +" ###### ", +" ##### ", +" +#++ ", +" +++ ", +" ++ ", +" . ", +" " +}; diff --git a/src/xpm/conn_dark.xpm b/src/xpm/conn_dark.xpm new file mode 100644 index 0000000..d6e5f86 --- /dev/null +++ b/src/xpm/conn_dark.xpm @@ -0,0 +1,61 @@ +/* XPM */ +static const char * conn_dark_xpm[] = { +"20 20 38 1", +" c None", +". c #7B7C63", +"+ c #7A7B61", +"@ c #7B7C64", +"# c #797B60", +"$ c #7A7B63", +"% c #7B7C67", +"& c #797A5F", +"* c #797B61", +"= c #7A7B65", +"- c #7C7D6A", +"; c #787A5F", +"> c #797A60", +", c #797B62", +"' c #7D7D6E", +") c #78795E", +"! c #78795F", +"~ c #787A60", +"{ c #797B63", +"] c #7B7C69", +"^ c #7D7D70", +"/ c #787960", +"( c #797A64", +"_ c #7C7D6E", +": c #77785D", +"< c #77785E", +"[ c #77795E", +"} c #797A63", +"| c #7A7B66", +"1 c #7A7B67", +"2 c #77785F", +"3 c #777860", +"4 c #777960", +"5 c #76785D", +"6 c #76775C", +"7 c #76775D", +"8 c #75765C", +"9 c #75765B", +" ", +" ", +" . ", +" +@ ", +" #$% ", +" &*=- ", +" ;>,%' ", +" )!~{]^ ", +" ))!/(]_ ", +" :<<[/}|1 ", +" ::::<2343 ", +" 55555555 ", +" 6666667 ", +" 666666 ", +" 66666 ", +" 8888 ", +" 999 ", +" 99 ", +" 9 ", +" "}; diff --git a/src/xpm/folder.png b/src/xpm/folder.png new file mode 100644 index 0000000..eb87a58 Binary files /dev/null and b/src/xpm/folder.png differ diff --git a/src/xpm/green_dark.png b/src/xpm/green_dark.png new file mode 100644 index 0000000..772c80f Binary files /dev/null and b/src/xpm/green_dark.png differ diff --git a/src/xpm/green_light.png b/src/xpm/green_light.png new file mode 100644 index 0000000..7379321 Binary files /dev/null and b/src/xpm/green_light.png differ diff --git a/src/xpm/live365_badge.png b/src/xpm/live365_badge.png new file mode 100644 index 0000000..88fd7b0 Binary files /dev/null and b/src/xpm/live365_badge.png differ diff --git a/src/xpm/orange_dark.png b/src/xpm/orange_dark.png new file mode 100644 index 0000000..74852a1 Binary files /dev/null and b/src/xpm/orange_dark.png differ diff --git a/src/xpm/orange_light.png b/src/xpm/orange_light.png new file mode 100644 index 0000000..bc6dfee Binary files /dev/null and b/src/xpm/orange_light.png differ diff --git a/src/xpm/radio_co_badge.png b/src/xpm/radio_co_badge.png new file mode 100644 index 0000000..e34d029 Binary files /dev/null and b/src/xpm/radio_co_badge.png differ diff --git a/src/xpm/rec.xpm b/src/xpm/rec.xpm new file mode 100644 index 0000000..62a7cad --- /dev/null +++ b/src/xpm/rec.xpm @@ -0,0 +1,106 @@ +/* XPM */ +static const char * rec_xpm[] = { +"16 16 87 1", +" c None", +". c #AD1313", +"+ c #B21717", +"@ c #B81C1C", +"# c #C22525", +"$ c #D03131", +"% c #E14141", +"& c #AA1212", +"* c #AE1414", +"= c #B31818", +"- c #BC2020", +"; c #C82B2B", +"> c #DA3C3C", +", c #F05151", +"' c #FF6868", +") c #A71111", +"! c #AE1515", +"~ c #B41A1A", +"{ c #BE2323", +"] c #CE3131", +"^ c #E44646", +"/ c #FF6060", +"( c #FF7B7B", +"_ c #FF9393", +": c #A51010", +"< c #B51B1B", +"[ c #C02525", +"} c #D23636", +"| c #EB4D4D", +"1 c #FF6A6A", +"2 c #FF8888", +"3 c #FFA1A1", +"4 c #FFB0B0", +"5 c #A41010", +"6 c #A61111", +"7 c #A91212", +"8 c #AD1515", +"9 c #C02626", +"0 c #D33737", +"a c #EC4F4F", +"b c #FF6C6C", +"c c #FF8A8A", +"d c #FFAEAE", +"e c #A81212", +"f c #AC1515", +"g c #B31B1B", +"h c #BE2424", +"i c #CF3434", +"j c #E74B4B", +"k c #FF6565", +"l c #FF7F7F", +"m c #FF9D9D", +"n c #A31010", +"o c #A71212", +"p c #AB1414", +"q c #B11919", +"r c #BA2121", +"s c #C92E2E", +"t c #DC4141", +"u c #F35656", +"v c #FF6B6B", +"w c #FF7A7A", +"x c #FF8181", +"y c #A21010", +"z c #A91313", +"A c #AE1717", +"B c #B51D1D", +"C c #C02727", +"D c #DF4343", +"E c #EF5252", +"F c #FB5D5D", +"G c #FF6262", +"H c #A51111", +"I c #AB1515", +"J c #B81F1F", +"K c #C22828", +"L c #CD3232", +"M c #D83B3B", +"N c #E04242", +"O c #B81E1E", +"P c #BF2424", +"Q c #C52A2A", +"R c #CB2E2E", +"S c #B01818", +"T c #B91E1E", +"U c #AC1414", +"V c #AE1616", +" ", +" ", +" .+@#$% ", +" &*=-;>,' ", +" )&!~{]^/(_ ", +" :)&!<[}|1234 ", +" 5678<90abc3d ", +" 56efghijkl_m ", +" n:opqrstuvwx ", +" y56zABCiDEFG ", +" ynHeIqJKLMN^ ", +" y56zfqOPQR ", +" n:)z8S c #DD844F", +", c #F19863", +"' c #FEAA78", +") c #C25514", +"! c #CA5B18", +"~ c #CD5F1D", +"{ c #D56927", +"] c #D37B45", +"^ c #E68D58", +"/ c #FEA570", +"( c #FFB487", +"_ c #FFC29D", +": c #C35513", +"< c #CD601F", +"[ c #D66B2A", +"} c #D67F4A", +"| c #EC935E", +"1 c #FEAC7A", +"2 c #FFBC93", +"3 c #FECAAA", +"4 c #FFD2B7", +"5 c #C15413", +"6 c #C85A18", +"7 c #D56B2B", +"8 c #D77F49", +"9 c #ED9661", +"0 c #FEAD7C", +"a c #FFBD95", +"b c #FFD1B5", +"c c #C35615", +"d c #CB601F", +"e c #D46928", +"f c #D47D48", +"g c #E9925D", +"h c #FEA874", +"i c #FFB78B", +"j c #FEC7A6", +"k c #C15513", +"l c #C35715", +"m c #C75917", +"n c #CB5E1D", +"o c #D36725", +"p c #D3763D", +"q c #DF8853", +"r c #F49C66", +"s c #FFB88D", +"t c #BF5413", +"u c #C45816", +"v c #C95C1B", +"w c #CD6221", +"x c #D56C2D", +"y c #E28A54", +"z c #F09964", +"A c #FBA26D", +"B c #FEA772", +"C c #C25614", +"D c #C65A18", +"E c #D16523", +"F c #D46E30", +"G c #D27B46", +"H c #DC844E", +"I c #E28954", +"J c #D06322", +"K c #D66A28", +"L c #D47136", +"M c #D4773E", +"N c #CA5D1C", +"O c #D26422", +"P c #C95B19", +" ", +" ", +" .+@#$% ", +" &*=-;>,' ", +" )&!~{]^/(_ ", +" :)&!<[}|1234 ", +" 5)&6<7890a3b ", +" 5)c6defghi_j ", +" k:lmnopqr1(s ", +" t5)uvwxfyzAB ", +" tkCcDnEFGHI^ ", +" t5)u6nJKLM ", +" k:)u6N c #827070", +", c #847474", +"' c #7D5F5F", +") c #7E6363", +"! c #816D6D", +"~ c #847272", +"{ c #847676", +"] c #847979", +"^ c #7B5959", +"/ c #806969", +"( c #826F6F", +"_ c #847878", +": c #847B7B", +"< c #847D7D", +"[ c #7B5A5A", +"} c #806A6A", +"| c #847C7C", +"1 c #7F6969", +"2 c #826E6E", +"3 c #847373", +"4 c #847777", +"5 c #7D6262", +"6 c #7F6767", +"7 c #837171", +"8 c #7C5E5E", +"9 c #7D6161", +"0 c #7E6565", +"a c #7C5D5D", +" ", +" ", +" .+@#$% ", +" &*+=-;>, ", +" &&*')$!~{] ", +" ^&&*@#/(,_:< ", +" ^[&*@#}(,_:| ", +" ^[&*@#1234]: ", +" ^^&*'56%7,{4 ", +" ^^[.8901!>~3 ", +" ^^[&*'50$;%! ", +" ^^[.*'9#-6 ", +" ^^&.*+@9 ", +" ^[&.*a ", +" ", +" "}; diff --git a/src/xpm/red_dark.png b/src/xpm/red_dark.png new file mode 100644 index 0000000..e5d654e Binary files /dev/null and b/src/xpm/red_dark.png differ diff --git a/src/xpm/red_light.png b/src/xpm/red_light.png new file mode 100644 index 0000000..866b5ee Binary files /dev/null and b/src/xpm/red_light.png differ diff --git a/src/xpm/refresh.png b/src/xpm/refresh.png new file mode 100644 index 0000000..2c576bf Binary files /dev/null and b/src/xpm/refresh.png differ diff --git a/src/xpm/settings.png b/src/xpm/settings.png new file mode 100644 index 0000000..59746f1 Binary files /dev/null and b/src/xpm/settings.png differ diff --git a/src/xpm/yt_icon.png b/src/xpm/yt_icon.png new file mode 100644 index 0000000..5164030 Binary files /dev/null and b/src/xpm/yt_icon.png differ diff --git a/src/xpm/yt_icon.svg b/src/xpm/yt_icon.svg new file mode 100644 index 0000000..ff0140b --- /dev/null +++ b/src/xpm/yt_icon.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/usr/share/applications/butt.desktop b/usr/share/applications/butt.desktop new file mode 100644 index 0000000..ea9b861 --- /dev/null +++ b/usr/share/applications/butt.desktop @@ -0,0 +1,15 @@ +[Desktop Entry] +Version=1.0 +Name=butt +Comment=broadcast using this tool +GenericName=Streaming Tool +Keywords=Stream,Audio,Shoutcast,Icecast,Record +Exec=butt %u +Terminal=false +X-MultipleArgs=false +Type=Application +Icon=butt +StartupWMClass=butt_FLTK +Categories=AudioVideo;Audio;AudioVideoEditing; +StartupNotify=true + diff --git a/usr/share/icons/hicolor/128x128/apps/butt.png b/usr/share/icons/hicolor/128x128/apps/butt.png new file mode 100644 index 0000000..433c9ce Binary files /dev/null and b/usr/share/icons/hicolor/128x128/apps/butt.png differ diff --git a/usr/share/icons/hicolor/128x128@2x/apps/butt.png b/usr/share/icons/hicolor/128x128@2x/apps/butt.png new file mode 100644 index 0000000..1feecf6 Binary files /dev/null and b/usr/share/icons/hicolor/128x128@2x/apps/butt.png differ diff --git a/usr/share/icons/hicolor/16x16/apps/butt.png b/usr/share/icons/hicolor/16x16/apps/butt.png new file mode 100644 index 0000000..ab759d6 Binary files /dev/null and b/usr/share/icons/hicolor/16x16/apps/butt.png differ diff --git a/usr/share/icons/hicolor/22x22/apps/butt.png b/usr/share/icons/hicolor/22x22/apps/butt.png new file mode 100644 index 0000000..ccbed83 Binary files /dev/null and b/usr/share/icons/hicolor/22x22/apps/butt.png differ diff --git a/usr/share/icons/hicolor/24x24/apps/butt.png b/usr/share/icons/hicolor/24x24/apps/butt.png new file mode 100644 index 0000000..cf25d67 Binary files /dev/null and b/usr/share/icons/hicolor/24x24/apps/butt.png differ diff --git a/usr/share/icons/hicolor/256x256/apps/butt.png b/usr/share/icons/hicolor/256x256/apps/butt.png new file mode 100644 index 0000000..b7cb5dc Binary files /dev/null and b/usr/share/icons/hicolor/256x256/apps/butt.png differ diff --git a/usr/share/icons/hicolor/256x256@2x/apps/butt.png b/usr/share/icons/hicolor/256x256@2x/apps/butt.png new file mode 100644 index 0000000..0c73963 Binary files /dev/null and b/usr/share/icons/hicolor/256x256@2x/apps/butt.png differ diff --git a/usr/share/icons/hicolor/32x32/apps/butt.png b/usr/share/icons/hicolor/32x32/apps/butt.png new file mode 100644 index 0000000..280993e Binary files /dev/null and b/usr/share/icons/hicolor/32x32/apps/butt.png differ diff --git a/usr/share/icons/hicolor/48x48/apps/butt.png b/usr/share/icons/hicolor/48x48/apps/butt.png new file mode 100644 index 0000000..7252521 Binary files /dev/null and b/usr/share/icons/hicolor/48x48/apps/butt.png differ diff --git a/usr/share/icons/hicolor/512x512/apps/butt.png b/usr/share/icons/hicolor/512x512/apps/butt.png new file mode 100644 index 0000000..0c73963 Binary files /dev/null and b/usr/share/icons/hicolor/512x512/apps/butt.png differ diff --git a/usr/share/icons/hicolor/512x512@2x/apps/butt.png b/usr/share/icons/hicolor/512x512@2x/apps/butt.png new file mode 100644 index 0000000..97467d7 Binary files /dev/null and b/usr/share/icons/hicolor/512x512@2x/apps/butt.png differ diff --git a/usr/share/icons/hicolor/64x64/apps/butt.png b/usr/share/icons/hicolor/64x64/apps/butt.png new file mode 100644 index 0000000..17a41ae Binary files /dev/null and b/usr/share/icons/hicolor/64x64/apps/butt.png differ diff --git a/usr/share/icons/hicolor/96x96/apps/butt.png b/usr/share/icons/hicolor/96x96/apps/butt.png new file mode 100644 index 0000000..54bd8c6 Binary files /dev/null and b/usr/share/icons/hicolor/96x96/apps/butt.png differ diff --git a/usr/share/icons/hicolor/scalable/apps/butt.svg b/usr/share/icons/hicolor/scalable/apps/butt.svg new file mode 100644 index 0000000..69f7434 --- /dev/null +++ b/usr/share/icons/hicolor/scalable/apps/butt.svg @@ -0,0 +1,441 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/usr/share/metainfo/de.danielnoethen.butt.metainfo.xml b/usr/share/metainfo/de.danielnoethen.butt.metainfo.xml new file mode 100644 index 0000000..513f18c --- /dev/null +++ b/usr/share/metainfo/de.danielnoethen.butt.metainfo.xml @@ -0,0 +1,23 @@ + + + de.danielnoethen.butt + + butt +

Icecast and Shoutcast streaming client + + MIT + GPL-2.0-or-later + + +

+ butt (broadcast using this tool) is an easy to use, multi OS streaming tool. It supports SHOUTcast and Icecast and runs on Linux, Mac OS X and Windows (64 Bit only since version 0.1.20). The main purpose of butt is to stream live audio data from your computers Mic or Line input to a Shoutcast or Icecast server. If you want you can also record your session. +

+
+ + butt.desktop + + + https://danielnoethen.de/butt/butt_ubuntu.png + + + diff --git a/usr/share/pixmaps/butt16.xpm b/usr/share/pixmaps/butt16.xpm new file mode 100644 index 0000000..92c6e1c --- /dev/null +++ b/usr/share/pixmaps/butt16.xpm @@ -0,0 +1,278 @@ +/* XPM */ +static char *butt16x16[] = { +/* columns rows colors chars-per-pixel */ +"16 16 256 2 ", +" c None", +". c black", +"X c black", +"o c black", +"O c black", +"+ c black", +"@ c black", +"# c black", +"$ c black", +"% c black", +"& c black", +"* c black", +"= c black", +"- c black", +"; c black", +": c black", +"> c black", +", c black", +"< c black", +"1 c black", +"2 c black", +"3 c black", +"4 c black", +"5 c black", +"6 c black", +"7 c black", +"8 c black", +"9 c black", +"0 c black", +"q c black", +"w c black", +"e c black", +"r c black", +"t c black", +"y c black", +"u c black", +"i c black", +"p c black", +"a c black", +"s c black", +"d c black", +"f c black", +"g c black", +"h c black", +"j c #020202", +"k c black", +"l c black", +"z c black", +"x c black", +"c c black", +"v c black", +"b c black", +"n c black", +"m c black", +"M c black", +"N c black", +"B c black", +"V c black", +"C c black", +"Z c black", +"A c #020202", +"S c black", +"D c black", +"F c black", +"G c black", +"H c black", +"J c black", +"K c black", +"L c black", +"P c black", +"I c black", +"U c black", +"Y c black", +"T c black", +"R c black", +"E c black", +"W c #020202", +"Q c black", +"! c black", +"~ c black", +"^ c black", +"/ c black", +"( c black", +") c black", +"_ c black", +"` c black", +"' c black", +"] c black", +"[ c black", +"{ c black", +"} c black", +"| c black", +" . c #020202", +".. c black", +"X. c black", +"o. c black", +"O. c black", +"+. c black", +"@. c black", +"#. c black", +"$. c black", +"%. c black", +"&. c black", +"*. c black", +"=. c black", +"-. c black", +";. c black", +":. c black", +">. c #020202", +",. c black", +"<. c black", +"1. c black", +"2. c black", +"3. c black", +"4. c black", +"5. c black", +"6. c black", +"7. c black", +"8. c black", +"9. c black", +"0. c black", +"q. c black", +"w. c black", +"e. c black", +"r. c #020202", +"t. c black", +"y. c black", +"u. c black", +"i. c black", +"p. c black", +"a. c black", +"s. c black", +"d. c black", +"f. c black", +"g. c black", +"h. c black", +"j. c black", +"k. c black", +"l. c black", +"z. c black", +"x. c #020202", +"c. c black", +"v. c black", +"b. c black", +"n. c black", +"m. c black", +"M. c black", +"N. c black", +"B. c black", +"V. c black", +"C. c black", +"Z. c black", +"A. c black", +"S. c black", +"D. c black", +"F. c black", +"G. c #020202", +"H. c black", +"J. c black", +"K. c black", +"L. c black", +"P. c black", +"I. c black", +"U. c black", +"Y. c black", +"T. c black", +"R. c black", +"E. c black", +"W. c black", +"Q. c black", +"!. c #020202", +"~. c black", +"^. c #020202", +"/. c black", +"(. c black", +"). c black", +"_. c black", +"`. c black", +"'. c black", +"]. c black", +"[. c black", +"{. c black", +"}. c black", +"|. c black", +" X c black", +".X c black", +"XX c black", +"oX c black", +"OX c #020202", +"+X c black", +"@X c black", +"#X c black", +"$X c black", +"%X c black", +"&X c black", +"*X c black", +"=X c black", +"-X c black", +";X c black", +":X c black", +">X c black", +",X c black", +" , < 1 2 3 4 5 6 7 8 9 0 q w e ", +"r t y u i p a s d f g h j k l z ", +"x c v b n m M N B V C Z A S D F ", +"G H J K L P I U Y T R E W Q ! ~ ", +"^ / ( ) _ ` ' ] [ { } | ...X.o.", +"O.+.@.#.$.%.&.*.=.-.;.:.>.,.<.1.", +"2.3.4.5.6.7.8.9.0.q.w.e.r.t.y.u.", +"i.p.a.s.d.f.g.h.j.k.l.z.x.c.v.b.", +"n.m.M.N.B.V.C.Z.A.S.D.F.G.H.J.K.", +"L.P.I.U.Y.T.R.E.W.Q.!.~.^./.(.).", +"_.`.'.].[.{.}.|. X.XXXoXOX+X@X#X", +"$X%X&X*X=X-X;X:X>X,X