diff --git a/darkice/tags/darkice-1_3/AUTHORS b/darkice/tags/darkice-1_3/AUTHORS new file mode 100644 index 0000000..3f00064 --- /dev/null +++ b/darkice/tags/darkice-1_3/AUTHORS @@ -0,0 +1,48 @@ +DarkIce initial author: + + Akos Maroy, + +DarkIce current maintainer: + + Rafael Diniz, + +with contributions by: + + Jim Crilly, + aNa|0Gue, + Robin P. Blanchard, + Tom Gray, + Michael Smith, + Julius O. Smith, + the OSALP team, http://osalp.sourceforge.net + Kristjan G. Bjarnason + Nicu Pavel + Kai Krakow + Atsuhiko Yamanaka + Ricardo Galli + John Hay + Christian Forster + John Deeny + Robert Lunnon + Enrico Ardizzoni + Deti Fliegl + Nicholas J. Humfrey + Joel Ebel + + Alexander Vlasov + Mariusz Mazur + dsk + Clyde Stubbs + Jens Maurer + Elod Horvath + Pierre Souchay + Daniel Hazelbaker + Alessandro Beretta + Roland Hermans + Sergiy + Clemens Ladisch + Edwin van den Oetelaar + Adrian Knoth + Filipe Roque + Johann Fot + Alban Peignier diff --git a/darkice/tags/darkice-1_3/COPYING b/darkice/tags/darkice-1_3/COPYING new file mode 100644 index 0000000..6c62854 --- /dev/null +++ b/darkice/tags/darkice-1_3/COPYING @@ -0,0 +1,677 @@ +All source code in the src directory is covered under the +GNU General Public License version 3 or any later version. + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + 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 +state 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 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 . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU 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. But first, please read +. diff --git a/darkice/tags/darkice-1_3/ChangeLog b/darkice/tags/darkice-1_3/ChangeLog new file mode 100644 index 0000000..aee8c3d --- /dev/null +++ b/darkice/tags/darkice-1_3/ChangeLog @@ -0,0 +1,300 @@ +04-08-2016 Darkice 1.3 released + o Small bugs fixed by Nicolas Boulenguez . + o Bugs related to streaming to remote servers fixed. Patch by Kalle Kulonen + and Mark Turner . + +15-07-2013 Darkice 1.2 released + o Issue #75: Added Ogg/Opus support. Patch by Doug Kelly + dougk.ff7@gmail.com + o Fix 'Ring Ruffer' reports. + - Increased buffer for jack to 5 seconds + - prevent darkice termination by jack, report no fatal problem when we + have a ringbuffer overflow, can happen during startup + If we can not handle input audio fast enough we just ignore the buffer + and skip it, and just report it. + - new multithreaded connector code, now handles encoders in parallel + and does not spin waiting, cpu load will be very much lower now + Codes uses 2 condition variables to report data availability and + consumer thread availability + - Hopes are that glitching reports will be a thing of the past + - minor compiler warnings fixed + (Fix by Edwin van den Oetelaar) + o Issue #56: Wrong icecast2 password isn't properly reported, fixed. + thanks to Filipe Roque + o Issue #57: BufferedSink makes streams invalid, fixed. + thanks to Alban Peignier + o Issue #30: Segmentation Fault when creating file with fileAddDate, fixed + thanks to Filipe Roque + +27-10-2011 Darkice 1.1 released + o Updated aac+ encoding to use libaacplus-2.0.0 api. + thanks to Sergiy + o Added pulseaudio support + closes ticket #25 + thanks to Filipe Roque and + and Johann Fot + o Added rtprio parameter and revisited realtime priority + closes ticket #21 + thanks to Adrian Knoth + o Fixed a call to a deprecated jack call + closes ticket #22 + thanks to Adrian Knoth again. + +09-05-2010 Darkice 1.0 released + o fixed a bug in BufferedSink.cpp that leads to some buffers + being written twice, causing corruption of datastream, + closes ticked #20 + thanks to Edwin van den Oetelaar + o implemented samplerate conversion for all codecs using libsamplerate, + and keeping internal aflibConverter as fallback, + thanks to Sergiy + o bugfix: fix for alsa driver - closes ticked #8 + thanks to Clemens Ladisch + +14-11-2009 Darkice 0.20.1 released + o added rc.darkice init script + thanks to Niels Dettenbach + o bugfix: fix for gcc 4.4 + +05-11-2009 Darkice 0.20 released + + o new maintainer: Rafael Diniz + o added AAC HEv2 encoding support (branch darkice-aacp merged) through + libaacplus, http://tipok.org.ua/ru/node/17 + thanks to tipok and others for the contribution. + o bugfix: the configure script recognizes Ogg Vorbis shared objects + now, not just static libraries. Thanks to omroepvenray. + o bugfix: enabling jack source compilation on Debian Lenny, + thanks to Alessandro Beretta + +07-07-2008 Darkice 0.19 released + + o added mount point option for Darwin Streaming Server + thanks to Pierre Souchay + o fix for some reliablity issues when using a Jack source + thanks to Pierre Souchay + o enable easier finding of jack libraries on MacOS X, + thanks to Daniel Hazelbaker + o added ability to specify name of jack device created by darkice, + thanks to Alessandro Beretta + +26-04-2007 DarkIce 0.18.1 released + + o enable real-time scheduling for non-super-users, if they have + the proper operating system permissions, + thanks to Jens Maurer + o fix to enable compliation of the Serial ULAW code on MacOS X, + thanks to Elod Horvath + o fix to solve Shoutcast login failures, introduced in 0.18 + +05-03-2007 DarkIce 0.18 released + + o added serial ulaw input device support, thanks to + Clyde Stubbs + o improvements on reconnecting: + added TCP connection keep-alive to TCP sockets + added graceful sleep when trying to reconnect + o added user-defined date formatting for the fileAddDate options, + thanks to dsk + o added logging facility - [file-X] targets will cut the saved file + and rename it as needed when darkice recieves the SIGUSR1 signal + o added default configuration file handling - if no configuration file + is specified, /etc/darkice.cfg is used + o fix to enable compiling on 64 bit platforms + thanks to Alexander Vlasov and + Mariusz Mazur + o fix to enable file dump feature using ogg vorbis. + thanks to dsk + o fix to enable compiling with jack installed at arbitrary locations + +19-05-2006 DarkIce 0.17.1 released + + o bugfix: automatic reconnect works more reliably + +26-01-2006 DarkIce 0.17 released + + o added check for bufferSecs set to 0 + thanks to Toph + o added realtime parameter to the general section + o added MPEG2 support through the TwoLame library. + thanks to Nicholas J Humfrey + +22-10-2005 DarkIce 0.16 released + + o added AAC support through the faac codec, http://www.audiocoding.com + o bug fix: icecast2 sections didn't honor lowpass or highpass filters + when using the mp3 format + +14-04-2005 DarkIce 0.15 released + + o ported to OpenBSD and NetBSD, though real-time scheduling not supported, + since it is not implemented in OpenBSD / NetBSD + o added possibility to downsample from stereo to mono when encoding + to Ogg Vorbis, thanks to Deti Fliegl, + o added support for Jack inputs, enabling a lot of interesting usage, + including support for MacOS X. + Thanks to Nicholas J. Humfrey + o various improvements by Joel Ebel + o added option to turn off automatic reconnect feature + o added IPv6 support, thanks to + +15-02-2004: DarkIce 0.14 released + + o added ALSA support, thanks to Christian Forster + + o added fix to enable downsampling from stereo to mono of mp3 streams + when streaming to an icecast2 server. thanks to John Deeny + + o removed _X and _Y symbols from aflibConverter files, which caused + a naming collision on Solaris. thanks to Robert Lunnon, + + o bug fix: ogg vorbis recording to only a file caused a segfault. + now fixed, thanks to Enrico Ardizzoni + +07-01-2004: DarkIce 0.13.2 released + + o bug fix: two bugs fixed that caused core dump when encoding into + mp3 of FreeBSD. thanks to John Hay + o added configure option --with-debug to enable compilation for debug mode + +12-02-2003: Darkice 0.13.1 released + + o added cross-platform pthread detection, thanks to + Steven G. Johnson and + Alejandro Forero Cuervo + see http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html + o added proper detection of netural endiannes for 16 bit recording + o basically these changes allow compilation on FreeBSD + +09-02-2003: DarkIce 0.13 released + + o added feature for setting the TITLE comment field for vorbis + streams. thanks to Ricardo Galli + o bugfix: fixed minor bug in IcecCast2.cpp, which could have lead to + a buffer overflow. thanks to Atsuhiko Yamanaka + o bugfix: MultiThreadedConnector::sinkThread() was private, now public + o added fileAddDate configuration option + thanks to Nicu Pavel + o added support for big endian OSS devices (like Linux PowerPC) + +20-10-2002: DarkIce 0.12 released + + o ported to FreeBSD (removed reference to MSG_NOSIGNAL in TcpSocket.cpp) + o bug fix: maximum bitrate setting fixed for Ogg Vorbis streams + o changed internals so that now each encoding/server connection is + a separate thread + o when a connection is dropped, DarkIce tries to reconnect, indefinitely + +20-08-2002: DarkIce 0.11 released + + o added possibility to specify maximum bitrate for Ogg Vorbis streams + o added HTTP Basic authentication for icecast2 logins + o added mp3 streaming for icecast2 + o added possibility to stream in mono even when recording in stereo, + thus enabling mono and stereo streams with the same darkice instance. + only for mp3 streams at the moment + thanks to Kai Krakow + o bug fix: resampling audio for vorbis streams bugs fixed + +02-08-2002: DarkIce 0.10.1 released + + o bug fix: when the last server dropped connection, darkice crashed + thanks to Nicu Pavel + o bug fix for LameLibEncoder: the mp3 encoding buffer was deleted too + early, resulting in mp3 data corruption. + thanks to Nicu Pavel + +20-07-2002: DarkIce 0.10 released + + o added possibility to select constant, average and variable bit rate + encoding modes with specifying encoding quality as well. + thanks to Nicu Pavel + o added support for Ogg Vorbis 1.0 final, removed support for rc2 + o added fault tolerance: if one of several server connection drops, + DarkIce carries on with the rest of the servers still connected + +09-04-2002: DarkIce 0.9.1 released + + o bugfix: a memory leak was introduced in 0.9, which is fixed thanks to + Kristjan G. Bjarnason and Nicu Pavel + o minor documentation fix + +28-03-2002: DarkIce 0.9 released + + o added possibility to simply read from the soundcard, encode, and + save the encoded data into a local file (no streaming server needed) + o added variable bitrate support for vorbis streams + o support for both rc2 and rc3 versions of vorbis libraries + o added support for resampling when encoding to vorbis + thanks to the OSALP project for the resampling class, + http://osalp.sourceforge.net/ and + Julius O. Smith, for the original code + +20-02-2002: DarkIce 0.8 released + + o added possibility to disable lowpass and highpass filtering for lame + o fixed incorrect vorbis bitrate setting + o fix: DarkIce now reports public streams correctly + thanks to Tom Gray, + o made up-to-date with Ogg Vorbis rc3 libs + thanks to Michael Smith, + o made up-to-date with current IceCast2 cvs version + o added local stream dump possibility + +19-10-2001: DarkIce 0.7 released + + o added support for FreeBSD + thanks to Robin P. Blanchard, + o added support for resampling mp3 streams + o DarkIce config file now may contain spaces and tabs as white space + o configure script enables build with or without lame / Ogg Vorbis + also possibility to specify alternate locations for these + +18-09-2001: DarkIce 0.6 released + + o added support for IceCast2 server with Ogg Vorbis streaming + Ogg Vorbis support thanks to aNa|0Gue + o added support for SUN Solaris + o removed long command line options (as these are extensions to UNIX) + o removed configure option to specify location of lame library + o removed configure option to compile static executable + +09-09-2001: DarkIce 0.5 released + + o added support for ShoutCast servers + o removed local copy of SGI STL, uses STL of the C++ compiler + o compiles with gcc3-c++ + o added man page darkice.cfg.5 + o bugfix: config files can have comments before the first section + +02-09-2001: DarkIce 0.4 released + + o support for external command line encoder removed, replaced + with using lame as a shared object or statically linked library + o added darkice man page + o created RPM packages + o DarkIce no longer reports an error if the sound card recording + sample rate could not be set to the exact specified amount + (e.g. the sound card reports 44101 Hz instead of 44100 Hz) + + +26-08-2001: DarkIce 0.3.1 released + + o support for unlimited time encoding + thanks to Jim Crilly, + + +20-12-2000: DarkIce 0.3 released + + o added POSIX real-time scheduling + + +18-11-2000: DarkIce 0.2 released + + o code cleanup + o first real tests made + o added verbosity command line option + + +13-11-2000: DarkIce 0.1 released + diff --git a/darkice/tags/darkice-1_3/FAQ b/darkice/tags/darkice-1_3/FAQ new file mode 100644 index 0000000..d19c4e6 --- /dev/null +++ b/darkice/tags/darkice-1_3/FAQ @@ -0,0 +1,21 @@ +DarkIce Frequenty Asked Questions + + +Q: I get the following error: + +DarkIce: LameLibEncoder.cpp:75: lame lib opening underlying sink error [0] + +What am I doing wrong? + + +A: This error means (quite anti-intuitively), that darkice coulnd't connect + to the streaming server. Please double-check the following values in + your config file: + - server + - port + - password + + If you're streaming to a shoutcast server, make sure that the port + you use is the _source_ port, which is usually 1 above the _client_ + port for shoutcast (the defaults are 8000 for client, 8001 for source). + diff --git a/darkice/tags/darkice-1_3/INSTALL.lame b/darkice/tags/darkice-1_3/INSTALL.lame new file mode 100644 index 0000000..f49d27c --- /dev/null +++ b/darkice/tags/darkice-1_3/INSTALL.lame @@ -0,0 +1,52 @@ +Installing Lame +--------------- + +To install DarkIce, you need the Lame 3.89 or later libraries and +related header files already installed on your system. + +It is recommended that use install Lame to the usual system locations, +/usr/lib, /usr/include, so that DarkIce will find the header files and +libraries. Thus when configuring, add --prefix=/usr to the configure +options. + +Grab the latest lame source tarball from a download site found at +http://www.mp3dev.org/mp3/download/download.html +or from the DarkIce SourceForge project download area +http://sourceforge.net/project/showfiles.php?group_id=14111 + +I took lame lame-3.91.tar.gz. Go to the directory where you saved it, +and issue the following commands: + +tar xfz lame-3.91.tar.gz +cd lame-3.91 +./configure --with-fileio=lame --without-vorbis --disable-gtktest --enable-expopt=full --prefix=/usr +make +make install + +For the last step, you need to be root or have write permissions in the +target directories. + +You might consider using nasm if you're on a i386 system, with the +configure option --enable-nasmm, for maximum performance. + + +On RedHat Linux +--------------- + +Compiling Lame on RedHat Linux is a tricky issue, because of gcc 2.96 +packaged with the distributions 7.0 and 7.1. You either have to use +the comaptibility compiler package (compat-egcs and related packages, +providing gcc 2.91), or even better, gcc 3.0. + +It is recommended that you compile lame with gcc 3. For maximum performance, +use the nasm assembler to compile assembly optimizations into lame. +Try the following commands: + +tar xfz lame-3.91.tar.gz +cd lame-3.91 +export CC=gcc3 +./configure --with-fileio=lame --without-vorbis --disable-gtktest --enable-nasm --enable-expopt=full --prefix=/usr +make +make install + + diff --git a/darkice/tags/darkice-1_3/INSTALL.vorbis b/darkice/tags/darkice-1_3/INSTALL.vorbis new file mode 100644 index 0000000..44d135f --- /dev/null +++ b/darkice/tags/darkice-1_3/INSTALL.vorbis @@ -0,0 +1,39 @@ +Installing Ogg Vorbis +--------------------- + +To install DarkIce, you need the following Ogg Vorbis 1.0 or later +libraries (and related header files): + +- libogg +- libvoribs +- libvorbisenc + +installed on your system. + +It is recommended that use install these to the usual system locations, +/usr/lib, /usr/include, so that DarkIce will find the header files and +libraries. Thus when configuring, add --prefix=/usr to the configure +options. + +Grab the latest Ogg Vorbis tarballs from +http://www.xiph.org/ogg/vorbis/download.html + +I took libogg-1.0.tar.gz and libvorbis-1.0.tar.gz. Go to the +directory where you saved them, and issue the following commands: + +tar xfz libogg-1.0.tar.gz +cd libogg-1.0 +./configure --prefix=/usr +make +make install +cd .. + +tar xfz libvorbis-1.0.tar.gz +cd libvorbis-1.0 +./configure --prefix=/usr +make +make install + +For the install steps, you need to be root or have write permissions in the +target directories. + diff --git a/darkice/tags/darkice-1_3/Makefile.am b/darkice/tags/darkice-1_3/Makefile.am new file mode 100644 index 0000000..ad0f9ba --- /dev/null +++ b/darkice/tags/darkice-1_3/Makefile.am @@ -0,0 +1,7 @@ +SUBDIRS = src man + +sysconf_DATA = darkice.cfg + +EXTRA_DIST = darkice.cfg INSTALL.lame INSTALL.vorbis FAQ rc.darkice + + diff --git a/darkice/tags/darkice-1_3/NEWS b/darkice/tags/darkice-1_3/NEWS new file mode 100644 index 0000000..5bb3f73 --- /dev/null +++ b/darkice/tags/darkice-1_3/NEWS @@ -0,0 +1,136 @@ +14-11-2009, Rafael Diniz, rafael@riseup.net + + Released version 0.20.1. See ChangeLog for changes. + +05-11-2009, Rafael Diniz, rafael@riseup.net + + Released version 0.20. See ChangeLog for changes. + +07-07-2008, Akos Maroy, darkeye@tyrell.hu + + Released version 0.19. See ChangeLog for changes. + +26-04-2007, Akos Maroy, darkeye@tyrell.hu + + Released version 0.18.1. See ChangeLog for changes. + +05-03-2007, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.18. See ChangeLog for changes. + + +19-05-2006, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.17.1. See ChangeLog for changes. + + +26-01-2006, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.17. See ChangeLog for changes. + + +22-10-2005, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.16. See ChangeLog for changes. + + +14-04-2005, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.15. See ChangeLog for changes. + + +15-02-2004, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.14. See ChangeLog for changes. + + +07-01-2004, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.13.2. See ChangeLog for changes. + + +12-02-2003, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.13.1. See ChangeLog for changes. + + +09-02-2003, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.13. See ChangeLog for changes. + + +20-10-2002, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.12. See ChangeLog for changes. + + +20-08-2002, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.11. See ChangeLog for changes. + + +02-08-2002, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.10.1. See ChangeLog for changes. + + +20-07-2002, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.10. See ChangeLog for changes. + + +09-04-2002, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.9.1. See ChangeLog for changes. + + +28-03-2002, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.9. See ChangeLog for changes. + + +20-02-2002, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.8. See ChangeLog for changes. + + +19-10-2001, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.7. See ChangeLog for changes. + + +18-09-2001, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.6. See ChangeLog for changes. + + +09-09-2001, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.5. See ChangeLog for changes. + + +02-09-2001, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.4. See ChangeLog for changes. + + +26-08-2001, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.3.1. See ChangeLog for changes. + + +20-12-2000, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.3. See ChangeLog for changes. + + +18-11-2000, Akos Maroy, darkeye@users.sourceforge.net + + Released version 0.2. See ChangeLog for changes. + + +13-11-2000, Akos Maroy, darkeye@users.sourceforge.net + + Initial release. Supports the lame encoder. + + diff --git a/darkice/tags/darkice-1_3/README b/darkice/tags/darkice-1_3/README new file mode 100644 index 0000000..d5b57a9 --- /dev/null +++ b/darkice/tags/darkice-1_3/README @@ -0,0 +1,75 @@ +DarkIce live audio streamer, http://www.darkice.org/ +Copyright (c) 2000-2007, Tyrell Hungary, http://tyrell.hu/ +Copyright (c) 2008, Ákos Maróy, akos@maroy.hu +Copyright (c) 2009, Rafael Diniz, rafael@riseup.net + + +Contents +-------- + +1. What is DarkIce? +2. Compiling and installing +3. Reporting crashes + + +1. What is DarkIce? +------------------- + +DarkIce is an IceCast, IceCast2 and ShoutCast live audio streamer. It +takes audio input from a sound card, encodes it into mp3 and/or Ogg Vorbis, +and sends the mp3 stream to one or more IceCast and/or ShoutCast servers, +the Ogg Vorbis stream to one or more IceCast2 servers. + +DarkIce website: http://www.darkice.org/ + + +2. Compiling and installing +--------------------------- + +On how to compile and install, please read the file INSTALL. If you're +impatient, try: + +./configure +make + +The executable built is src/darkice. +To install, try as root: + +make install + + +For documentation, try: + +man darkice + + +3. Reporting crashes +-------------------- + +When DarkIce core dumps, please send the backtrace along with your error +report to the darkice mailing list: http://www.freelists.org/list/darkice +Alternatively you could file a bug report at http://www.darkice.org/ +To get the backtrace information, you need gdb, the GNU debugger: + +1. configure and compile using the --with-debug option: + +./configure --with-debug=yes +make clean all + +2. run darkice from within gdb: + +gdb src/darkice + +3. set parameters within gdb: + +(gdb) set args -c darkice.cfg + +4. run: + +(gdb) run + +5. after coredump, print the backtrace: + +(gdb) bt + + diff --git a/darkice/tags/darkice-1_3/TODO b/darkice/tags/darkice-1_3/TODO new file mode 100644 index 0000000..9e12f8d --- /dev/null +++ b/darkice/tags/darkice-1_3/TODO @@ -0,0 +1,13 @@ +o Add samplerate conversion for samplerate audio output different from audio source +o Add Coreaudio support +o change Ref to follow inheritance +o make a master config file, and a small one ? +o add support for multiple servers for one stream ? +o revisit real-time scheduling +o look into performance +o create proper error-reporting module +o set comment fields for Ogg Vorbis streams as in + http://www.xiph.org/ogg/vorbis/doc/v-comment.html +o change config file to separate descriptions of input, streams and + stream targets (servers, files, etc.) +o add support for 24 and 32 bit input and higher sample rates (up to 96kHz) diff --git a/darkice/tags/darkice-1_3/acinclude.m4 b/darkice/tags/darkice-1_3/acinclude.m4 new file mode 100644 index 0000000..dc3e16f --- /dev/null +++ b/darkice/tags/darkice-1_3/acinclude.m4 @@ -0,0 +1,299 @@ +dnl acinclude.m4. Change *this* file to add new or change macros. +dnl When changes have been made, delete aclocal.m4 and run +dnl "aclocal". +dnl +dnl DO NOT change aclocal.m4 ! +dnl + +dnl----------------------------------------------------------------------------- +dnl LA_SEARCH_FILE(variable, filename, PATH) +dnl Search "filename" in the specified "PATH", "variable" will +dnl contain the full pathname or the empty string +dnl PATH is space-separated list of directories. +dnl by Florian Bomers +dnl----------------------------------------------------------------------------- +AC_DEFUN([LA_SEARCH_FILE],[ + $1= + dnl hack: eliminate line feeds in $2 + for FILE in $2; do + for DIR in $3; do + dnl use PATH in order + if test ".$1"="." && test -f "$DIR/$FILE"; then + $1=$DIR + fi + done + done +]) + +dnl----------------------------------------------------------------------------- +dnl LA_SEARCH_LIB(lib-variable, include-variable, lib-filename, header-filename, prefix) +dnl looks for "lib-filename" and "header-filename" in the area of "prefix". +dnl if found, "lib-variable" and "include-variable" are set to the +dnl respective paths. +dnl prefix is a single path +dnl libs are searched in prefix, prefix/lib +dnl headers are searched in prefix, prefix/include, +dnl +dnl If one of them is not found, both "lib-variable", "include-variable" are +dnl set to the empty string. +dnl +dnl TODO: assert function call to verify lib +dnl +dnl by Florian Bomers +dnl----------------------------------------------------------------------------- +AC_DEFUN([LA_SEARCH_LIB],[ + dnl look for lib + LA_SEARCH_FILE($1, $3, $5 $5/lib64 $5/lib $5/lib/x86_64-linux-gnu ) + dnl look for header. + LA_SEARCH_FILE($2, $4, $5 $5/include ) + if test ".$1" = "." || test ".$2" = "."; then + $1= + $2= + fi +]) + + +dnl----------------------------------------------------------------------------- +dnl funky posix threads checking, thanks to +dnl Steven G. Johnson +dnl and Alejandro Forero Cuervo +dnl see http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html +dnl----------------------------------------------------------------------------- +dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +dnl +dnl This macro figures out how to build C programs using POSIX +dnl threads. It sets the PTHREAD_LIBS output variable to the threads +dnl library and linker flags, and the PTHREAD_CFLAGS output variable +dnl to any special C compiler flags that are needed. (The user can also +dnl force certain compiler flags/libs to be tested by setting these +dnl environment variables.) +dnl +dnl Also sets PTHREAD_CC to any special C compiler that is needed for +dnl multi-threaded programs (defaults to the value of CC otherwise). +dnl (This is necessary on AIX to use the special cc_r compiler alias.) +dnl +dnl NOTE: You are assumed to not only compile your program with these +dnl flags, but also link it with them as well. e.g. you should link +dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +dnl +dnl If you are only building threads programs, you may wish to +dnl use these variables in your default LIBS, CFLAGS, and CC: +dnl +dnl LIBS="$PTHREAD_LIBS $LIBS" +dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +dnl CC="$PTHREAD_CC" +dnl +dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute +dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE +dnl to that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +dnl +dnl ACTION-IF-FOUND is a list of shell commands to run if a threads +dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands +dnl to run it if it is not found. If ACTION-IF-FOUND is not specified, +dnl the default action will define HAVE_PTHREAD. +dnl +dnl Please let the authors know if this macro fails on any platform, +dnl or if you have any other suggestions or comments. This macro was +dnl based on work by SGJ on autoconf scripts for FFTW (www.fftw.org) +dnl (with help from M. Frigo), as well as ac_pthread and hb_pthread +dnl macros posted by AFC to the autoconf macro repository. We are also +dnl grateful for the helpful feedback of numerous users. +dnl +dnl @version $Id$ +dnl @author Steven G. Johnson and Alejandro Forero Cuervo + +AC_DEFUN([ACX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_SAVE +AC_LANG_C +acx_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) + AC_MSG_RESULT($acx_pthread_ok) + if test x"$acx_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all. + +acx_pthread_flags="pthread-config pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthread-config: use pthread-config program (on NetBSD) +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# pthread: Linux, etcetera +# --thread-safe: KAI C++ + +case "${host_cpu}-${host_os}" in + *solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthread or + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" + ;; +esac + +if test x"$acx_pthread_ok" = xno; then +for flag in $acx_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) + if test x"$acx_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [acx_pthread_ok=yes]) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT($acx_pthread_ok) + if test "x$acx_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$acx_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: threads are created detached by default + # and the JOINABLE attribute has a nonstandard name (UNDETACHED). + AC_MSG_CHECKING([for joinable pthread attribute]) + AC_TRY_LINK([#include ], + [int attr=PTHREAD_CREATE_JOINABLE;], + ok=PTHREAD_CREATE_JOINABLE, ok=unknown) + if test x"$ok" = xunknown; then + AC_TRY_LINK([#include ], + [int attr=PTHREAD_CREATE_UNDETACHED;], + ok=PTHREAD_CREATE_UNDETACHED, ok=unknown) + fi + if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then + AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok, + [Define to the necessary symbol if this constant + uses a non-standard name on your system.]) + fi + AC_MSG_RESULT(${ok}) + if test x"$ok" = xunknown; then + AC_MSG_WARN([we do not know how to create joinable pthreads]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case "${host_cpu}-${host_os}" in + *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";; + *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; + esac + AC_MSG_RESULT(${flag}) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: must compile with cc_r + AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) +else + PTHREAD_CC="$CC" +fi + +AC_SUBST(PTHREAD_LIBS) +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_CC) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$acx_pthread_ok" = xyes; then + ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) + : +else + acx_pthread_ok=no + $2 +fi +AC_LANG_RESTORE +])dnl ACX_PTHREAD diff --git a/darkice/tags/darkice-1_3/autogen.sh b/darkice/tags/darkice-1_3/autogen.sh new file mode 100755 index 0000000..9af1fbf --- /dev/null +++ b/darkice/tags/darkice-1_3/autogen.sh @@ -0,0 +1,69 @@ +#!/bin/sh +# Run this to set up the build system: configure, makefiles, etc. +# (based on the version in enlightenment's cvs) + +package="darkice" + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +cd "$srcdir" +DIE=0 + +(autoheader --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have autoconf installed to compile $package." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have autoconf installed to compile $package." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(automake --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have automake installed to compile $package." + echo "Download the appropriate package for your system," + echo "or get the source from one of the GNU ftp sites" + echo "listed in http://www.gnu.org/order/ftp.html" + DIE=1 +} + +(libtool --help) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have libtool installed to compile $package." + echo "Download the appropriate package for your system," + echo "or get the source from one of the GNU ftp sites" + echo "listed in http://www.gnu.org/order/ftp.html" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +if test -z "$*"; then + echo "I am going to run ./configure with no arguments - if you wish " + echo "to pass any to it, please specify them on the $0 command line." +fi + +echo "Generating configuration files for $package, please wait...." + +echo " aclocal $ACLOCAL_FLAGS" +aclocal $ACLOCAL_FLAGS +echo " autoheader" +autoheader +echo " libtoolize --automake" +libtoolize --automake +echo " automake --add-missing $AUTOMAKE_FLAGS" +automake --add-missing $AUTOMAKE_FLAGS +echo " autoconf" +autoconf + +$srcdir/configure "$@" && echo diff --git a/darkice/tags/darkice-1_3/configure.in b/darkice/tags/darkice-1_3/configure.in new file mode 100644 index 0000000..8ba9b5f --- /dev/null +++ b/darkice/tags/darkice-1_3/configure.in @@ -0,0 +1,271 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(darkice, 1.3) +AC_CONFIG_SRCDIR(src/DarkIce.cpp) +AM_CONFIG_HEADER(src/config.h) + +AM_INIT_AUTOMAKE + +AC_PROG_CC +AC_PROG_CXX +AC_PROG_INSTALL + +PKG_PROG_PKG_CONFIG + +dnl AC_STDC_HEADERS +AC_HAVE_HEADERS(errno.h fcntl.h stdio.h stdlib.h string.h unistd.h limits.h) +AC_HAVE_HEADERS(signal.h time.h sys/time.h sys/types.h sys/wait.h math.h) +AC_HAVE_HEADERS(netdb.h netinet/in.h sys/ioctl.h sys/socket.h sys/stat.h) +AC_HAVE_HEADERS(sched.h pthread.h termios.h) +AC_HAVE_HEADERS(sys/soundcard.h sys/audio.h sys/audioio.h) +AC_HEADER_SYS_WAIT() + +AC_TYPE_PID_T() +AC_TYPE_SIZE_T() +AC_C_BIGENDIAN() + +AC_CHECK_LIB(socket, socket) +AC_CHECK_LIB(nsl, gethostbyname) +AC_CHECK_LIB(rt, sched_getscheduler) + +AC_CHECK_FUNC(getaddrinfo, AC_DEFINE(HAVE_GETADDRINFO, 1, [Does function getaddrinfo exist?] )) + +dnl----------------------------------------------------------------------------- +dnl funky posix threads checking, thanks to +dnl Steven G. Johnson +dnl and Alejandro Forero Cuervo +dnl see http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html +dnl----------------------------------------------------------------------------- +ACX_PTHREAD(, AC_MSG_ERROR( [pthread library not found] )) + +SYSTEM_INCLUDE=/usr/include + + +dnl----------------------------------------------------------------------------- +dnl link the lame library if requested +dnl----------------------------------------------------------------------------- +AC_SUBST(LAME_CFLAGS) +AC_SUBST(LAME_LIBS) + +AC_ARG_WITH(lame, + AS_HELP_STRING([--with-lame], [use lame for encoding mp3 streams @<:@check@:>@]), + [], with_lame=check) +AC_ARG_WITH(lame-prefix, + AS_HELP_STRING([--with-lame-prefix=DIR], + [alternate location for lame @<:@/usr@:>@. + Look for libraries in LAME-PREFIX/lib, + for headers in LAME-PREFIX/include]), + CONFIG_LAME_PREFIX="${withval}", CONFIG_LAME_PREFIX="/usr") + +if test "x$with_lame" != xno ; then + AC_MSG_CHECKING( [for lame library at ${CONFIG_LAME_PREFIX}] ) + LA_SEARCH_LIB( LAME_LIB_LOC, LAME_INC_LOC, libmp3lame.a libmp3lame.so, lame/lame.h, + ${CONFIG_LAME_PREFIX}) + if test "x${LAME_LIB_LOC}" != "x" ; then + AC_DEFINE( HAVE_LAME_LIB, 1, [build with lame library] ) + if test "x${LAME_INC_LOC}" != "x${SYSTEM_INCLUDE}" ; then + LAME_CFLAGS="-I${LAME_INC_LOC}" + fi + LAME_LIBS="-L${LAME_LIB_LOC} -lmp3lame" + AC_MSG_RESULT( [found at ${CONFIG_LAME_PREFIX}] ) + elif test "x$with_lame" = xyes ; then + AC_MSG_ERROR([unable to find lame library]) + else + AC_MSG_WARN( [not found, building without lame]) + fi +else + AC_MSG_RESULT( [building without lame] ) +fi + + +dnl----------------------------------------------------------------------------- +dnl link the ogg vorbis libraries if requested +dnl----------------------------------------------------------------------------- +AC_ARG_WITH(vorbis, + AS_HELP_STRING([--with-vorbis], [use Ogg Vorbis for encoding vorbis streams @<:@check@:>@]), + [], with_vorbis=check) +AS_CASE([$with_vorbis], + check, [PKG_CHECK_MODULES(VORBIS, [ogg vorbis vorbisenc], [], true)], + yes, [PKG_CHECK_MODULES(VORBIS, [ogg vorbis vorbisenc])], + AC_MSG_RESULT([building without Ogg Vorbis])) +AS_IF(test -n "$VORBIS_LIBS", + AC_DEFINE(HAVE_VORBIS_LIB, 1, [build with Ogg Vorbis library])) + +dnl----------------------------------------------------------------------------- +dnl link the ogg / opus libraries if requested +dnl----------------------------------------------------------------------------- +AC_ARG_WITH(opus, + AS_HELP_STRING([--with-opus], [use Ogg Opus for encoding opus streams @<:@check@:>@]), + [], with_opus=check) +AS_CASE([$with_opus], + check, [PKG_CHECK_MODULES(OPUS, [ogg opus], [], true)], + yes, [PKG_CHECK_MODULES(OPUS, [ogg opus])], + AC_MSG_RESULT([building without Ogg Opus])) +AS_IF(test -n "$OPUS_LIBS", + AC_DEFINE(HAVE_OPUS_LIB, 1, [build with Ogg Opus library])) + +dnl----------------------------------------------------------------------------- +dnl link the faac library if requested +dnl----------------------------------------------------------------------------- +AC_SUBST(FAAC_CFLAGS) +AC_SUBST(FAAC_LIBS) + +AC_ARG_WITH(faac, + AS_HELP_STRING([--with-faac], [use faac for encoding AAC streams @<:@check@:>@]), + [], with_faac=check) +AC_ARG_WITH(faac-prefix, + AS_HELP_STRING([--with-faac-prefix=DIR], + [alternate location for faac @<:@/usr@:>@. + Look for libraries in FAAC-PREFIX/lib, + for headers in FAAC-PREFIX/include]), + CONFIG_FAAC_PREFIX="${withval}", CONFIG_FAAC_PREFIX="/usr") + +if test "x$with_faac" != xno ; then + AC_MSG_CHECKING( [for faac library at ${CONFIG_FAAC_PREFIX}] ) + LA_SEARCH_LIB( FAAC_LIB_LOC, FAAC_INC_LOC, libfaac.a libfaac.so, faac.h, + ${CONFIG_FAAC_PREFIX}) + if test "x${FAAC_LIB_LOC}" != "x" ; then + AC_DEFINE( HAVE_FAAC_LIB, 1, [build with faac library] ) + if test "x${FAAC_INC_LOC}" != "x${SYSTEM_INCLUDE}" ; then + FAAC_CFLAGS="-I${FAAC_INC_LOC}" + fi + FAAC_LIBS="-L${FAAC_LIB_LOC} -lfaac" + AC_MSG_RESULT( [found at ${CONFIG_FAAC_PREFIX}] ) + elif test "x$with_faac" = yes ; then + AC_MSG_ERROR([unable to find faac library]) + else + AC_MSG_WARN( [not found, building without faac]) + fi +else + AC_MSG_RESULT( [building without faac] ) +fi + + +dnl----------------------------------------------------------------------------- +dnl link the aacplus library if requested +dnl----------------------------------------------------------------------------- +AC_ARG_WITH(aacplus, + AS_HELP_STRING([--with-aacplus], [use aacplus for encoding AAC HEv2 streams @<:@check@:>@]), + [], with_aacplus=check) +AS_CASE([$with_aacplus], + check, [PKG_CHECK_MODULES(AACPLUS, aacplus, [], true)], + yes, [PKG_CHECK_MODULES(AACPLUS, aacplus)], + AC_MSG_RESULT([building without aacplus])) +AS_IF(test -n "$AACPLUS_LIBS", + AC_DEFINE(HAVE_AACPLUS_LIB, 1, [build with aacplus library])) + +dnl----------------------------------------------------------------------------- +dnl link the twolame library if requested +dnl----------------------------------------------------------------------------- +AC_ARG_WITH(twolame, + AS_HELP_STRING([--with-twolame], [use twolame for encoding MP2 streams @<:@check@:>@]), + [], with_twolame=check) +AS_CASE([$with_twolame], + check, [PKG_CHECK_MODULES(TWOLAME, twolame, [], true)], + yes, [PKG_CHECK_MODULES(TWOLAME, twolame)], + AC_MSG_RESULT([building without twolame])) +AS_IF(test -n "$TWOLAME_LIBS", + AC_DEFINE(HAVE_TWOLAME_LIB, 1, [build with twolame library])) + +dnl----------------------------------------------------------------------------- +dnl make sure at least one of lame and vorbis present +dnl----------------------------------------------------------------------------- +if test -z "x${LAME_LIBS}" \ + -a -z "${VORBIS_LIBS}" \ + -a -z "${OPUS_LIBS}" \ + -a -z "${FAAC_LIBS}" \ + -a -z "${AACPLUS_LIBS}" \ + -a -z "${TWOLAME_LIBS}" ; then + AC_MSG_ERROR([neither lame, Ogg Vorbis, opus, faac, aac+ nor twolame configured]) +fi + + +dnl----------------------------------------------------------------------------- +dnl link ALSA sound system if requested +dnl----------------------------------------------------------------------------- +AC_ARG_WITH(alsa, + AS_HELP_STRING([--with-alsa], [use ALSA sound system @<:@check@:>@]), + [], with_alsa=check) +AS_CASE([$with_alsa], + check, [PKG_CHECK_MODULES(ALSA, alsa, [], true)], + yes, [PKG_CHECK_MODULES(ALSA, alsa)], + AC_MSG_RESULT([building without ALSA support])) +AS_IF(test -n "$ALSA_LIBS", + AC_DEFINE(HAVE_ALSA_LIB, 1, [build with ALSA sound system])) + +dnl----------------------------------------------------------------------------- +dnl link PULSEAUDIO sound system if requested +dnl----------------------------------------------------------------------------- +AC_ARG_WITH(pulseaudio, + AS_HELP_STRING([--with-pulseaudio], [use PULSEAUDIO sound system @<:@check@:>@]), + [], with_pulseaudio=check) +AS_CASE([$with_pulseaudio], + check, [PKG_CHECK_MODULES(PULSEAUDIO, libpulse-simple libpulse, [], true)], + yes, [PKG_CHECK_MODULES(PULSEAUDIO, libpulse-simple libpulse)], + AC_MSG_RESULT([building without PULSEAUDIO support])) +AS_IF(test -n "$PULSEAUDIO_LIBS", + AC_DEFINE(HAVE_PULSEAUDIO_LIB, 1, [build with PULSEAUDIO sound system])) + +dnl----------------------------------------------------------------------------- +dnl link JACK sound server if requested +dnl----------------------------------------------------------------------------- +AC_ARG_WITH(jack, + AS_HELP_STRING([--with-jack], [use JACK sound system @<:@check@:>@]), + [], with_jack=check) +AS_CASE([$with_jack], + check, [PKG_CHECK_MODULES(JACK, jack, [], true)], + yes, [PKG_CHECK_MODULES(JACK, jack)], + AC_MSG_RESULT([building without JACK support])) +AS_IF(test -n "$JACK_LIBS", + AC_DEFINE(HAVE_JACK_LIB, 1, [build with JACK audio server support])) + +dnl----------------------------------------------------------------------------- +dnl link Secret Rabbit Code (aka libsamplerate) if requested +dnl----------------------------------------------------------------------------- +AC_ARG_WITH(samplerate, + AS_HELP_STRING([--with-samplerate], [use Secret Rabbit Code (aka libsamplerate) for samplerate conversion @<:@check@:>@]), + [], with_samplerate=check) +AS_CASE([$with_samplerate], + check, [PKG_CHECK_MODULES(SRC, samplerate, [], true)], + yes, [PKG_CHECK_MODULES(SRC, samplerate)], + AC_MSG_RESULT([building without libsamplerate support])) +AS_IF(test -n "$SRC_LIBS", + AC_DEFINE(HAVE_SRC_LIB, 1, [build with samplerate conversion through libsamplerate])) + +AM_CONDITIONAL(HAVE_SRC_LIB, test -n "${SRC_LIBS}") +dnl----------------------------------------------------------------------------- +dnl check for MSG_NOSIGNAL for the send() function in libsocket +dnl----------------------------------------------------------------------------- +AC_MSG_CHECKING(for MSG_NOSIGNAL) +AC_TRY_COMPILE([#include ], [ + int f = MSG_NOSIGNAL; +], [ + # Yes, we have it... + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MSG_NOSIGNAL, 1, [use MSG_NOSIGNAL for send()]) +], [ + # We'll have to use signals + AC_MSG_RESULT(no) +]) + + +dnl----------------------------------------------------------------------------- +dnl check for POSIX real-time scheduling +dnl----------------------------------------------------------------------------- +AC_CHECK_FUNCS( sched_getscheduler sched_getparam ) + + +dnl----------------------------------------------------------------------------- +dnl enable compilation with debug flags +dnl----------------------------------------------------------------------------- +AC_SUBST(DEBUG_CXXFLAGS) + +AC_ARG_ENABLE(debug, + AS_HELP_STRING([--enable-debug], [enable debug mode @<:@no@:>@]), + [], enable_debug=no) +AS_IF([test "x$enable_debug" = xyes], + [DEBUG_CXXFLAGS="-g" + AC_MSG_RESULT([compiling in debug mode])], + AC_MSG_RESULT([not compiling in debug mode])) + +AC_OUTPUT(Makefile src/Makefile man/Makefile) + diff --git a/darkice/tags/darkice-1_3/darkice.cfg b/darkice/tags/darkice-1_3/darkice.cfg new file mode 100644 index 0000000..4ccf1c6 --- /dev/null +++ b/darkice/tags/darkice-1_3/darkice.cfg @@ -0,0 +1,84 @@ +# sample DarkIce configuration file, edit for your needs before using +# see the darkice.cfg man page for details + +# this section describes general aspects of the live streaming session +[general] +duration = 60 # duration of encoding, in seconds. 0 means forever +bufferSecs = 5 # size of internal slip buffer, in seconds +reconnect = yes # reconnect to the server(s) if disconnected +realtime = yes # run the encoder with POSIX realtime priority +rtprio = 3 # scheduling priority for the realtime threads + +# this section describes the audio input that will be streamed +[input] +device = /dev/dsp # OSS DSP soundcard device for the audio input +sampleRate = 22050 # sample rate in Hz. try 11025, 22050 or 44100 +bitsPerSample = 16 # bits per sample. try 16 +channel = 2 # channels. 1 = mono, 2 = stereo + +# this section describes a streaming connection to an IceCast2 server +# there may be up to 8 of these sections, named [icecast2-0] ... [icecast2-7] +# these can be mixed with [icecast-x] and [shoutcast-x] sections +[icecast2-0] +bitrateMode = abr # average bit rate +format = vorbis # format of the stream: ogg vorbis +bitrate = 96 # bitrate of the stream sent to the server +server = yp.yourserver.com + # host name of the server +port = 8000 # port of the IceCast2 server, usually 8000 +password = hackme # source password to the IceCast2 server +mountPoint = sample96 # mount point of this stream on the IceCast2 server +name = DarkIce trial + # name of the stream +description = This is only a trial + # description of the stream +url = http://www.yourserver.com + # URL related to the stream +genre = my own # genre of the stream +public = yes # advertise this stream? +localDumpFile = dump.ogg # local dump file + +# this section describes a streaming connection to an IceCast server +# there may be up to 8 of these sections, named [icecast-0] ... [icecast-7] +# these can be mixed with [icecast2-x] and [shoutcast-x] sections +[icecast-0] +bitrateMode = cbr # constant bit rate +bitrate = 96 # bitrate of the mp3 stream sent to the server +quality = 0.8 # encoding quality +server = yp.yourserver.com + # host name of the server +port = 8000 # port of the IceCast server, usually 8000 +password = hackme # source password to the IceCast server +mountPoint = sample96 # mount point of this stream on the IceCast server +name = DarkIce trial + # name of the stream +description = This is only a trial + # description of the stream +url = http://www.yourserver.com + # URL related to the stream +genre = my own # genre of the stream +public = yes # advertise this stream? + +# this section describes a streaming connection to a ShoutCast server +# there may be up to 8 of these sections, named [shoutcast-0] ... [shoutcast-7] +# these can be mixed with [icecast-x] and [icecast2-x] sections +[shoutcast-0] +bitrateMode = vbr # variable bit rate mode +quality = 0.5 # encoding quality +server = yp.yourserver.com + # host name of the server +port = 8001 # source port of the ShoutCast server, usually 8001 +password = hackme # source password to the ShoutCast server +name = DarkIce trial + # name of the stream +url = http://www.yourserver.com + # URL related to the stream +genre = my own # genre of the stream +public = yes # advertise this stream? +irc = irc.yourserver.com + # IRC info related to the stream +aim = aim here # AIM info related to the stream +icq = I see you too + # ICQ info related to the stream + + diff --git a/darkice/tags/darkice-1_3/etc/doxygen.config b/darkice/tags/darkice-1_3/etc/doxygen.config new file mode 100644 index 0000000..4700454 --- /dev/null +++ b/darkice/tags/darkice-1_3/etc/doxygen.config @@ -0,0 +1,1150 @@ +#------------------------------------------------------------------------------- +# +# Copyright (c) 2000 Tyrell Corporation. All rights reserved. +# +# Tyrell DarkIce +# +# File : main.cpp +# Version : $Revision$ +# Author : $Author$ +# Location : $Source$ +# +# Abstract : +# +# Program entry point +# +# Copyright notice: +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +#------------------------------------------------------------------------------- + +# Doxyfile 1.3.6 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = DarkIce + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 1.0 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc/doxygen + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, +# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en +# (Japanese with English messages), Korean, Korean-en, Norwegian, Polish, Portuguese, +# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for +# all platforms other than Windows). + +USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is used +# as the annotated text. Otherwise, the brief description is used as-is. If left +# blank, the following values are used ("$name" is automatically replaced with the +# name of the entity): "The $name class" "The $name widget" "The $name file" +# "is" "provides" "specifies" "contains" "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = YES + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES # needed by storageServer docs + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = src + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# that are symbolic links (a Unix filesystem feature) are excluded from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse the +# parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superseded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes that +# lay further from the root node will be omitted. Note that setting this option to +# 1 or 2 may greatly reduce the computation time needed for large code bases. Also +# note that a graph may be further truncated if the graph's image dimensions are +# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). +# If 0 is used for the depth value (the default), the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.15.ebuild b/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.15.ebuild new file mode 100644 index 0000000..3db3aec --- /dev/null +++ b/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.15.ebuild @@ -0,0 +1,42 @@ +IUSE="encode oggvorbis alsa jack" + +DESCRIPTION="IceCast live streamer delivering Ogg and mp3 streams simultaneously to multiple hosts." +HOMEPAGE="http://darkice.sourceforge.net/" +SRC_URI="mirror://sourceforge/${PN}/${P}.tar.gz" +RESTRICT="nomirror" + +SLOT="0" +LICENSE="GPL-2" +KEYWORDS="~x86 ~ppc ~sparc ~alpha ~hppa ~amd64" + +DEPEND="encode? ( >=media-sound/lame-3.89 ) + oggvorbis? ( >=media-libs/libvorbis-1.0 ) + alsa? ( >=media-libs/alsa-lib-1.0.0 ) + jack? ( media-sound/jack-audio-connection-kit )" + +src_compile() { + if ! use encode && ! use oggvorbis + then + + eerror "You need support for mp3 or Ogg Vorbis enconding for this" + eerror "package. Please merge again with at least one of the " + eerror "\`encode' and \`oggvorbis' USE flags enabled:" + eerror + eerror " # USE=\"encode\" emerge darkice" + eerror " # USE=\"oggvorbis\" emerge darkice" + die "Won't build without support for lame nor vorbis" + fi + + econf `use_with alsa` \ + `use_with encode lame` \ + `use_with oggvorbis vorbis` \ + `use_with jack` || die + + emake || die "Compilation failed" +} + +src_install() { + einstall darkicedocdir=${D}/usr/share/doc/${PF} || die + + dodoc AUTHORS ChangeLog COPYING NEWS README TODO +} diff --git a/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.16.ebuild b/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.16.ebuild new file mode 100644 index 0000000..3c997ad --- /dev/null +++ b/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.16.ebuild @@ -0,0 +1,45 @@ +IUSE="encode oggvorbis aac alsa jack" + +DESCRIPTION="IceCast live streamer delivering Ogg, mp3 or aac streams simultaneously to multiple hosts." +HOMEPAGE="http://darkice.sourceforge.net/" +SRC_URI="mirror://sourceforge/${PN}/${P}.tar.gz" +RESTRICT="nomirror" + +SLOT="0" +LICENSE="GPL-2" +KEYWORDS="~x86 ~ppc ~sparc ~alpha ~hppa ~amd64" + +DEPEND="encode? ( >=media-sound/lame-3.89 ) + oggvorbis? ( >=media-libs/libvorbis-1.0 ) + aac? ( >=media-libs/faac-1.24 ) + alsa? ( >=media-libs/alsa-lib-1.0.0 ) + jack? ( media-sound/jack-audio-connection-kit )" + +src_compile() { + if ! use encode && ! use oggvorbis && ! use aac + then + + eerror "You need support for mp3, Ogg Vorbis or FAAC enconding for this" + eerror "package. Please merge again with at least one of the " + eerror "\`encode', \`oggvorbis' or \'aac' USE flags enabled:" + eerror + eerror " # USE=\"encode\" emerge darkice" + eerror " # USE=\"oggvorbis\" emerge darkice" + eerror " # USE=\"aac\" emerge darkice" + die "Won't build without support for lame, vorbis or aac" + fi + + econf `use_with alsa` \ + `use_with encode lame` \ + `use_with oggvorbis vorbis` \ + `use_with aac faac` \ + `use_with jack` || die + + emake || die "Compilation failed" +} + +src_install() { + einstall darkicedocdir=${D}/usr/share/doc/${PF} || die + + dodoc AUTHORS ChangeLog COPYING NEWS README TODO +} diff --git a/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.17.1.ebuild b/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.17.1.ebuild new file mode 100644 index 0000000..ae70ac0 --- /dev/null +++ b/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.17.1.ebuild @@ -0,0 +1,43 @@ +# Copyright 1999-2006 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header$ + +DESCRIPTION="IceCast live streamer, delivering ogg and mp3 streams simultaneously to multiple hosts." +HOMEPAGE="http://darkice.sourceforge.net/" +SRC_URI="mirror://sourceforge/${PN}/${P}.tar.gz" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~alpha ~amd64 ~hppa ~ppc ~sparc ~x86" +IUSE="alsa encode jack vorbis" + +DEPEND="encode? ( >=media-sound/lame-1.89 ) + vorbis? ( >=media-libs/libvorbis-1.0 ) + alsa? ( >=media-libs/alsa-lib-1.0.0 ) + jack? ( media-sound/jack-audio-connection-kit )" + +src_compile() { + if ! use encode && ! use vorbis + then + + eerror "You need support for mp3 or Ogg Vorbis enconding for this" + eerror "package. Please merge again with at least one of the " + eerror "\`encode' and \`vorbis' USE flags enabled:" + eerror + eerror " # USE=\"encode\" emerge darkice" + eerror " # USE=\"vorbis\" emerge darkice" + die "Won't build without support for lame nor vorbis" + fi + + econf $(use_with alsa) \ + $(use_with encode lame) \ + $(use_with jack) \ + $(use_with vorbis) || die "configuration failed" + emake || die "Compilation failed" +} + +src_install() { + einstall darkicedocdir=${D}/usr/share/doc/${PF} || die "make install failed" + + dodoc AUTHORS ChangeLog NEWS README TODO +} diff --git a/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.17.ebuild b/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.17.ebuild new file mode 100644 index 0000000..c40b481 --- /dev/null +++ b/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.17.ebuild @@ -0,0 +1,48 @@ +IUSE="encode mp2 oggvorbis aac alsa jack" + +DESCRIPTION="IceCast live streamer delivering Ogg, mp3, mp2 or aac streams simultaneously to multiple hosts." +HOMEPAGE="http://darkice.sourceforge.net/" +SRC_URI="mirror://sourceforge/${PN}/${P}.tar.gz" +RESTRICT="nomirror" + +SLOT="0" +LICENSE="GPL-2" +KEYWORDS="~x86 ~ppc ~sparc ~alpha ~hppa ~amd64" + +DEPEND="encode? ( >=media-sound/lame-3.89 ) + mp2? ( >=media-sound/twolame-0.3.6 ) + oggvorbis? ( >=media-libs/libvorbis-1.0 ) + aac? ( >=media-libs/faac-1.24 ) + alsa? ( >=media-libs/alsa-lib-1.0.0 ) + jack? ( media-sound/jack-audio-connection-kit )" + +src_compile() { + if ! use encode && ! use mp2 && ! use oggvorbis && ! use aac + then + + eerror "You need support for mp3, Ogg Vorbis or FAAC enconding for this" + eerror "package. Please merge again with at least one of the " + eerror "\`encode', \'mp2', \`oggvorbis' or \'aac' USE flags enabled:" + eerror + eerror " # USE=\"encode\" emerge darkice" + eerror " # USE=\"mp2\" emerge darkice" + eerror " # USE=\"oggvorbis\" emerge darkice" + eerror " # USE=\"aac\" emerge darkice" + die "Won't build without support for lame, mp2, vorbis or aac" + fi + + econf `use_with alsa` \ + `use_with encode lame` \ + `use_with mp2 twolame` \ + `use_with oggvorbis vorbis` \ + `use_with aac faac` \ + `use_with jack` || die + + emake || die "Compilation failed" +} + +src_install() { + einstall darkicedocdir=${D}/usr/share/doc/${PF} || die + + dodoc AUTHORS ChangeLog COPYING NEWS README TODO +} diff --git a/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.18.1.ebuild b/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.18.1.ebuild new file mode 100644 index 0000000..04500eb --- /dev/null +++ b/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.18.1.ebuild @@ -0,0 +1,43 @@ +# Copyright 1999-2006 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header$ + +DESCRIPTION="IceCast live streamer, delivering ogg and mp3 streams simultaneously to multiple hosts." +HOMEPAGE="http://darkice.tyrell.hu/" +SRC_URI="http://darkice.tyrell.hu/dist/${PV}/${P}.tar.gz" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~alpha ~amd64 ~hppa ~ppc ~sparc ~x86" +IUSE="alsa encode jack vorbis" + +DEPEND="encode? ( >=media-sound/lame-1.89 ) + vorbis? ( >=media-libs/libvorbis-1.0 ) + alsa? ( >=media-libs/alsa-lib-1.0.0 ) + jack? ( media-sound/jack-audio-connection-kit )" + +src_compile() { + if ! use encode && ! use vorbis + then + + eerror "You need support for mp3 or Ogg Vorbis enconding for this" + eerror "package. Please merge again with at least one of the " + eerror "\`encode' and \`vorbis' USE flags enabled:" + eerror + eerror " # USE=\"encode\" emerge darkice" + eerror " # USE=\"vorbis\" emerge darkice" + die "Won't build without support for lame nor vorbis" + fi + + econf $(use_with alsa) \ + $(use_with encode lame) \ + $(use_with jack) \ + $(use_with vorbis) || die "configuration failed" + emake || die "Compilation failed" +} + +src_install() { + einstall darkicedocdir=${D}/usr/share/doc/${PF} || die "make install failed" + + dodoc AUTHORS ChangeLog NEWS README TODO +} diff --git a/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.18.ebuild b/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.18.ebuild new file mode 100644 index 0000000..04500eb --- /dev/null +++ b/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.18.ebuild @@ -0,0 +1,43 @@ +# Copyright 1999-2006 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header$ + +DESCRIPTION="IceCast live streamer, delivering ogg and mp3 streams simultaneously to multiple hosts." +HOMEPAGE="http://darkice.tyrell.hu/" +SRC_URI="http://darkice.tyrell.hu/dist/${PV}/${P}.tar.gz" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~alpha ~amd64 ~hppa ~ppc ~sparc ~x86" +IUSE="alsa encode jack vorbis" + +DEPEND="encode? ( >=media-sound/lame-1.89 ) + vorbis? ( >=media-libs/libvorbis-1.0 ) + alsa? ( >=media-libs/alsa-lib-1.0.0 ) + jack? ( media-sound/jack-audio-connection-kit )" + +src_compile() { + if ! use encode && ! use vorbis + then + + eerror "You need support for mp3 or Ogg Vorbis enconding for this" + eerror "package. Please merge again with at least one of the " + eerror "\`encode' and \`vorbis' USE flags enabled:" + eerror + eerror " # USE=\"encode\" emerge darkice" + eerror " # USE=\"vorbis\" emerge darkice" + die "Won't build without support for lame nor vorbis" + fi + + econf $(use_with alsa) \ + $(use_with encode lame) \ + $(use_with jack) \ + $(use_with vorbis) || die "configuration failed" + emake || die "Compilation failed" +} + +src_install() { + einstall darkicedocdir=${D}/usr/share/doc/${PF} || die "make install failed" + + dodoc AUTHORS ChangeLog NEWS README TODO +} diff --git a/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.19.ebuild b/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.19.ebuild new file mode 100644 index 0000000..04500eb --- /dev/null +++ b/darkice/tags/darkice-1_3/etc/ebuild/darkice-0.19.ebuild @@ -0,0 +1,43 @@ +# Copyright 1999-2006 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header$ + +DESCRIPTION="IceCast live streamer, delivering ogg and mp3 streams simultaneously to multiple hosts." +HOMEPAGE="http://darkice.tyrell.hu/" +SRC_URI="http://darkice.tyrell.hu/dist/${PV}/${P}.tar.gz" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~alpha ~amd64 ~hppa ~ppc ~sparc ~x86" +IUSE="alsa encode jack vorbis" + +DEPEND="encode? ( >=media-sound/lame-1.89 ) + vorbis? ( >=media-libs/libvorbis-1.0 ) + alsa? ( >=media-libs/alsa-lib-1.0.0 ) + jack? ( media-sound/jack-audio-connection-kit )" + +src_compile() { + if ! use encode && ! use vorbis + then + + eerror "You need support for mp3 or Ogg Vorbis enconding for this" + eerror "package. Please merge again with at least one of the " + eerror "\`encode' and \`vorbis' USE flags enabled:" + eerror + eerror " # USE=\"encode\" emerge darkice" + eerror " # USE=\"vorbis\" emerge darkice" + die "Won't build without support for lame nor vorbis" + fi + + econf $(use_with alsa) \ + $(use_with encode lame) \ + $(use_with jack) \ + $(use_with vorbis) || die "configuration failed" + emake || die "Compilation failed" +} + +src_install() { + einstall darkicedocdir=${D}/usr/share/doc/${PF} || die "make install failed" + + dodoc AUTHORS ChangeLog NEWS README TODO +} diff --git a/darkice/tags/darkice-1_3/etc/ebuild/twolame-0.3.6.ebuild b/darkice/tags/darkice-1_3/etc/ebuild/twolame-0.3.6.ebuild new file mode 100644 index 0000000..40d3848 --- /dev/null +++ b/darkice/tags/darkice-1_3/etc/ebuild/twolame-0.3.6.ebuild @@ -0,0 +1,21 @@ +# Copyright 1999-2006 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header$ + +IUSE="" +DESCRIPTION="TwoLAME is an optimised MPEG Audio Layer 2 (MP2) encoder" +HOMEPAGE="http://www.twolame.org/" +SRC_URI="mirror://sourceforge/${PN}/${P}.tar.gz" +RESTRICT="nomirror" + +SLOT="0" +LICENSE="GPL-2" +KEYWORDS="~x86 ~ppc ~sparc ~alpha ~hppa ~amd64" + +DEPEND=">=media-libs/libsndfile-1.0.11" + +src_install() { + make DESTDIR=${D} || die + + dodoc AUTHORS ChangeLog COPYING README TODO +} diff --git a/darkice/tags/darkice-1_3/etc/rpm/darkice.spec b/darkice/tags/darkice-1_3/etc/rpm/darkice.spec new file mode 100644 index 0000000..ee85641 --- /dev/null +++ b/darkice/tags/darkice-1_3/etc/rpm/darkice.spec @@ -0,0 +1,60 @@ +%{!?dist: %define dist fc3} + +Summary : DarkIce live IceCast / ShoutCast streamer +Name: darkice +Vendor: Tyrell Hungary +Packager: Akos Maroy +Version: 0.18 +Release: 1.%{dist} +Copyright: GPL +Group: Applications/Multimedia +Source: http://prdownloads.sourceforge.net/darkice/darkice-%{version}.tar.gz +URL: http://darkice.sourceforge.net/ +Provides: darkice +BuildRoot: %{_tmppath}/%{name}-%{version}-root +BuildPrereq: lame-devel libogg-devel libvorbis-devel +%if %{dist} != el3 +BuildPrereq: jack-audio-connection-kit-devel +%endif +Prefix: /usr + +%description +DarkIce is an IceCast, IceCast2 and ShoutCast live audio streamer. It +takes audio input from a sound card, encodes it into mp3 and/or Ogg Vorbis, +and sends the mp3 stream to one or more IceCast and/or ShoutCast servers, +the Ogg Vorbis stream to one or more IceCast2 servers. + +%prep +%setup + +%build +%configure \ +%if %{dist} == el3 + --without-alsa --without-jack +%endif + +make all + +%install +rm -fr %{buildroot} +%makeinstall + +%clean +rm -rf %{buildroot} + +%files +%defattr (-, root, root) +%doc COPYING ChangeLog README TODO AUTHORS +%config(noreplace) %{_sysconfdir}/darkice.cfg +%{_bindir}/darkice +%{_mandir}/man1/darkice.1* +%{_mandir}/man5/darkice.cfg.5* + + +%changelog +* Thu May 18 2006 Akos Maroy 0.18-1 +- rewrite the spec file for 0.18 +* Tue Apr 19 2005 Akos Maroy 0.16-1 +- rewrite the spec file for 0.16 +* Tue Apr 19 2005 Akos Maroy 0.15-1 +- rewrite the spec file for 0.15 diff --git a/darkice/tags/darkice-1_3/etc/rpm/lame.spec b/darkice/tags/darkice-1_3/etc/rpm/lame.spec new file mode 100644 index 0000000..8c6ecbb --- /dev/null +++ b/darkice/tags/darkice-1_3/etc/rpm/lame.spec @@ -0,0 +1,151 @@ +#------------------------------------------------------------------------------- +# +# Copyright (c) 2000 Tyrell Corporation. All rights reserved. +# +# Tyrell DarkIce +# +# File : lame.spec +# Version : $Revision$ +# Author : $Author$ +# Location : $Source$ +# +# Abstract : +# +# Specification file to build RPM packages of lame. +# Builds a proper lame executable on a RedHat 7.1 system. +# Based on the official lame RPM spec file by +# cefiar +# +# Copyright notice: +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +#------------------------------------------------------------------------------- + +# ================================================================= local macros +%define name lame +%define ver 3.91 +%define rel 1 +%define prefix /usr + + +# ===================================================================== preamble +Summary : LAME Ain't an MP3 Encoder +Name: %{name} +Version: %{ver} +Release: %{rel} +Copyright: LGPL +Vendor: The LAME Project +Packager: Akos Maroy +URL: http://www.mp3dev.org/mp3/ +Group: Applications/Multimedia +Source: http://prdownloads.sourceforge.net/darkice/%{name}-%{ver}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{ver}-root +Prefix: %{prefix} +Provides: lame + +%description +LAME is an educational tool to be used for learning about MP3 encoding. The +goal of the LAME project is to use the open source model to improve the +psycho acoustics, noise shaping and speed of MP3. Another goal of the LAME +project is to use these improvements for the basis of a patent free audio +compression codec for the GNU project. + +This build is optimized for %{_target}. + +# ============================================================ devel sub-package +%package devel +Summary: Shared and static libraries for LAME. +Group: Development/Libraries +Requires: %{name} = %{version} + +%description devel +LAME is an educational tool to be used for learning about MP3 encoding. +This package contains both the shared and the static libraries from the +LAME project. + +You will also need to install the main lame package in order to install +these libraries. + +This build is optimized for %{_target}. + +# =================================================================== prep stage +%prep +%setup -n %{name}-%{ver} + + +# ================================================================== build stage +%build +export CC=gcc3 +export CFLAGS="-O9" +%configure --with-fileio=lame \ + --without-vorbis \ + --disable-gtktest \ + --enable-nasm \ + --enable-expopt=full +make + + +# ================================================================ install stage +%install +%makeinstall + + +# ======================================================================== clean +%clean +rm -rf $RPM_BUILD_ROOT +make clean + + +# =========================================================== main package files +%files +%defattr (-,root,root) +%doc LICENSE USAGE COPYING TODO README* +%doc doc/html +%{_bindir}/lame +%{_mandir}/man1/lame.1* +%{_libdir}/libmp3lame.so.* + + +# ====================================================== devel sub-package files +%files devel +%defattr (-,root,root) +%doc API HACKING STYLEGUIDE +%{_includedir}/lame/lame.h +%{_libdir}/libmp3lame.la +%{_libdir}/libmp3lame.a +%{_libdir}/libmp3lame.so + + +# =================================================================== change log +# +# $Log$ +# Revision 1.1 2005/04/14 11:58:08 darkeye +# moved directory rpm to etc/rpm +# +# Revision 1.4 2002/02/19 14:52:41 darkeye +# updated for lame 3.91 +# +# Revision 1.3 2001/09/13 05:06:41 darkeye +# removed references to SourceForget FTP sites, as they are phased out +# +# Revision 1.2 2001/09/09 09:06:26 darkeye +# lame RPM is now created with gcc3 and full optimizations +# +# Revision 1.1 2001/09/02 12:46:05 darkeye +# added RPM package creation scripts +# +# + diff --git a/darkice/tags/darkice-1_3/man/Makefile.am b/darkice/tags/darkice-1_3/man/Makefile.am new file mode 100644 index 0000000..8406ddd --- /dev/null +++ b/darkice/tags/darkice-1_3/man/Makefile.am @@ -0,0 +1,4 @@ +man_MANS = darkice.1 darkice.cfg.5 + +EXTRA_DIST = ${man_MANS} + diff --git a/darkice/tags/darkice-1_3/man/darkice.1 b/darkice/tags/darkice-1_3/man/darkice.1 new file mode 100644 index 0000000..fbce9c0 --- /dev/null +++ b/darkice/tags/darkice-1_3/man/darkice.1 @@ -0,0 +1,160 @@ +.TH darkice 1 "November 20, 2007" "DarkIce" "DarkIce live audio streamer" +.SH NAME +darkice \- an icecast / shoutcast live audio streamer +.SH SYNOPSIS +.B darkice +[options] -c config.file +.SH DESCRIPTION +.PP +DarkIce as a live audio streamer. It records audio from an audio interface (e.g. sound card), encodes it and sends it to a streaming server. +DarkIce can record from: + + * OSS audio devices + * ALSA audio devices + * Solaris audio interface + * Jack sources + * PulseAudio sources + +DarkIce can encode in the following formats: + + * mp3 - using the lame library + * mp2 - using the twolame library + * Ogg Vorbis + * Ogg Opus + * AAC - using the faac library + * AAC HEv2 - using the libaacplus (3GPP reference code) + +DarkIce can send the encoded stream to the following streaming servers: + + * ShoutCast + * IceCast 1.3.x and 2.x + * Darwin Streaming Server + +Darkice runs on the following operating systems: + + * FreeBSD + * Linux on intel and PowerPC + * MacOS X + * NetBSD / OpenBSD + * SUN Solaris + +.B DarkIce +uses +.SM POSIX +real-time scheduling to keep up with sound card input. +.SM POSIX +real-time scheduling is only available if the program is run as root. +Therefore it is recommended that +.B DarkIce +is run as root. + +.SH OPTIONS +.TP +.BI "\-c " config.file +Specifies what configuration file to use. +If not specified, /etc/darkice.cfg will be used. + +.TP +.BI "\-v " n +Sets the verbosity level, between 0 and 10. 0 is silent, 10 is loud. +Defaults to 1. + +.TP +.BI "\-h " +Prints the help page and exits. + + +.SH BUGS +.PP +Lots of bugs. + + +.SH "SEE ALSO" +darkice.cfg(5) + + +.SH AUTHOR +Akos Maroy +.I + + +.SH ACKNOWLEDGEMENTS +Developed with contributions by + + Jim Crilly, + aNa|0Gue, + Robin P. Blanchard, + Tom Gray, + Michael Smith, + Julius O. Smith, + the OSALP team, http://osalp.sourceforge.net + Kristjan G. Bjarnason + Nicu Pavel + Kai Krakow + Atsuhiko Yamanaka + Ricardo Galli + John Hay + Christian Forster + John Deeny + Robert Lunnon + Enrico Ardizzoni + Deti Fliegl + Nicholas J. Humfrey + Joel Ebel + + Alexander Vlasov + Mariusz Mazur + dsk + Clyde Stubbs + Jens Maurer + Elod Horvath + Pierre Souchay + Daniel Hazelbaker + Alessandro Beretta + Roland Hermans + Rafael Diniz + +.SH LINKS +Project homepage: +.I http://code.google.com/p/darkice/ + +.B IceCast +homepage: +.I http://www.icecast.org/ + +.B ShoutCast +homepage: +.I http://www.shoutcast.com/ + +.B Darwin Streaming Server +homepage: +.I http://developer.apple.com/darwin/projects/streaming/ + +.B Lame +homepage: +.I http://www.mp3dev.org/mp3/ + +.B TwoLame +homepage: +.I http://www.twolame.org/ + +.B Ogg Vorbis +homepage: +.I http://www.xiph.org/ogg/vorbis/ + +.B Ogg Opus +homepage +.I http://www.opus-codec.org/ + +.B faac +homepage: +.I http://www.audiocoding.com/ + +.B libaacplus +homepage: +.I http://tipok.org.ua/node/17 + +.B DarkSnow +GTK front-end: +.I http://darksnow.radiolivre.org/index.en.html +written by Rafael Diniz diff --git a/darkice/tags/darkice-1_3/man/darkice.cfg.5 b/darkice/tags/darkice-1_3/man/darkice.cfg.5 new file mode 100644 index 0000000..ea72600 --- /dev/null +++ b/darkice/tags/darkice-1_3/man/darkice.cfg.5 @@ -0,0 +1,688 @@ +.TH darkice.cfg 5 "February 25, 2007" "DarkIce" "DarkIce live audio streamer" +.SH NAME +darkice.cfg \- configuration file for darkice +.SH DESCRIPTION +.PP +The configuration file consists of sections, with key = value pairs +separated with spaces and/or tabs inside each secion: + +.nf +[section1] +# this is a whole line comment +key = value +an ugly key name = long value # this end is a comment too + +[section2] +# this is a whole line comment in section 2 +key = value +an ugly key name = long value # this end is a comment too +.fi + +A proper +.B DarkIce +configuration file contains the following sections: +.nf +[general] +[input] +[icecast-0] ... [icecast-7] +[icecast2-0] ... [icecast2-7] +[shoutcast-0] ... [shoutcast-7] +[file-0] ... [file-7] +.fi + +The order of the sections is not important. Sections [general] and [input] +are required, and at least one of [icecast-x], [icecast2-x], [shoutcast-x] +or [file-x] is needed. + +In particular, the following sections and values are recognized: +.PP +.B [general] + +This section describes general operational parameters (required). + +Required values: + +.TP +.I duration +Time for DarkIce to run, in seconds. If 0, run forever. +.TP +.I bufferSecs +Data read from the sound card is buffered before sent to +the encoder. Each buffer will be able to hold this +many seconds of samples. + +.PP +Optional values: + +.TP +.I reconnect +Try to reconnect to the server(s) if the connection is broken during +streaming, "yes" or "no". (optional parameter, defaults to "yes") +.TP +.I realtime +Use POSIX realtime scheduling, "yes" or "no". +(optional parameter, defaults to "yes") +.TP +.I rtprio +Scheduling priority for the realtime threads. +(optional parameter, defaults to 4) + + +.PP +.B [input] + +This section describes the input (required). + +Required values: + +.TP +.I device +Specify the device to record from, which can be an OSS DSP device, +an ALSA source, PulseAudio source or you can use Jack audio. +- OSS DSP audio device to record from (e.g. /dev/dsp) +- ALSA DSP device name (e.g. hwplug:0,0) +- for PulseAudio use "pulseaudio" +- the string 'jack', to have an unconnected Jack port, or + 'jack_auto' to automatically make Jack connect to the first source. +.TP +.I sampleRate +The sample rate to record with, samples per second +(e.g. 44100 for 44.1kHz CD-quality audio, 22050 for 22kHz or 11025 +for 11kHz) +.TP +.I bitsPerSample +Number of bits to use for each sample (e.g. 8 bits or 16 bits) +.TP +.I channel +Number of channels to record (e.g. 1 for mono, 2 for stereo) +.TP +.I jackClientName +The name of the jack input channel created by darkice if device=jack +is specified. +.TP +.I paSourceName +The name of the PulseAudio source to use. It can be "default", an index or a device string obtained from running "pactl list" + +.PP +.B [icecast-x] + +This section describes an output to an +.B IceCast 1.3.x +server or +.B Darwin Streaming Server +, while encoding +with a lame encoder. There may be at most 8 outputs, numbered from 0 ... 7. +The number is included in the section name (e.g. [icecast-0] ... [icecast-7]). +The stream will be reachable at +.I http://:/ + +Required values: + +.TP +.I bitrateMode +The bit rate mode of the encoding, either "cbr", "abr" or "vbr", +standing for constant bit rate, average bit rate and variable bit +respectively. Use the bitrate and/or quality values to specify details +of the appropriate bit rate mode. +.TP +.I bitrate +Bit rate to encode to in kBits / sec (e.g. 96). Only used when cbr or +abr bit rate modes are specified. +.TP +.I quality +The quality of encoding a value between 0.0 .. 1.0 (e.g. 0.8), with 1.0 being +the highest quality. Use a value greater than 0.0. Only used when cbr or vbr +bit rate modes are specified. +.TP +.I server +The +.B IceCast +server's name (e.g. yp.yourserver.com) +.TP +.I port +The port to connect to the IceCast server (e.g. 8000) +.TP +.I password +The password to use to connect to the +.B IceCast +server +.TP +.I mountPoint +Mount point for the stream on the server + +.PP +Optional values: + +.TP +.I sampleRate +The sample rate of the encoded mp3 output. If not specified, defaults +to the value of the input sample rate. +.TP +.I channel +Number of channels for the mp3 output (e.g. 1 for mono, 2 for stereo). +If not specified, defaults to the value of the input sample rate. +.TP +.I name +Name of the stream +.TP +.I description +Description of the stream +.TP +.I url +Url related to the stream +.TP +.I genre +Genre of the stream +.TP +.I public +"yes" or "no", whether the stream is public +.TP +.I remoteDumpFile +The file the +.B IceCast +server should dump the contents of +this stream on its side. +.TP +.I localDumpFile +Dump the same mp3 data sent to the +.B IceCast +server to this local file. +.TP +.I fileAddDate +"yes" or "no" if you want to automatically insert a date string in +the localDumpFile name before its extension or at the end of file name if +no extension present +.TP +.I fileDateFormat +The date format to use for appending the date to the dump file name. +Defaults to "[%m-%d-%Y-%H-%M-%S]". All format strings acceptable by strftime() +can be used, see the strftime man page for details. Only applicable is +fileAddDate is "true". +.TP +.I lowpass +Lowpass filter setting for the lame encoder, in Hz. Frequencies above +the specified value will be cut. +If not set or set to 0, the encoder's default behaviour is used. +If set to -1, the filter is disabled. +.TP +.I highpass +Highpass filter setting for the lame encoder, in Hz. Frequencies below +the specified value will be cut. +If not set or set to 0, the encoder's default behaviour is used. +If set to -1, the filter is disabled. + +.PP +.B [icecast2-x] + +This section describes an output to an +.B IceCast2 +server, while encoding with the ogg vobis encoder. +There may be at most 8 outputs, numbered from 0 ... 7. +The number is included in the section name (e.g. [icecast2-0] ... [icecast2-7]). +The stream will be reachable at +.I http://:/ +.P +.B DarkIce +supports both fixed bitrate and variable bitrate vorbis streams. When +using fixed bitrate, specify the bitrate using the +.I bitrate +field. When using variable bitrate, specify the quality of the stream by the +.I quality +field, which is a value between 0.0 and 1.0. + +Required values: + +.TP +.I format +Format of the stream sent to the +.B IceCast2 +server. Supported formats are 'vorbis', 'opus', 'mp3', 'mp2', 'aac' and 'aacp'. +.TP +.I bitrateMode +The bit rate mode of the encoding, either "cbr", "abr" or "vbr", +standing for constant bit rate, average bit rate and variable bit +respectively. Use the bitrate and/or quality values to specify details +of the appropriate bit rate mode. Ogg Opus only supports 'cbr' and 'abr'. +.TP +.I bitrate +Bit rate to encode to in kBits / sec (e.g. 96). Only used when cbr or +abr bit rate modes are specified. +.TP +.I quality +The quality of encoding a value between 0.0 .. 1.0 (e.g. 0.8), with 1.0 being +the highest quality. Use a value greater than 0.0. Only used when vbr +bit rate mode is specified for Ogg Vorbis format, or in vbr and abr +modes for mp3 and mp2 format. +.TP +.I server +The +.B IceCast2 +server's name (e.g. yp.yourserver.com) +.TP +.I port +The port to connect to the IceCast server (e.g. 8000) +.TP +.I password +The password to use to connect to the +.B IceCast2 +server +.TP +.I mountPoint +Mount point for the stream on the server + +.PP +Optional values: + +.TP +.I sampleRate +The sample rate of the encoded output. If not specified, defaults +to the value of the input sample rate. Please note that Ogg Opus +only supports 48kHz sample rate, and will resample to this rate. +.TP +.I channel +Number of channels for the output (e.g. 1 for mono, 2 for stereo). +If not specified, defaults to the value of the input sample rate. +Different channels for input and output are only supported for mp3, +but not for Ogg Vorbis. +.TP +.I maxBitrate +The maximum bitrate of the stream. Only used when in cbr mode and in +Ogg Vorbis format. +.TP +.I name +Name of the stream +.TP +.I description +Description of the stream +.TP +.I url +Url related to the stream +.TP +.I genre +Genre of the stream +.TP +.I public +"yes" or "no", whether the stream is public +.TP +.I localDumpFile +Dump the same Ogg Vorbis data sent to the +.B IceCast2 +server to this local file. +.TP +.I fileAddDate +"yes" or "no" if you want to automatically insert a date string in +the localDumpFile name before its extension or at the end of file name if +no extension present +.TP +.I fileDateFormat +The date format to use for appending the date to the dump file name. +Defaults to "[%m-%d-%Y-%H-%M-%S]". All format strings acceptable by strftime() +can be used, see the strftime man page for details. Only applicable is +fileAddDate is "true". +.TP +.I lowpass +Lowpass filter setting for the lame encoder, in Hz. Frequencies above +the specified value will be cut. +If not set or set to 0, the encoder's default behaviour is used. +If set to -1, the filter is disabled. +Only has effect if the mp3 or mp2 format is used. +.TP +.I highpass +Highpass filter setting for the lame encoder, in Hz. Frequencies below +the specified value will be cut. +If not set or set to 0, the encoder's default behaviour is used. +If set to -1, the filter is disabled. +Only has effect if the mp3 or mp2 format is used. + +.PP +.B [shoutcast-x] + +This section describes an output to a +.B ShoutCast +server, while encoding +with a lame encoder. There may be at most 8 outputs, numbered from 0 ... 7. +The number is included in the section name +(e.g. [shoutcast-0] ... [shoutcast-7]). +The stream will be reachable at +.I http://:/ + +Required values: + +.TP +.I bitrateMode +The bit rate mode of the encoding, either "cbr", "abr" or "vbr", +standing for constant bit rate, average bit rate and variable bit +respectively. Use the bitrate and/or quality values to specify details +of the appropriate bit rate mode. +.TP +.I bitrate +Bit rate to encode to in kBits / sec (e.g. 96). Only used when cbr or +abr bit rate modes are specified. +.TP +.I quality +The quality of encoding a value between 0.0 .. 1.0 (e.g. 0.8), with 1.0 being +the highest quality. Use a value greater than 0.0. Only used when cbr or vbr +bit rate modes are specified. +.TP +.I server +The +.B ShoutCast +server's name (e.g. yp.yourserver.com) +.TP +.I port +The source port to connect to the ShoutCast server (e.g. 8001) +.TP +.I password +The password to use to connect to the +.B ShoutCast +server + +.PP +Optional values: + +.TP +.I mountPoint +Mount point for the stream on the server. Only works on Darwin Streaming +Server, the original Shoutcast server does not support mount points +.TP +.I sampleRate +The sample rate of the encoded mp3 output. If not specified, defaults +to the value of the input sample rate. +.TP +.I channel +Number of channels for the mp3 output (e.g. 1 for mono, 2 for stereo). +If not specified, defaults to the value of the input sample rate. +.TP +.I name +Name of the stream +.TP +.I url +Url related to the stream +.TP +.I genre +Genre of the stream +.TP +.I public +"yes" or "no", whether the stream is public +.TP +.I irc +IRC information related to the stream +.TP +.I aim +AIM information related to the stream +.TP +.I icq +ICQ information related to the stream +.TP +.I lowpass +Lowpass filter setting for the lame encoder, in Hz. Frequencies above +the specified value will be cut. +If not set or set to 0, the encoder's default behaviour is used. +If set to -1, the filter is disabled. +.TP +.I highpass +Highpass filter setting for the lame encoder, in Hz. Frequencies below +the specified value will be cut. +If not set or set to 0, the encoder's default behaviour is used. +If set to -1, the filter is disabled. +.TP +.I localDumpFile +Dump the same mp3 data sent to the +.B ShoutCast +server to this local file. +.TP +.I fileAddDate +"yes" or "no" if you want to automatically insert a date string in +the localDumpFile name before its extension or at the end of file name if +no extension present +.TP +.I fileDateFormat +The date format to use for appending the date to the dump file name. +Defaults to "[%m-%d-%Y-%H-%M-%S]". All format strings acceptable by strftime() +can be used, see the strftime man page for details. Only applicable is +fileAddDate is "true". +.PP +.B [file-x] + +This section describes an output to a local file in either Ogg Vorbis or +mp3 format. +There may be at most 8 outputs, numbered from 0 ... 7. +The number is included in the section name (e.g. [file-0] ... [file-7]). + +Required values: + +.TP +.I format +Format to encode in. Must be either 'mp3', 'mp2', 'vorbis', 'opus', 'aac' +or 'aacp'. +.TP +.I bitrateMode +The bit rate mode of the encoding, either "cbr", "abr" or "vbr", +standing for constant bit rate, average bit rate and variable bit +respectively. Use the bitrate and/or quality values to specify details +of the appropriate bit rate mode. +.TP +.I bitrate +Bit rate to encode to in kBits / sec (e.g. 96). Only used when cbr or +abr bit rate modes are specified. +.TP +.I quality +The quality of encoding a value between 0.0 .. 1.0 (e.g. 0.8), with 1.0 being +the highest quality. Use a value greater than 0.0. Only used when cbr or vbr +bit rate modes are specified. +.TP +.I fileName +The name of the local file to save the encoded data into. + +.PP +Optional values: + +.TP +.I sampleRate +The sample rate of the encoded mp3 output. If not specified, defaults +to the value of the input sample rate. +Only used if the output format is mp3. +.TP +.I lowpass +Lowpass filter setting for the lame encoder, in Hz. Frequencies above +the specified value will be cut. +If not set or set to 0, the encoder's default behaviour is used. +If set to -1, the filter is disabled. +Only used if the output format is mp3. +.TP +.I highpass +Highpass filter setting for the lame encoder, in Hz. Frequencies below +the specified value will be cut. +If not set or set to 0, the encoder's default behaviour is used. +If set to -1, the filter is disabled. +Only used if the output format is mp3. + +.PP +A sample configuration file follows. This file makes +.B DarkIce +stream for 1 minute (60 seconds) from the audio device +.I /dev/dsp +at 22.05kHz, 16 bit stereo. +It will build up a connection to the +.B IceCast +server yp.yourserver.com on port 8000 with the password "hackme". +The stream will be encoded to 96 kb/s mp3 with quality 0.8, and will be +reachable at +.I http://yp.yourserver.com:8000/live96 +to mp3 players. +The encoding session will be stored by +.B IceCast +in the file +.I /tmp/server-dump.mp3 +on the server side, and also by +.B DarkIce +in the file +.I /tmp/encoder-dump.mp3 +on the encoder side. + +.nf +[general] +duration = 60 +bufferSecs = 5 + +[input] +device = /dev/dsp +sampleRate = 22050 +bitsPerSample = 16 +channel = 2 + +[icecast-0] +bitrateMode = cbr +bitrate = 96 +quality = 0.8 +server = yp.yourserver.com +port = 8000 +password = hackme +mountPoint = live96 +name = DarkIce trial +description = This is only a trial +url = http://www.yourserver.com +genre = live +public = no +remoteDumpFile = /tmp/server-dump.mp3 +localDumpFile = /tmp/encoder-dump.mp3 +fileAddDate = no +.fi + + +.PP +The following sample configuration file simply encodes the 16 bit stereo +44.1 kHz sound card input into Ogg Vorbis at average bit rate 96 kb/s for 60 +seconds, and saves it in the local file at /tmp/save.ogg. + +.nf +[general] +duration = 60 +bufferSecs = 5 + +[input] +device = /dev/dsp +sampleRate = 44100 +bitsPerSample = 16 +channel = 2 + +[file-0] +format = vorbis +bitrateMode = abr +bitrate = 96 +fileName = /tmp/save.ogg +.fi + + +.PP +A bit more complicated sample follows. This one makes +.B DarkIce +stream for 1 hour (3600 seconds) from the audio device +.I /dev/dsp +at 44.1kHz, 16 bit stereo. + +It will build up a connection to an +.B IceCast +server yp.your-ice-server.com on port 8000 with the password "ice-hackme". +The sound for this stream will be cut at 10500 Hz from above. +The stream will be encoded to average bit rate 96 kb/s mp3 and resampled to +22.05kHz and 1 channel (mono). +The stream will be reachable at +.I http://yp.your-ice-server.com:8000/live96 +to mp3 players. +The encoding session will be stored by +.B IceCast +in the file +.I /tmp/live96.mp3 +on the server side. + +It will also connect to a +.I ShoutCast +server at yp.your-shout-server.com on port 8001 with the password "shout-hackme" +This stream will be encoded to constant bit rate 128 kb/s mp3 with quality +0.8, and will be reachable at +.I http://yp.your-shout-server.com:8000 +to mp3 players. + +.nf +[general] +duration = 3600 +bufferSecs = 5 + +[input] +device = /dev/dsp +sampleRate = 22050 +bitsPerSample = 16 +channel = 2 + +[icecast-0] +sampleRate = 22050 +channel = 1 +bitrateMode = abr +bitrate = 96 +lowpass = 10500 +server = yp.your-ice-server.com +port = 8000 +password = ice-hackme +mountPoint = live96 +name = DarkIce trial +description = This is only a trial +url = http://www.yourserver.com +genre = live +public = yes +remoteDumpFile = /tmp/live96.mp3 + +[shoutcast-0] +bitrateMode = cbr +bitrate = 128 +quality = 0.8 +server = yp.your-shout-server.com +port = 8001 +password = shout-hackme +name = DarkIce trial +url = http://www.yourserver.com +genre = live +public = yes +irc = irc.yourserver.com +aim = aim here +icq = I see you too +.fi + + +.SH BUGS +.PP +Lots of bugs. + + +.SH "SEE ALSO" +darkice(1) + + +.SH AUTHOR +Akos Maroy +.I + + +.SH LINKS +Project homepage: +.I http://code.google.com/p/darkice/ + +.B IceCast +homepage: +.I http://www.icecast.org/ + +.B ShoutCast +homepage: +.I http://www.shoutcast.com/ + +.B Lame +homepage: +.I http://www.mp3dev.org/mp3/ + +.B Ogg Vorbis +homepage: +.I http://www.xiph.org/ogg/vorbis/ + +.B Ogg Opus +homepage: +.I http://www.opus-codec.org/ diff --git a/darkice/tags/darkice-1_3/rc.darkice b/darkice/tags/darkice-1_3/rc.darkice new file mode 100644 index 0000000..0c5047c --- /dev/null +++ b/darkice/tags/darkice-1_3/rc.darkice @@ -0,0 +1,131 @@ +#!/bin/sh +# generic init file for darkice +# +# Niels Dettenbach - nd@syndicat.com - 2009-11-05 +# Last Change: 2010-12-21 +# +# thanks to: +# - Roland Whitehead +# GPL (2009) +# 0.7 + +## settings ## +# check your paths! + +program=/usr/bin/darkice +pidfile=/var/run/darkice.pid +configfile=/etc/darkice.cfg +logfile=/var/log/darkice.log +progname="darkice" +restart_delay=2 +verbose="5" + +## end of settings ## + +RETVAL=0 +if [ ! -f $configfile ] +then + echo "$progname: config file not found" + exit +fi + +if [ ! -f $program ] +then + echo "$progname: programm file $program not found" + exit +fi + +case $1 in +'start') + if [ -f $pidfile ]; then + PID=`cat $pidfile` + running=`ps --no-headers -o "%c" -p $PID` + if ( [ "$progname" == "$running" ] ); then + echo "$progname is still running" + else + echo "$progname seems crashed - PID ($PID) does not match the deamon" + echo "removing stale PID File $pidfile" + rm -f $pidfile + $0 start + exit $? + fi + exit 0 + else + echo -n $"Starting $progname " + RETVAL=1 + $program -v $verbose -c $configfile 2>%1 >> $logfile & + echo + RETVAL=$? + if [ $RETVAL -eq 0 ]; then + echo $! > $pidfile + echo " started" + else + echo " not started" + echo $RETVAL + exit 0 + fi + RETVAL=$? + fi +;; +'stop') + if [ -f $pidfile ]; then + echo -n $"Stop $progname " + PID=`cat $pidfile` + kill -s TERM $PID 2> /dev/null + echo + sleep $restart_delay + rm -f $pidfile + echo " stopped" + else + echo "$progname not running" + fi + RETVAL=$? +;; +'status') + if [ -f $pidfile ]; then + PID=`cat $pidfile` + running=`ps --no-headers -o "%c" -p $PID` + if ( [ "$progname" == "$running" ] ); then + echo "$progname IS running with PID `cat $pidfile`." + else + echo "$progname process is dead or stale PID File $pidfile" + exit 0 + fi + else + echo "$progname is not running" + exit 0 + fi +;; +'restart') + $0 stop + $0 start + RETVAL=$? +;; + +'restartifdown') + if [ -f $pidfile ]; then + PID=`cat $pidfile` + running=`ps --no-headers -o "%c" -p $PID` + if ( [ "$progname" == "$running" ] ); then + echo "$progname IS running with PID `cat $pidfile` - no restart." + else + echo "$progname PID $PID seems dead - restart" + $0 stop + $0 start + RETVAL=$? + fi + else + echo "PID file $pidfile found - restart" + $0 stop + $0 start + RETVAL=$? + fi +;; + +*) + echo "Usage: $0 {start|stop|restart|status|restartifdown} " + exit 1; +;; +esac + +exit $RETVAL diff --git a/darkice/tags/darkice-1_3/src/AlsaDspSource.cpp b/darkice/tags/darkice-1_3/src/AlsaDspSource.cpp new file mode 100644 index 0000000..7ef6a0c --- /dev/null +++ b/darkice/tags/darkice-1_3/src/AlsaDspSource.cpp @@ -0,0 +1,290 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Copyright (c) 2004 + LS Informationstechnik (LIKE) + University of Erlangen Nuremberg + All rights reserved. + + Tyrell DarkIce + + File : AlsaDspSource.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#include "AudioSource.h" + +// compile only if configured for ALSA +#ifdef SUPPORT_ALSA_DSP + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "Util.h" +#include "Exception.h" +#include "AlsaDspSource.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Tell if source id big endian + *----------------------------------------------------------------------------*/ +bool +AlsaDspSource :: isBigEndian ( void ) const throw () +{ + return SND_PCM_FORMAT_S16 == SND_PCM_FORMAT_S16_BE; +} + + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +AlsaDspSource :: init ( const char * name ) throw ( Exception ) +{ + pcmName = Util::strDup( name); + captureHandle = 0; + bufferTime = 1000000; // Do 1s buffering + running = false; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +AlsaDspSource :: strip ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + delete[] pcmName; +} + + +/*------------------------------------------------------------------------------ + * Open the audio source + *----------------------------------------------------------------------------*/ +bool +AlsaDspSource :: open ( void ) throw ( Exception ) +{ + unsigned int u; + snd_pcm_format_t format; + snd_pcm_hw_params_t *hwParams; + + if ( isOpen() ) { + return false; + } + + switch ( getBitsPerSample() ) { + case 8: + format = SND_PCM_FORMAT_S8; + break; + + case 16: + format = SND_PCM_FORMAT_S16; + break; + + default: + return false; + } + + if (snd_pcm_open(&captureHandle, pcmName, SND_PCM_STREAM_CAPTURE, 0) < 0) { + captureHandle = 0; + return false; + } + + if (snd_pcm_hw_params_malloc(&hwParams) < 0) { + close(); + throw Exception( __FILE__, __LINE__, "can't alloc hardware "\ + "parameter structure"); + } + + if (snd_pcm_hw_params_any(captureHandle, hwParams) < 0) { + snd_pcm_hw_params_free(hwParams); + close(); + throw Exception( __FILE__, __LINE__, "can't initialize hardware "\ + "parameter structure"); + } + + if (snd_pcm_hw_params_set_access(captureHandle, hwParams, + SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { + snd_pcm_hw_params_free(hwParams); + close(); + throw Exception( __FILE__, __LINE__, "can't set access type"); + } + + if (snd_pcm_hw_params_set_format(captureHandle, hwParams, format) < 0) { + snd_pcm_hw_params_free(hwParams); + close(); + throw Exception( __FILE__, __LINE__, "can't set sample format"); + } + + u = getSampleRate(); + if (snd_pcm_hw_params_set_rate_near(captureHandle, hwParams, &u, 0) < 0) { + snd_pcm_hw_params_free(hwParams); + close(); + throw Exception( __FILE__, __LINE__, "can't set sample rate", u); + } + + u = getChannel(); + if (snd_pcm_hw_params_set_channels(captureHandle, hwParams, u) < 0) { + snd_pcm_hw_params_free(hwParams); + close(); + throw Exception( __FILE__, __LINE__, "can't set channels", u); + } + + u = 4; + if (snd_pcm_hw_params_set_periods_near(captureHandle, hwParams, &u, 0) + < 0) { + snd_pcm_hw_params_free(hwParams); + close(); + throw Exception( __FILE__, __LINE__, "can't set interrupt frequency"); + } + + u = getBufferTime(); + if (snd_pcm_hw_params_set_buffer_time_near(captureHandle, hwParams, &u, 0) + < 0) { + snd_pcm_hw_params_free(hwParams); + close(); + throw Exception( __FILE__, __LINE__, "can't set buffer size"); + } + + if (snd_pcm_hw_params(captureHandle, hwParams) < 0) { + snd_pcm_hw_params_free(hwParams); + close(); + throw Exception( __FILE__, __LINE__, "can't set hardware parameters"); + } + + snd_pcm_hw_params_free(hwParams); + + if (snd_pcm_prepare(captureHandle) < 0) { + close(); + throw Exception( __FILE__, __LINE__, "can't prepare audio interface "\ + "for use"); + } + + bytesPerFrame = getChannel() * getBitsPerSample() / 8; + + return true; +} + + +/*------------------------------------------------------------------------------ + * Check whether read() would return anything + *----------------------------------------------------------------------------*/ +bool +AlsaDspSource :: canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ) +{ + if ( !isOpen() ) { + return false; + } + + if ( !running ) { + snd_pcm_start(captureHandle); + running = true; + } + + /* + * FIXME How to check for available frames? It + * seems like snd_pcm_wait stops working when + * it comes to ALSA plugins... :-( + * + * int milliDelay = sec * 1000 + usec/1000; + * return snd_pcm_wait(captureHandle, milliDelay)!=0; + */ + return true; // bad!! +} + + +/*------------------------------------------------------------------------------ + * Read from the audio source + *----------------------------------------------------------------------------*/ +unsigned int +AlsaDspSource :: read ( void * buf, + unsigned int len ) throw ( Exception ) +{ + snd_pcm_sframes_t ret; + + if ( !isOpen() ) { + return 0; + } + + do { + ret = snd_pcm_readi(captureHandle, buf, len/bytesPerFrame); + + // Check for buffer overrun + if (ret == -EPIPE) { + reportEvent(1, "AlsaDspSource :: Buffer overrun!"); + snd_pcm_prepare(captureHandle); + ret = -EAGAIN; + } + } while (ret == -EAGAIN); + + if ( ret < 0 ) { + throw Exception(__FILE__, __LINE__, snd_strerror(ret)); + } + + running = true; + return ret * bytesPerFrame; +} + + +/*------------------------------------------------------------------------------ + * Close the audio source + *----------------------------------------------------------------------------*/ +void +AlsaDspSource :: close ( void ) throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + snd_pcm_close(captureHandle); + + captureHandle = 0; + running = false; +} + +#endif // HAVE_ALSA_LIB + diff --git a/darkice/tags/darkice-1_3/src/AlsaDspSource.h b/darkice/tags/darkice-1_3/src/AlsaDspSource.h new file mode 100644 index 0000000..3d0965c --- /dev/null +++ b/darkice/tags/darkice-1_3/src/AlsaDspSource.h @@ -0,0 +1,299 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Copyright (c) 2004 + LS Informationstechnik (LIKE) + University of Erlangen Nuremberg + All rights reserved. + + Tyrell DarkIce + + File : AlsaDspSource.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef ALSA_SOURCE_H +#define ALSA_SOURCE_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "Reporter.h" +#include "AudioSource.h" + +#ifdef HAVE_ALSA_LIB +#include +#else +#error configure for ALSA +#endif + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * An audio input based on the ALSA sound system + * + * @author $Author$ + * @version $Revision$ + */ +class AlsaDspSource : public AudioSource, public virtual Reporter +{ + private: + + /** + * Name of the capture PCM stream. + */ + char *pcmName; + + /** + * Handle to access PCM stream data. + */ + snd_pcm_t *captureHandle; + + /** + * Stores number of bytes per frame. One frame + * contains all samples per time instance. + */ + int bytesPerFrame; + + /** + * Is the stream running? + */ + bool running; + + /** + * Number of useconds to do buffering in the audio device. + */ + unsigned int bufferTime; + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + AlsaDspSource ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Initialize the object + * + * @param name the PCM to open. + * @exception Exception + */ + void + init ( const char * name ) throw ( Exception ); + + /** + * De-iitialize the object + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + public: + + /** + * Constructor. + * + * @param name the PCM (e.g. "hwplug:0,0"). + * @param sampleRate samples per second (e.g. 44100 for 44.1kHz). + * @param bitsPerSample bits per sample (e.g. 16 bits). + * @param channel number of channels of the audio source + * (e.g. 1 for mono, 2 for stereo, etc.). + * @exception Exception + */ + inline + AlsaDspSource ( const char * name, + int sampleRate = 44100, + int bitsPerSample = 16, + int channel = 2 ) + throw ( Exception ) + : AudioSource( sampleRate, bitsPerSample, channel) + { + init( name); + } + + /** + * Copy Constructor. + * + * @param ds the object to copy. + * @exception Exception + */ + inline + AlsaDspSource ( const AlsaDspSource & ds ) throw ( Exception ) + : AudioSource( ds ) + { + init( ds.pcmName); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~AlsaDspSource ( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param ds the object to assign to this one. + * @return a reference to this object. + * @exception Exception + */ + inline virtual AlsaDspSource & + operator= ( const AlsaDspSource & ds ) throw ( Exception ) + { + if ( this != &ds ) { + strip(); + AudioSource::operator=( ds); + init( ds.pcmName); + } + return *this; + } + + /** + * Tell if the data from this source comes in big or little endian. + * + * @return true if the source is big endian, false otherwise + */ + virtual bool + isBigEndian ( void ) const throw (); + + /** + * Open the AlsaDspSource. + * This does not put Alsa device into recording mode. + * To start getting samples, call either canRead() or read(). + * + * @return true if opening was successful, false otherwise + * @exception Exception + * + * @see #canRead + * @see #read + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the AlsaDspSource is open. + * + * @return true if the AlsaDspSource is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return captureHandle != 0; + } + + /** + * Check if the AlsaDspSource can be read from. + * Blocks until the specified time for data to be available. + * Puts the PCM into recording mode. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the AlsaDspSource is ready to be read from, + * false otherwise. + * @exception Exception + */ + virtual bool + canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ); + + /** + * Read from the AlsaDspSource. + * Puts the PCM into recording mode. + * + * @param buf the buffer to read into. + * @param len the number of bytes to read into buf + * @return the number of bytes read (may be less than len). + * @exception Exception + */ + virtual unsigned int + read ( void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Close the AlsaDspSource. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); + + /** + * Returns the buffer size in useconds. + * + * @return the number of useconds audio will be buffered in ALSA + */ + inline virtual unsigned int + getBufferTime( void ) const + { + return bufferTime; + } + + /** + * Sets the number of useconds to buffer audio in ALSA + * + * @param time buffer time + */ + inline virtual void + setBufferTime( unsigned int time ) { + bufferTime = time; + } +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* ALSA_SOURCE_H */ + diff --git a/darkice/tags/darkice-1_3/src/AudioEncoder.h b/darkice/tags/darkice-1_3/src/AudioEncoder.h new file mode 100644 index 0000000..bff2d63 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/AudioEncoder.h @@ -0,0 +1,493 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : AudioEncoder.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef AUDIO_ENCODER_H +#define AUDIO_ENCODER_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Referable.h" +#include "Sink.h" +#include "AudioSource.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * An audio encoder + * + * @author $Author$ + * @version $Revision$ + */ +class AudioEncoder : public Sink, public virtual Referable +{ + public: + /** + * Type to specify bitrate mode. Possible values: + * - cbr - constant bitrate mode + * described by bitrate + * - abr - average bitrate mode + * described by an average bitrate and quality + * - vbr - variable bitrate mode + * described by quality + */ + enum BitrateMode { cbr, abr, vbr }; + + private: + + /** + * The Sink to dump the encoded data to + */ + Ref sink; + + /** + * Sample rate of the input. + */ + unsigned int inSampleRate; + + /** + * Number of bits per sample of the input. + */ + unsigned int inBitsPerSample; + + /** + * Number of channels of the input. + */ + unsigned int inChannel; + + /** + * Is the input big endian or little endian? + */ + bool inBigEndian; + + /** + * The bitrate mode of the encoder + */ + BitrateMode outBitrateMode; + + /** + * Bit rate of the output in kbits/sec, for fixed bitrate encodings. + */ + unsigned int outBitrate; + + /** + * Quality of the output, for variable bitrate encodings. + */ + double outQuality; + + /** + * Sample rate of the output. + */ + unsigned int outSampleRate; + + /** + * Number of channels of the output. + */ + unsigned int outChannel; + + /** + * Initialize the object. + * + * @param sink the sink to send encoded output to + * @param inSampleRate sample rate of the input. + * @param inBitsPerSample number of bits per sample of the input. + * @param inChannel number of channels of the input. + * @param inBigEndian shows if the input is big or little endian. + * @param outBitrateMode the bit rate mode of the output. + * @param outBitrate bit rate of the output. + * @param outSampleRate sample rate of the output. + * @param outChannel number of channels of the output. + * @exception Exception + */ + inline void + init ( Sink * sink, + unsigned int inSampleRate, + unsigned int inBitsPerSample, + unsigned int inChannel, + bool inBigEndian, + BitrateMode outBitrateMode, + unsigned int outBitrate, + double outQuality, + unsigned int outSampleRate, + unsigned int outChannel ) throw ( Exception ) + { + this->sink = sink; + this->inSampleRate = inSampleRate; + this->inBitsPerSample = inBitsPerSample; + this->inChannel = inChannel; + this->inBigEndian = inBigEndian; + this->outBitrateMode = outBitrateMode; + this->outBitrate = outBitrate; + this->outQuality = outQuality; + this->outSampleRate = outSampleRate; + this->outChannel = outChannel; + + if ( outQuality < -0.1 || 1.0 < outQuality ) { + throw Exception( __FILE__, __LINE__, "invalid encoder quality"); + } + } + + /** + * De-iitialize the object. + * + * @exception Exception + */ + inline void + strip ( void ) throw ( Exception ) + { + } + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + AudioEncoder ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Constructor. + * + * @param sink the sink to send encoded output to + * @param inSampleRate sample rate of the input. + * @param inBitsPerSample number of bits per sample of the input. + * @param inChannel number of channels of the input. + * @param inBigEndian shows if the input is big or little endian + * @param outBitrateMode the bit rate mode of the output. + * @param outBitrate bit rate of the output (kbits/sec). + * @param outQuality the quality of the stream. + * @param outSampleRate sample rate of the output. + * If 0, inSampleRate is used. + * @param outChannel number of channels of the output. + * If 0, inChannel is used. + * @exception Exception + */ + inline + AudioEncoder ( Sink * sink, + unsigned int inSampleRate, + unsigned int inBitsPerSample, + unsigned int inChannel, + bool inBigEndian, + BitrateMode outBitrateMode, + unsigned int outBitrate, + double outQuality, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0 ) + throw ( Exception ) + { + init ( sink, + inSampleRate, + inBitsPerSample, + inChannel, + inBigEndian, + outBitrateMode, + outBitrate, + outQuality, + outSampleRate ? outSampleRate : inSampleRate, + outChannel ? outChannel : inChannel ); + } + + /** + * Constructor. + * + * @param sink the sink to send encoded output to + * @param as get input sample rate, bits per sample and channels + * from this AudioSource. + * @param outBitrateMode the bit rate mode of the output. + * @param outBitrate bit rate of the output (kbits/sec). + * @param outQuality the quality of the stream. + * @param outSampleRate sample rate of the output. + * If 0, input sample rate is used. + * @param outChannel number of channels of the output. + * If 0, input channel is used. + * @exception Exception + */ + inline + AudioEncoder ( Sink * sink, + const AudioSource * as, + BitrateMode outBitrateMode, + unsigned int outBitrate, + double outQuality, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0 ) + throw ( Exception) + { + init( sink, + as->getSampleRate(), + as->getBitsPerSample(), + as->getChannel(), + as->isBigEndian(), + outBitrateMode, + outBitrate, + outQuality, + outSampleRate ? outSampleRate : as->getSampleRate(), + outChannel ? outChannel : as->getChannel() ); + } + + /** + * Copy constructor. + * + * @param encoder the AudioEncoder to copy. + */ + inline + AudioEncoder ( const AudioEncoder & encoder ) throw ( Exception ) + { + init ( encoder.sink.get(), + encoder.inSampleRate, + encoder.inBitsPerSample, + encoder.inChannel, + encoder.inBigEndian, + encoder.outBitrateMode, + encoder.outBitrate, + encoder.outQuality, + encoder.outSampleRate, + encoder.outChannel ); + } + + /** + * Assignment operator. + * + * @param encoder the AudioEncoder to assign this to. + * @return a reference to this AudioEncoder. + * @exception Exception + */ + inline virtual AudioEncoder & + operator= ( const AudioEncoder & encoder ) throw ( Exception ) + { + if ( this != &encoder ) { + strip(); + + init ( encoder.sink.get(), + encoder.inSampleRate, + encoder.inBitsPerSample, + encoder.inChannel, + encoder.inBigEndian, + encoder.outBitrateMode, + encoder.outBitrate, + encoder.outQuality, + encoder.outSampleRate, + encoder.outChannel ); + } + + return *this; + } + + + public: + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~AudioEncoder ( void ) throw ( Exception ) + { + strip(); + } + + /** + * Get the underlying sink, that the encoded content is sent to. + * + * @return the underlying sink + */ + inline virtual Ref + getSink(void) throw () + { + return sink; + } + + /** + * Get the number of channels of the input. + * + * @return the number of channels of the input. + */ + inline int + getInChannel ( void ) const throw () + { + return inChannel; + } + + /** + * Tell if the input is big or little endian. + * + * @return true if the input is big endian, false if little endian. + */ + inline bool + isInBigEndian ( void ) const throw () + { + return inBigEndian; + } + + /** + * Get the sample rate of the input. + * + * @return the sample rate of the input. + */ + inline int + getInSampleRate ( void ) const throw () + { + return inSampleRate; + } + + /** + * Get the number of bits per sample of the input. + * + * @return the number of bits per sample of the input. + */ + inline int + getInBitsPerSample ( void ) const throw () + { + return inBitsPerSample; + } + + /** + * Get the number of channels of the output. + * + * @return the number of channels of the output. + */ + inline int + getOutChannel ( void ) const throw () + { + return outChannel; + } + + /** + * Get the sample rate of the output. + * + * @return the sample rate of the output. + */ + inline int + getOutSampleRate ( void ) const throw () + { + return outSampleRate; + } + + /** + * Get the bit rate mode of the output. + * + * @return the bit rate mode of the output. + */ + inline BitrateMode + getOutBitrateMode ( void ) const throw () + { + return outBitrateMode; + } + + /** + * Get the bit rate of the output in kbits/sec, for fixed bitrate + * encodings. + * + * @return the bit rate of the output. + */ + inline unsigned int + getOutBitrate ( void ) const throw () + { + return outBitrate; + } + + /** + * Get the encoding quality of the output, for variable bitrate + * encodings. + * + * @return the encoding quality of the output. + */ + inline double + getOutQuality ( void ) const throw () + { + return outQuality; + } + + /** + * Check whether encoding is in progress. + * + * @return true if encoding is in progress, false otherwise. + */ + virtual bool + isRunning ( void ) const throw () = 0; + + /** + * Start encoding. This function returns as soon as possible, + * with encoding started in the background. + * + * @return true if encoding has started, false otherwise. + * @exception Exception + */ + virtual bool + start ( void ) throw ( Exception ) = 0; + + /** + * Stop encoding. Stops the encoding running in the background. + * + * @exception Exception + */ + virtual void + stop ( void ) throw ( Exception ) = 0; + + /** + * Cut what the sink has been doing so far, and start anew. + * This usually means separating the data sent to the sink up + * until now, and start saving a new chunk of data. + * + * Typically this action is delegated to the underlying sink. + */ + inline virtual void + cut ( void ) throw () + { + sink->cut(); + } + +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* AUDIO_ENCODER_H */ + diff --git a/darkice/tags/darkice-1_3/src/AudioSource.cpp b/darkice/tags/darkice-1_3/src/AudioSource.cpp new file mode 100644 index 0000000..2387396 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/AudioSource.cpp @@ -0,0 +1,141 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : AudioSource.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "AudioSource.h" +#include "Util.h" +#include "Exception.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Return an audio source based on the compiled DSP supports and the + * supplied device name parameter. + *----------------------------------------------------------------------------*/ +AudioSource * +AudioSource :: createDspSource( const char * deviceName, + const char * jackClientName, + const char * paSourceName, + int sampleRate, + int bitsPerSample, + int channel) + throw ( Exception ) +{ + + if ( Util::strEq( deviceName, "/dev/tty", 8) ) { +#if defined( SUPPORT_SERIAL_ULAW ) + Reporter::reportEvent( 1, "Using Serial Ulaw input device:", + deviceName); + return new SerialUlaw( deviceName, + sampleRate, + bitsPerSample, + channel); +#else + throw Exception( __FILE__, __LINE__, + "trying to open Serial ULaw device " + "without support compiled", deviceName); +#endif + } else if ( Util::strEq( deviceName, "/dev", 4) ) { +#if defined( SUPPORT_OSS_DSP ) + Reporter::reportEvent( 1, "Using OSS DSP input device:", deviceName); + return new OssDspSource( deviceName, + sampleRate, + bitsPerSample, + channel); +#elif defined( SUPPORT_SOLARIS_DSP ) + Reporter::reportEvent( 1, "Using Solaris DSP input device:",deviceName); + return new SolarisDspSource( deviceName, + sampleRate, + bitsPerSample, + channel); +#else + throw Exception( __FILE__, __LINE__, + "trying to open OSS or Solaris DSP device " + "without support compiled", deviceName); +#endif + } else if ( Util::strEq( deviceName, "jack", 4) ) { +#if defined( SUPPORT_JACK_DSP ) + Reporter::reportEvent( 1, "Using JACK audio server as input device."); + return new JackDspSource( deviceName, + jackClientName, + sampleRate, + bitsPerSample, + channel); +#else + throw Exception( __FILE__, __LINE__, + "trying to open JACK device without " + "support compiled", deviceName); +#endif + } else if ( Util::strEq( deviceName, "pulseaudio", 10) ) { +#if defined( SUPPORT_PULSEAUDIO_DSP ) + Reporter::reportEvent( 1, "Using PulseAudio audio server as input device."); + return new PulseAudioDspSource( paSourceName, + sampleRate, + bitsPerSample, + channel); +#else + throw Exception( __FILE__, __LINE__, + "trying to open PulseAudio device without " + "support compiled", deviceName); +#endif + } else { +#if defined( SUPPORT_ALSA_DSP ) + Reporter::reportEvent( 1, "Using ALSA DSP input device:", deviceName); + return new AlsaDspSource( deviceName, + sampleRate, + bitsPerSample, + channel); +#else + throw Exception( __FILE__, __LINE__, + "trying to open ALSA DSP device without " + "support compiled", deviceName); +#endif + } +} + diff --git a/darkice/tags/darkice-1_3/src/AudioSource.h b/darkice/tags/darkice-1_3/src/AudioSource.h new file mode 100644 index 0000000..0230d42 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/AudioSource.h @@ -0,0 +1,338 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : AudioSource.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef AUDIO_SOURCE_H +#define AUDIO_SOURCE_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* ============================================================ include files */ + +#include "Source.h" +#include "Reporter.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + +/*------------------------------------------------------------------------------ + * Determine the kind of audio device based on the system + *----------------------------------------------------------------------------*/ +#if defined( HAVE_ALSA_LIB ) +// we have an ALSA sound system available +#define SUPPORT_ALSA_DSP 1 +#endif + +#if defined( HAVE_PULSEAUDIO_LIB ) +// we have an PULSEAUDIO sound system available +#define SUPPORT_PULSEAUDIO_DSP 1 +#endif + +#if defined( HAVE_SYS_SOUNDCARD_H ) +// we have an OSS DSP sound source device available +#define SUPPORT_OSS_DSP 1 +#endif + +#if defined( HAVE_SYS_AUDIO_H ) || defined( HAVE_SYS_AUDIOIO_H ) +// we have a Solaris DSP sound device available (same for OpenBSD) +#define SUPPORT_SOLARIS_DSP 1 +#endif + +#if defined( HAVE_JACK_LIB ) +// we have JACK audio server +#define SUPPORT_JACK_DSP 1 +#endif + +#if defined ( HAVE_TERMIOS_H ) +#define SUPPORT_SERIAL_ULAW 1 +#endif + +#if !defined( SUPPORT_ALSA_DSP ) \ + && !defined( SUPPORT_PULSEAUDIO_DSP ) \ + && !defined( SUPPORT_OSS_DSP ) \ + && !defined( SUPPORT_JACK_DSP ) \ + && !defined( SUPPORT_SOLARIS_DSP ) \ + && !defined( SUPPORT_SERIAL_ULAW) +// there was no DSP audio system found +#error No DSP audio input device found on system +#endif + + +/* =============================================================== data types */ + +/** + * Audio data input + * + * @author $Author$ + * @version $Revision$ + */ +class AudioSource : public Source, public virtual Reporter +{ + private: + + /** + * Number of channels of the audio source + * (e.g. 1 for mono, 2 for stereo, etc.) + */ + unsigned int channel; + + /** + * Samples per second (e.g. 44100 for 44.1kHz CD quality) + */ + unsigned int sampleRate; + + /** + * Bits per sample (e.g. 8 bits, 16 bits, etc.) + */ + unsigned int bitsPerSample; + + /** + * Initialize the object. + * + * @param sampleRate samples per second. + * @param bitsPerSample bits per sample. + * @param channel number of channels of the audio source. + * @exception Exception + */ + inline void + init ( unsigned int sampleRate, + unsigned int bitsPerSample, + unsigned int channel ) throw ( Exception ) + { + this->sampleRate = sampleRate; + this->bitsPerSample = bitsPerSample; + this->channel = channel; + } + + /** + * De-initialize the object. + * + * @exception Exception + */ + inline void + strip ( void ) throw ( Exception ) + { + } + + + protected: + + /** + * Constructor. + * Because all values have defaults, this is also the default + * constructor. + * + * @param sampleRate samples per second (e.g. 44100 for 44.1kHz). + * @param bitsPerSample bits per sample (e.g. 16 bits). + * @param channel number of channels of the audio source + * (e.g. 1 for mono, 2 for stereo, etc.). + * @exception Exception + */ + inline + AudioSource ( unsigned int sampleRate = 44100, + unsigned int bitsPerSample = 16, + unsigned int channel = 2 ) + throw ( Exception ) + { + init ( sampleRate, bitsPerSample, channel); + } + + /** + * Copy Constructor. + * + * @param as the object to copy. + * @exception Exception + */ + inline + AudioSource ( const AudioSource & as ) throw ( Exception ) + : Source( as ) + { + init ( as.sampleRate, as.bitsPerSample, as.channel); + } + + /** + * Assignment operator. + * + * @param as the object to assign to this one. + * @return a reference to this object. + * @exception Exception + */ + inline virtual AudioSource & + operator= ( const AudioSource & as ) throw ( Exception ) + { + if ( this != &as ) { + strip(); + Source::operator=( as ); + init ( as.sampleRate, as.bitsPerSample, as.channel); + } + + return *this; + } + + + public: + + /** + * Destructor. + * + * @exception Exception + */ + virtual inline + ~AudioSource ( void ) throw ( Exception ) + { + } + + /** + * Get the number of channels for this AudioSource. + * + * @return the number of channels. + */ + inline unsigned int + getChannel ( void ) const throw () + { + return channel; + } + + /** + * Tell if the data from this source comes in big or little endian. + * + * @return true if the data is big endian, false if little endian + */ + virtual bool + isBigEndian ( void ) const throw () + { +#ifdef WORDS_BIGENDIAN + return true; +#else + return false; +#endif + } + + /** + * Get the sample rate per seconds for this AudioSource. + * + * @return the sample rate per seconds. + */ + inline unsigned int + getSampleRate ( void ) const throw () + { + return sampleRate; + } + + + /** + * Get the number of bits per sample for this AudioSource. + * + * @return the number of bits per sample. + */ + inline unsigned int + getBitsPerSample ( void ) const throw () + { + return bitsPerSample; + } + + /** + * Get the number of bytes for a sample for each channel + * (returns 4 bytes for 16 bits par sample in stereo) + * + * @return the number of bits per sample. + */ + inline unsigned int + getSampleSize ( void ) const throw () + { + return bitsPerSample / 8 * channel; + } + + /** + * Factory method for creating an AudioSource object of the + * appropriate type, based on the compiled DSP support and + * the supplied DSP name parameter. + * + * @param deviceName the audio device (/dev/dspX, hwplug:0,0, etc) + * @param jackClientName the source name for jack server + * @param paSourceName the pulse audio source + * @param sampleRate samples per second (e.g. 44100 for 44.1kHz). + * @param bitsPerSample bits per sample (e.g. 16 bits). + * @param channel number of channels of the audio source + * (e.g. 1 for mono, 2 for stereo, etc.). + * @exception Exception + */ + static AudioSource * + createDspSource( const char * deviceName, + const char * jackClientName, + const char * paSourceName, + int sampleRate = 44100, + int bitsPerSample = 16, + int channel = 2) throw ( Exception ); + +}; + + +/* ================================================= external data structures */ + +/*------------------------------------------------------------------------------ + * Determine the kind of audio device based on the system + *----------------------------------------------------------------------------*/ +#if defined( SUPPORT_ALSA_DSP ) +#include "AlsaDspSource.h" +#endif + +#if defined( SUPPORT_PULSEAUDIO_DSP ) +#include "PulseAudioDspSource.h" +#endif + +#if defined( SUPPORT_OSS_DSP ) +#include "OssDspSource.h" +#endif + +#if defined( SUPPORT_SOLARIS_DSP ) +#include "SolarisDspSource.h" +#endif + +#if defined( SUPPORT_JACK_DSP ) +#include "JackDspSource.h" +#endif + +#if defined ( SUPPORT_SERIAL_ULAW ) +#include "SerialUlaw.h" +#endif + + +/* ====================================================== function prototypes */ + + + +#endif /* AUDIO_SOURCE_H */ diff --git a/darkice/tags/darkice-1_3/src/BufferedSink.cpp b/darkice/tags/darkice-1_3/src/BufferedSink.cpp new file mode 100644 index 0000000..460baed --- /dev/null +++ b/darkice/tags/darkice-1_3/src/BufferedSink.cpp @@ -0,0 +1,434 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : BufferedSink.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + the buffer is filled like this: + + buffer bufferEnd + | | + +----------+--------------------------+--------------+ + |<---- valid data -------->| + outp inp + + buffer bufferEnd + | | + +----------------+--------------+--------------------+ + -- valid data -->| |--- valid data -----> + inp outp + + + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + + +#include "Exception.h" +#include "BufferedSink.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +BufferedSink :: init ( Sink * sink, + unsigned int size, + unsigned int chunkSize ) throw ( Exception ) +{ + if ( !sink ) { + throw Exception( __FILE__, __LINE__, "no sink"); + } + + this->sink = sink; // create a reference + this->chunkSize = chunkSize ? chunkSize : 1; + this->bufferSize = size; + // make bufferSize a multiple of chunkSize + this->bufferSize -= this->bufferSize % this->chunkSize; + this->peak = 0; + this->misalignment = 0; + this->buffer = new unsigned char[bufferSize]; + this->bufferEnd = buffer + bufferSize; + this->inp = buffer; + this->outp = buffer; + this->bOpen = true; + this->openAttempts = 0; +} + + +/*------------------------------------------------------------------------------ + * Copy Constructor + *----------------------------------------------------------------------------*/ +BufferedSink :: BufferedSink ( const BufferedSink & buffer ) + throw ( Exception ) +{ + init( buffer.sink.get(), buffer.bufferSize, buffer.chunkSize); + + this->peak = buffer.peak; + this->misalignment = buffer.misalignment; + this->bOpen = buffer.bOpen; + this->openAttempts = buffer.openAttempts; + memcpy( this->buffer, buffer.buffer, this->bufferSize); +} + + +/*------------------------------------------------------------------------------ + * De-initalize the object + *----------------------------------------------------------------------------*/ +void +BufferedSink :: strip ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + sink = 0; // delete the reference + delete buffer; +} + + +/*------------------------------------------------------------------------------ + * Assignment operator + *----------------------------------------------------------------------------*/ +BufferedSink & +BufferedSink :: operator= ( const BufferedSink & buffer ) + throw ( Exception ) +{ + if ( this != &buffer ) { + strip(); + Sink::operator=( buffer ); + init( buffer.sink.get(), buffer.bufferSize, buffer.chunkSize); + + this->peak = buffer.peak; + this->misalignment = buffer.misalignment; + this->bOpen = buffer.bOpen; + this->openAttempts = buffer.openAttempts; + memcpy( this->buffer, buffer.buffer, this->bufferSize); + } + + return *this; +} + + +/*------------------------------------------------------------------------------ + * Store bufferSize bytes into the buffer + * All data is consumed. The return value is less then bufferSize only + * if the BufferedSink's internal buffer is smaller than bufferSize, + * thus can't hold that much + * The data to be stored is treated as parts with chunkSize size + * Only full chunkSize sized parts are stored + *----------------------------------------------------------------------------*/ +unsigned int +BufferedSink :: store ( const void * buffer, + unsigned int bufferSize ) throw ( Exception ) +{ + const unsigned char * buf; + unsigned int size; + unsigned int i; + unsigned char * oldInp; + + if ( !buffer ) { + throw Exception( __FILE__, __LINE__, "buffer is null"); + } + + if ( !bufferSize ) { + return 0; + } + + unsigned int remaining = this->bufferSize - ( outp <= inp ? inp - outp : + (bufferEnd - outp) + (inp - this->buffer) ); + + // react only to the first overrun whenever there is a series of overruns + if ( remaining + chunkSize <= bufferSize && remaining > chunkSize ) { + reportEvent(3,"BufferedSink :: store, buffer overrun"); + throw Exception( __FILE__, __LINE__, + "buffer overrun"); + } + + oldInp = inp; + buf = (const unsigned char *) buffer; + + // adjust so it is a multiple of chunkSize + bufferSize -= bufferSize % chunkSize; + + // cut the front of the supplied buffer if it wouldn't fit + if ( bufferSize > this->bufferSize ) { + size = this->bufferSize - 1; + size -= size % chunkSize; // keep it a multiple of chunkSize + buf += bufferSize - size; + } else { + size = bufferSize; + } + + // copy the data into the buffer + i = bufferEnd - inp; + if ( (i % chunkSize) != 0 ) { + throw Exception( __FILE__, __LINE__, "copy quantity not aligned", i); + } + + if ( size <= i ) { + // the place between inp and bufferEnd is + // big enough to hold the data + + memcpy( inp, buf, size); + inp = slidePointer( inp, size); + + // adjust outp, lose the data that was overwritten, if any + if ( outp > oldInp && outp <= inp ) { + outp = slidePointer( inp, chunkSize); + } + + } else { + // the place between inp and bufferEnd is not + // big enough to hold the data + // writing will take place in two turns, once from + // inp -> bufferEnd, then from buffer -> + + memcpy( inp, buf, i); + i = size - i; + if ( (i % chunkSize) != 0 ) { + throw Exception(__FILE__, __LINE__, "copy quantity not aligned", i); + } + memcpy( this->buffer, buf, i); + inp = slidePointer( this->buffer, i); + + // adjust outp, lose the data that was overwritten, if any + if ( outp <= oldInp ) { + if ( outp < inp ) { + outp = slidePointer( inp, chunkSize); + } + } else { + outp = slidePointer( inp, chunkSize); + } + } + + updatePeak(); + + if ( ((inp - this->buffer) % chunkSize) != 0 ) { + throw Exception( __FILE__, __LINE__, + "inp not aligned", inp - this->buffer); + } + if ( ((outp - this->buffer) % chunkSize) != 0 ) { + throw Exception( __FILE__, __LINE__, + "outp not aligned", outp - this->buffer); + } + + return size; +} + + +/*------------------------------------------------------------------------------ + * Write some data to the sink + * if len == 0, try to flush the buffer + *----------------------------------------------------------------------------*/ +unsigned int +BufferedSink :: write ( const void * buf, + unsigned int len ) throw ( Exception ) +{ + unsigned int length = 0; + unsigned int soFar = 0; + unsigned char * b = (unsigned char *) buf; + + if ( !buf ) { + throw Exception( __FILE__, __LINE__, "buf is null"); + } + + if ( !isOpen() ) { + return 0; + } + + if ( !align() ) { + return 0; + } + + if ( !sink->isOpen() && openAttempts < 10 ) { + // try to reopen underlying sink, because it has closed on its own + openAttempts++; + try { + if( sink->open() ) { + // if reopening succeeds, reset open attempts + openAttempts = 0; + } + } catch ( Exception &e ) { + reportEvent( 4,"BufferedSink :: write,", + "couldn't reopen underlying sink, attempt", + openAttempts, "/ 10" ); + } + + if( openAttempts == 10 ) { + // all the attempts have been used, give up + close(); + throw Exception( __FILE__, __LINE__, + "reopen failed"); + } + } + + // make it a multiple of chunkSize + len -= len % chunkSize; + + // try to write data from the buffer first, if any + if ( inp != outp ) { + unsigned int size = 0; + unsigned int total = 0; + + if ( outp > inp ) { + // valuable data is between outp -> bufferEnd and buffer -> inp + // try to write the outp -> bufferEnd + // the rest will be written in the next if + + size = bufferEnd - outp; + size -= size % chunkSize; + if( size > len * 2 ) { + // do not try to send the content of the entire buffer at once, + // but limit sending to a multiple of len + // this prevents a surge of data to underlying buffer + // which is important especially during a lot of packet loss + size = len * 2; + } + soFar = 0; + + while ( outp > inp && soFar < size && sink->canWrite( 0, 0) ) { + try { + length = sink->write( outp + soFar, size - soFar); + } catch (Exception &e) { + length = 0; + reportEvent(3,"Exception caught in BufferedSink :: write1"); + } + outp = slidePointer( outp, length); + soFar += length; + } + + total += soFar; + } + + if ( outp < inp ) { + // valuable data is between outp and inp + // in the previous if wrote all data from the end + // this part will write the rest + + size = inp - outp; + if( size > len * 2 ) { + // prevent a surge of data to underlying buffer + size = len * 2; + } + soFar = 0; + + while ( soFar < size && sink->canWrite( 0, 0) ) { + try { + length = sink->write( outp + soFar, size - soFar); + } catch (Exception &e) { + length = 0; + reportEvent(3,"Exception caught in BufferedSink :: write2" ); + } + outp = slidePointer( outp, length); + soFar += length; + } + + total += soFar; + } + + while ( (outp - buffer) % chunkSize ) { + slidePointer( outp, 1); + } + + // calulate the misalignment to chunkSize boundaries + misalignment = (chunkSize - (total % chunkSize)) % chunkSize; + } + + if ( !align() ) { + return 0; + } + + // the internal buffer is empty, try to write the fresh data + soFar = 0; + if ( inp == outp ) { + while ( soFar < len && sink->canWrite( 0, 0) ) { + try { + soFar += sink->write( b + soFar, len - soFar); + } catch (Exception &e) { + reportEvent(3,"Exception caught in BufferedSink :: write3"); + } + } + } + length = soFar; + + // calulate the misalignment to chunkSize boundaries + misalignment = (chunkSize - (length % chunkSize)) % chunkSize; + + if ( length < len ) { + // if not all fresh could be written, store the remains + + store( b + length, len - length); + } + + updatePeak(); + + // tell them we ate everything up to chunkSize alignment + return len; +} + + +/*------------------------------------------------------------------------------ + * Close the sink, lose all pending data + *----------------------------------------------------------------------------*/ +void +BufferedSink :: close ( void ) throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + flush(); + sink->close(); + inp = outp = buffer; + bOpen = false; +} + diff --git a/darkice/tags/darkice-1_3/src/BufferedSink.h b/darkice/tags/darkice-1_3/src/BufferedSink.h new file mode 100644 index 0000000..2445c38 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/BufferedSink.h @@ -0,0 +1,419 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : BufferedSink.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef BUFFERED_SINK_H +#define BUFFERED_SINK_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Ref.h" +#include "Reporter.h" +#include "Sink.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A Sink First-In First-Out buffer. + * This buffer can always be written to, it overwrites any + * data contained if needed. + * The class is not thread-safe. + * + * @author $Author$ + * @version $Revision$ + */ +class BufferedSink : public Sink, public virtual Reporter +{ + private: + + /** + * The buffer. + */ + unsigned char * buffer; + + /** + * The end of the buffer. + */ + unsigned char * bufferEnd; + + /** + * The size of the buffer. + */ + unsigned int bufferSize; + + /** + * The highest usage of the buffer. + */ + unsigned int peak; + + /** + * All data written to this BufferedSink is handled by chuncks + * of this size. + */ + unsigned int chunkSize; + + /** + * Number of bytes the underlying stream is misaligned with + * chunkSize. (It needs this many bytes more to be aligned.) + */ + unsigned int misalignment; + + /** + * Start of free territory in buffer. + */ + unsigned char * inp; + + /** + * Start of sensible data in buffer. + */ + unsigned char * outp; + + + /** + * The underlying Sink. + */ + Ref sink; + + /** + * Is BufferedSink open. + */ + bool bOpen; + + /** + * Number of attempts so far to open underlying sink after it has + * closed on its own. + */ + unsigned int openAttempts; + + /** + * Initialize the object. + * + * @param sink the Sink to attach this BufferedSink to. + * @param size the size of the internal buffer to use. + * @param chunkSize size of chunks to handle data in. + * @exception Exception + */ + void + init ( Sink * sink, + unsigned int size, + unsigned int chunkSize ) throw ( Exception ); + + /** + * De-initialize the object. + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + /** + * Slide a pointer in the internal buffer by offset. If the pointer + * would reach beyond the end of the buffer, it goes wraps around. + * + * @param p the pointer to slide. + * @param offset the amount to slide with. + * @return pointer p + offset, wrapped around if needed. + */ + inline unsigned char * + slidePointer ( + unsigned char * p, + unsigned int offset ) throw () + { + p += offset; + while ( p >= bufferEnd ) { + p -= bufferSize; + } + + return p; + } + + /** + * Update the peak buffer usage indicator. + * + * @see #peak + */ + inline void + updatePeak ( void ) throw () + { + unsigned int u; + + u = outp <= inp ? inp - outp : (bufferEnd - outp) + (inp - buffer); + + // report new peaks if it is either significantly more severe than + // the previously reported peak + if ( peak * 2 < u ) { + peak = u; + reportEvent( 4, "BufferedSink, new peak:", peak, " / ", bufferSize); + } + + if ( peak > 0 && u == 0 ) { + peak = 0; + reportEvent( 4, "BufferedSink, healed:", peak, " / ", bufferSize); + } + } + + /** + * If the underlying Sink is misaligned on chunkSize, write as + * many 0s as needed to get it aligned. + * + * @see #misalignment + * @see #chunkSize + */ + inline bool + align ( void ) throw ( Exception ) + { + char b[] = { 0 }; + + while ( misalignment ) { + if ( sink->canWrite( 0, 0) ) { + unsigned int ret; + + if ( !(ret = sink->write( b, 1)) ) { + return false; + } + --misalignment; + + } else { + return false; + } + } + + return true; + } + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + BufferedSink ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Get the size of the buffer. + * + * @return the size of the buffer. + */ + inline unsigned int + getSize ( void ) const throw () + { + return bufferSize; + } + + /** + * Store data in the internal buffer. If there is not enough space, + * discard all in the buffer and the beginning of the supplied + * buffer if needed. + * + * @param buffer the data to store. + * @param bufferSize the amount of data to store in bytes. + * @return number of bytes really stored. + */ + unsigned int + store ( const void * buffer, + unsigned int bufferSize ) throw ( Exception ); + + + public: + + /** + * Constructor by an underlying Sink, buffer size and chunk size. + * + * @param sink the Sink to attach this BufferSink to. + * @param size the size of the buffer to use for buffering. + * @param chunkSize hanlde all data in write() as chunks of + * chunkSize + * @exception Exception + */ + inline + BufferedSink ( Sink * sink, + unsigned int size, + unsigned int chunkSize = 1 ) throw ( Exception ) + { + init( sink, size, chunkSize); + } + + /** + * Copy constructor. + * + * @param buffer the object to copy. + * @exception Exception + */ + BufferedSink ( const BufferedSink & buffer ) throw ( Exception ); + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~BufferedSink ( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param bs the object to assign to this one. + * @return a reference to this object. + * @exception Exception + */ + virtual BufferedSink & + operator= ( const BufferedSink & bs ) throw ( Exception ); + + /** + * Get the peak usage of the internal buffer. + * + * @return the peak usage of the internal buffer. + */ + inline unsigned int + getPeak ( void ) const throw () + { + return peak; + } + + /** + * Open the BufferedSink. Opens the underlying Sink. + * + * @return true if opening was successful, false otherwise. + * @exception Exception + */ + inline virtual bool + open ( void ) throw ( Exception ) + { + bOpen = sink->open(); + openAttempts = 0; + return bOpen; + } + + /** + * Check if a BufferedSink is open. + * + * @return true if the BufferedSink is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return bOpen; + } + + /** + * Check if the BufferedSink is ready to accept data. + * Always returns true immediately. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true + * @exception Exception + */ + inline virtual bool + canWrite ( unsigned int sec, + unsigned int usec ) throw ( Exception ) + { + return true; + } + + /** + * Write data to the BufferedSink. + * Always reads the maximum number of chunkSize chunks buf + * holds. If the data can not be written to the underlying + * stream, it is buffered. If the buffer overflows, the oldest + * data is discarded. + * + * @param buf the data to write. + * @param len number of bytes to write from buf. + * @return the number of bytes written (may be less than len). + * @exception Exception + */ + virtual unsigned int + write ( const void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Flush all data that was written to the BufferedSink to the + * underlying Sink. + * + * @exception Exception + */ + inline virtual void + flush ( void ) throw ( Exception ) + { + unsigned char b[1]; + + write( b, 0); + } + + /** + * Cut what the sink has been doing so far, and start anew. + * This usually means separating the data sent to the sink up + * until now, and start saving a new chunk of data. + */ + inline virtual void + cut ( void ) throw () + { + flush(); + sink->cut(); + } + + /** + * Close the BufferedSink. Closes the underlying Sink. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* BUFFERED_SINK_H */ + diff --git a/darkice/tags/darkice-1_3/src/CastSink.cpp b/darkice/tags/darkice-1_3/src/CastSink.cpp new file mode 100644 index 0000000..aa5c14c --- /dev/null +++ b/darkice/tags/darkice-1_3/src/CastSink.cpp @@ -0,0 +1,133 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : CastSink.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#include "Util.h" +#include "Exception.h" +#include "CastSink.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +CastSink :: init ( TcpSocket * socket, + Sink * streamDump, + const char * password, + unsigned int bitRate, + const char * name, + const char * url, + const char * genre, + bool isPublic ) + throw ( Exception ) +{ + this->socket = socket; + this->streamDump = streamDump; + this->password = password ? Util::strDup( password) : 0; + this->bitRate = bitRate; + this->name = name ? Util::strDup( name) : 0; + this->url = url ? Util::strDup( url) : 0; + this->genre = genre ? Util::strDup( genre) : 0; + this->isPublic = isPublic; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +CastSink :: strip ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + if ( password ) { + delete[] password; + } + if ( name ) { + delete[] name; + } + if ( url ) { + delete[] url; + } + if ( genre ) { + delete[] genre; + } +} + + +/*------------------------------------------------------------------------------ + * Open the connection + *----------------------------------------------------------------------------*/ +bool +CastSink :: open ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + return false; + } + + if ( !getSink()->open() ) { + return false; + } + + if ( !sendLogin() ) { + close(); + return false; + } + + if ( streamDump != 0 ) { + if ( !streamDump->isOpen() ) { + if ( !streamDump->open() ) { + reportEvent( 2, "can't open stream dump"); + } + } + } + + return true; +} + + diff --git a/darkice/tags/darkice-1_3/src/CastSink.h b/darkice/tags/darkice-1_3/src/CastSink.h new file mode 100644 index 0000000..79b934f --- /dev/null +++ b/darkice/tags/darkice-1_3/src/CastSink.h @@ -0,0 +1,454 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : CastSink.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef CAST_SINK_H +#define CAST_SINK_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Ref.h" +#include "Reporter.h" +#include "Sink.h" +#include "TcpSocket.h" +#include "BufferedSink.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * Data output to a ShoutCast / IceCast / etc. server + * This is an abstract class. A subclass should override at least + * the sendLogin() function. + * + * @author $Author$ + * @version $Revision$ + */ +class CastSink : public Sink, public virtual Reporter +{ + private: + + /** + * The socket connection to the server. + */ + Ref socket; + + /** + * An optional Sink to enable stream dumps. + */ + Ref streamDump; + + /** + * Password to the server. + */ + char * password; + + /** + * Name of the stream. + */ + char * name; + + /** + * URL associated with the stream. + */ + char * url; + + /** + * Genre of the stream. + */ + char * genre; + + /** + * Bitrate of the stream (e.g. mp3 bitrate). + */ + unsigned int bitRate; + + /** + * Is the stream public? + */ + bool isPublic; + + /** + * Initalize the object. + * + * @param socket socket connection to the server. + * @param password password to the server. + * @param name name of the stream. + * @param url URL associated with the stream. + * @param genre genre of the stream. + * @param bitRate bitrate of the stream (e.g. mp3 bitrate). + * @param isPublic is the stream public? + * @exception Exception + */ + void + init ( TcpSocket * socket, + Sink * streamDump, + const char * password, + unsigned int bitRate, + const char * name, + const char * url, + const char * genre, + bool isPublic) + throw ( Exception ); + + /** + * De-initalize the object. + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + CastSink ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Log in to the server using the socket avialable. + * + * @return true if login was successful, false otherwise. + * @exception Exception + */ + virtual bool + sendLogin ( void ) throw ( Exception ) = 0; + + /** + * Get the Sink underneath this CastSink. + * + * @return pointer to the Sink underneath this CastSink. + */ + inline Sink * + getSink ( void ) const throw () + { + return getSocket(); + } + + /** + * Get the TcpSocket underneath this CastSink. + * + * @return pointer to the TcpSocket underneath this CastSink. + */ + inline TcpSocket * + getSocket ( void ) const throw () + { + return socket.get(); + } + + + public: + + /** + * Constructor. + * + * @param socket socket connection to the server. + * @param password password to the server. + * @param name name of the stream. + * @param url URL associated with the stream. + * @param genre genre of the stream. + * @param bitRate bitrate of the stream (e.g. mp3 bitrate). + * @param isPublic is the stream public? + * @param streamDump a Sink to dump the streamed binary data to + * + * @exception Exception + */ + inline + CastSink ( TcpSocket * socket, + const char * password, + unsigned int bitRate, + const char * name = 0, + const char * url = 0, + const char * genre = 0, + bool isPublic = false, + Sink * streamDump = 0) + throw ( Exception ) + { + init( socket, + streamDump, + password, + bitRate, + name, + url, + genre, + isPublic ); + } + + /** + * Copy constructor. + * + * @param cs the CastSink to copy. + */ + inline + CastSink( const CastSink & cs ) throw ( Exception ) + : Sink( cs ) + { + init( cs.socket.get(), + cs.streamDump.get(), + cs.password, + cs.bitRate, + cs.name, + cs.url, + cs.genre, + cs.isPublic ); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~CastSink( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param cs the CastSink to assign this to. + * @return a reference to this CastSink. + * @exception Exception + */ + inline virtual CastSink & + operator= ( const CastSink & cs ) throw ( Exception ) + { + if ( this != &cs ) { + strip(); + Sink::operator=( cs ); + init( cs.socket.get(), + cs.streamDump.get(), + cs.password, + cs.bitRate, + cs.name, + cs.url, + cs.genre, + cs.isPublic ); + } + return *this; + } + + /** + * Open the CastSink. + * Logs in to the server. + * + * @return true if opening was successfull, false otherwise. + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the CastSink is open. + * + * @return true if the CastSink is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + if( !getSink() ) { + return false; + } + return getSink()->isOpen(); + } + + /** + * Check if the CastSink is ready to accept data. + * Blocks until the specified time for data to be available. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the CastSink is ready to accept data, + * false otherwise. + * @exception Exception + */ + inline virtual bool + canWrite ( unsigned int sec, + unsigned int usec ) throw ( Exception ) + { + return getSink()->canWrite( sec, usec); + } + + /** + * Write data to the CastSink. + * + * @param buf the data to write. + * @param len number of bytes to write from buf. + * @return the number of bytes written (may be less than len). + * @exception Exception + */ + inline virtual unsigned int + write ( const void * buf, + unsigned int len ) throw ( Exception ) + { + if ( streamDump != 0 ) { + streamDump->write( buf, len); + } + + return getSink()->write( buf, len); + } + + /** + * Flush all data that was written to the CastSink to the server. + * + * @exception Exception + */ + inline virtual void + flush ( void ) throw ( Exception ) + { + if ( streamDump != 0 ) { + streamDump->flush(); + } + + return getSink()->flush(); + } + + /** + * Cut what the sink has been doing so far, and start anew. + * This usually means separating the data sent to the sink up + * until now, and start saving a new chunk of data. + */ + inline virtual void + cut ( void ) throw () + { + if ( streamDump != 0 ) { + streamDump->cut(); + } + } + + /** + * Close the CastSink. + * + * @exception Exception + */ + inline virtual void + close ( void ) throw ( Exception ) + { + if ( streamDump != 0 ) { + streamDump->close(); + } + + return getSink()->close(); + } + + /** + * Get the password to the server. + * + * @return the password to the server. + */ + inline const char * + getPassword ( void ) const throw () + { + return password; + } + + /** + * Get the name of the stream. + * + * @return the name of the stream. + */ + inline const char * + getName ( void ) const throw () + { + return name; + } + + /** + * Get the URL associated with the stream. + * + * @return the URL associated with the stream. + */ + inline const char * + getUrl ( void ) const throw () + { + return url; + } + + /** + * Get the genre of the stream. + * + * @return the genre of the stream. + */ + inline const char * + getGenre ( void ) const throw () + { + return genre; + } + + /** + * Get the bitrate of the stream (e.g. mp3 bitrate). + * + * @return the bitrate of the stream (e.g. mp3 bitrate). + */ + inline unsigned int + getBitRate ( void ) const throw () + { + return bitRate; + } + + /** + * Get whether this stream is public. + * + * @return true if the stream is public, false otherwise. + */ + inline bool + getIsPublic ( void ) const throw () + { + return isPublic; + } +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* CAST_SINK_H */ + diff --git a/darkice/tags/darkice-1_3/src/ConfigSection.cpp b/darkice/tags/darkice-1_3/src/ConfigSection.cpp new file mode 100644 index 0000000..7a3bc48 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/ConfigSection.cpp @@ -0,0 +1,173 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell ConfigSection + + File : ConfigSection.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + + +#include "ConfigSection.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/*------------------------------------------------------------------------------ + * string containing all white space characters + *----------------------------------------------------------------------------*/ +#define WHITE_SPACE_STR " \t" + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Add a key / value pair + *----------------------------------------------------------------------------*/ +bool +ConfigSection :: add ( const char * key, + const char * value ) throw ( Exception ) +{ + if ( !key || !value ) { + throw Exception( __FILE__, __LINE__, "no key or value"); + } + + std::pair element( key, value); + std::pair res; + + res = table.insert( element); + + return res.second; +} + + +/*------------------------------------------------------------------------------ + * Get a value for a key + *----------------------------------------------------------------------------*/ +const char * +ConfigSection :: get ( const char * key ) const throw ( Exception ) +{ + if ( !key ) { + throw Exception( __FILE__, __LINE__, "no key"); + } + + TableType::const_iterator it = table.find( key); + if ( it == table.end() ) { + return 0; + } + return it->second.c_str(); +} + + +/*------------------------------------------------------------------------------ + * Get a value for a key, in the key does not exist, throw an exception + *----------------------------------------------------------------------------*/ +const char * +ConfigSection :: getForSure ( const char * key, + const char * message1, + const char * message2, + int code ) const + throw ( Exception ) +{ + const char * value; + + if ( !(value = get( key)) ) { + throw Exception( __FILE__, __LINE__, key, message1, message2, code); + } + + return value; +} + + +/*------------------------------------------------------------------------------ + * Add a configuration line + *----------------------------------------------------------------------------*/ +bool +ConfigSection :: addLine ( const char * line ) throw ( Exception ) +{ + if ( !line ) { + throw Exception( __FILE__, __LINE__, "no line"); + } + + std::string::size_type ix; + std::string str( line); + + /* delete everything after the first # */ + if ( (ix = str.find( '#')) != str.npos ) { + str.erase( ix); + } + /* eat up all white space from the front */ + if ( (ix = str.find_first_not_of( WHITE_SPACE_STR)) != str.npos ) { + str.erase( 0, ix); + } + /* eat up all white space from the end */ + if ( (ix = str.find_last_not_of( WHITE_SPACE_STR)) != str.npos ) { + str.erase( ix + 1); + } + if ( !str.length() ) { + return true; + } + + /* find the '=' delimiter between key and value */ + if ( (ix = str.find( '=')) == str.npos ) { + return false; + } + + std::string key( str, 0, ix); + std::string value( str, ix + 1); + + /* eat up all white space from the front of value */ + if ( (ix = value.find_first_not_of( WHITE_SPACE_STR)) != value.npos ) { + value.erase( 0, ix); + } + /* eat up all white space from the end of key */ + if ( (ix = key.find_last_not_of( WHITE_SPACE_STR)) != key.npos ) { + key.erase( ix + 1); + } + + /* now add the new key / value pair */ + return add( key.c_str(), value.c_str()); +} + diff --git a/darkice/tags/darkice-1_3/src/ConfigSection.h b/darkice/tags/darkice-1_3/src/ConfigSection.h new file mode 100644 index 0000000..2a42ec2 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/ConfigSection.h @@ -0,0 +1,184 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell ConfigSection + + File : ConfigSection.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef CONFIG_SECTION_H +#define CONFIG_SECTION_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include +#include + +#include "Referable.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A configuration file representation. The file is of the syntax: + * + *
+ *  # this is a whole line comment
+ *  key = value
+ *  an ugly key name = long value    # this end is a comment too
+ *  
+ * + * also empty lines are ignored and all white space is removed + * from the front and end of keys / values + * + * Knwon problem: you can't use '#' in any part of a key / value pair + * + * @author $Author$ + * @version $Revision$ + */ +class ConfigSection : public virtual Referable +{ + private: + + /** + * Type of the hash table used in this class. + */ + typedef std::map TableType; + + /** + * Hash table holding the configuration information. + */ + TableType table; + + + protected: + + + public: + + /** + * Default constructor. + * + * @exception Exception + */ + inline + ConfigSection ( void ) throw ( Exception ) + { + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~ConfigSection ( void ) throw ( Exception ) + { + } + + +/* TODO + + inline + ConfigSection ( const ConfigSection & di ) throw ( Exception ) + { + } + + + inline ConfigSection & + operator= ( const ConfigSection * di ) throw ( Exception ) + { + } +*/ + + /** + * Add a key / value pair to the configuration information. + * + * @param key the key to add the value by + * @param value the value to add for the key + * @return true if adding was successful, false otherwise + * @exception Exception + */ + virtual bool + add ( const char * key, + const char * value ) throw ( Exception ); + + /** + * Get a value for a key. + * + * @param key the key to get the value for + * @return the value for the key, or NULL if the key doesn't exist. + * @exception Exception + */ + virtual const char * + get ( const char * key ) const throw ( Exception ); + + /** + * Get a value for a key, or throw an Exception. + * + * @param key the key to get the value for + * @param message1 message part 1 of the Exception to be thrown. + * @param message2 message part 2 of the Exception to be thrown. + * @param code error code of the Exception to be thrown. + * @return the value for the key. The return value is never NULL. + * @exception Exception + */ + virtual const char * + getForSure ( const char * key, + const char * message1 = 0, + const char * message2 = 0, + int code = 0 ) const + throw ( Exception ); + + /** + * Add a line of configuration information. + * + * @param line the line to add. + * @return true if a new key was added, false otherwise. + * @exception Exception + */ + virtual bool + addLine ( const char * line ) throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* CONFIG_SECTION_H */ + diff --git a/darkice/tags/darkice-1_3/src/Connector.cpp b/darkice/tags/darkice-1_3/src/Connector.cpp new file mode 100644 index 0000000..f2b9139 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/Connector.cpp @@ -0,0 +1,358 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : Connector.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#include "Exception.h" +#include "Connector.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +Connector :: init ( Source * source ) throw ( Exception ) +{ + this->source = source; + this->sinks = 0; + this->numSinks = 0; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +Connector :: strip ( void ) throw ( Exception ) +{ + source = 0; + + if ( sinks ) { + unsigned int u; + + for ( u = 0; u < numSinks; ++u ) { + sinks[u] = 0; + } + + delete[] sinks; + } +} + + +/*------------------------------------------------------------------------------ + * Constructor + *----------------------------------------------------------------------------*/ +Connector :: Connector ( const Connector & connector ) throw ( Exception ) +{ + unsigned int u; + + init( connector.source.get()); + + for ( u = 0; u < connector.numSinks; ++u ) { + attach( connector.sinks[u].get() ); + } +} + + +/*------------------------------------------------------------------------------ + * Assignment operator + *----------------------------------------------------------------------------*/ +Connector & +Connector :: operator= ( const Connector & connector ) throw ( Exception ) +{ + if ( this != &connector ) { + unsigned int u; + + // first free everything + strip(); + + // then fill in + init( connector.source.get() ); + + for ( u = 0; u < connector.numSinks; ++u ) { + attach( connector.sinks[u].get() ); + } + } + + return *this; +} + + +/*------------------------------------------------------------------------------ + * Attach a sink to the connector + *----------------------------------------------------------------------------*/ +void +Connector :: attach ( Sink * sink ) throw ( Exception ) +{ + if ( !sinks ) { + + numSinks = 1; + sinks = new Ref[1]; + sinks[0] = sink; + + } else { + + unsigned int u; + Ref * s = new Ref[numSinks + 1]; + + for ( u = 0; u < numSinks; ++u ) { + s[u] = sinks[u].get(); + } + + s[numSinks] = sink; + delete[] sinks; + sinks = s; + ++numSinks; + } +} + + +/*------------------------------------------------------------------------------ + * Detach a sink to the connector + *----------------------------------------------------------------------------*/ +bool +Connector :: detach ( Sink * sink ) throw ( Exception ) +{ + if ( numSinks == 0 ) { + + return false; + + } else if ( numSinks == 1 ) { + + if ( sinks[0].get() != sink ) { + return false; + } + + sinks[0] = 0; + delete[] sinks; + sinks = 0; + --numSinks; + + return true; + + } else { + + unsigned int u; + unsigned int v; + unsigned int ix; + Ref * s; + + ix = numSinks; + for ( u = 0; u < numSinks; ++u ) { + + if ( sinks[u].get() == sink ) { + ix = u; + break; + } + } + + if ( ix == numSinks ) { + return false; + } + + s = new Ref[numSinks - 1]; + for ( u = 0, v = 0; u < numSinks; ++u ) { + + if ( u != ix ) { + s[v++] = sinks[u]; + } + } + + sinks[ix] = 0; + delete[] sinks; + sinks = s; + --numSinks; + + return true; + } +} + + +/*------------------------------------------------------------------------------ + * Open the source and all the sinks if needed + *----------------------------------------------------------------------------*/ +bool +Connector :: open ( void ) throw ( Exception ) +{ + unsigned int u; + + if ( !source->isOpen() ) { + if ( !source->open() ) { + return false; + } + } + + for ( u = 0; u < numSinks; ++u ) { + if ( !sinks[u]->isOpen() ) { + if ( !sinks[u]->open() ) { + break; + } + } + } + + // if not all could be opened, close those that were + if ( u < numSinks ) { + unsigned int v; + + for ( v = 0; v < u; ++v ) { + sinks[v]->close(); + } + + source->close(); + + return false; + } + + return true; +} + + +/*------------------------------------------------------------------------------ + * Transfer some data from the source to the sink + *----------------------------------------------------------------------------*/ +unsigned int +Connector :: transfer ( unsigned long bytes, + unsigned int bufSize, + unsigned int sec, + unsigned int usec ) throw ( Exception ) +{ + unsigned int u; + unsigned long b; + + if ( numSinks == 0 ) { + return 0; + } + + if ( bufSize == 0 ) { + return 0; + } + + unsigned char * buf = new unsigned char[bufSize]; + + reportEvent( 6, "Connector :: transfer, bytes", bytes); + + for ( b = 0; !bytes || b < bytes; ) { + unsigned int d = 0; + unsigned int e = 0; + + if ( source->canRead( sec, usec) ) { + d = source->read( buf, bufSize); + + // check for EOF + if ( d == 0 ) { + reportEvent( 3, "Connector :: transfer, EOF"); + break; + } + + for ( u = 0; u < numSinks; ++u ) { + + if ( sinks[u]->canWrite( sec, usec) ) { + try { + // we expect the sink to accept all data written + e = sinks[u]->write( buf, d); + } catch ( Exception & e ) { + sinks[u]->close(); + detach( sinks[u].get() ); + + reportEvent( 4, + "Connector :: transfer, sink removed, remaining", + numSinks); + + if ( numSinks == 0 ) { + reportEvent( 4, + "Connector :: transfer, no more sinks"); + delete[] buf; + return b; + } + // with the call to detach, numSinks gets 1 lower, + // and the next sink comes to sinks[u] + --u; + } + } + } + + b += d; + } else { + reportEvent( 3, "Connector :: transfer, can't read"); + break; + } + } + + delete[] buf; + return b; +} + + +/*------------------------------------------------------------------------------ + * Signal to each sink to cut what they've done so far, and start anew. + *----------------------------------------------------------------------------*/ +void +Connector :: cut ( void ) throw () +{ + unsigned int u; + + for ( u = 0; u < numSinks; ++u ) { + if ( sinks[u]->isOpen() ) { + sinks[u]->cut(); + } + } +} + + +/*------------------------------------------------------------------------------ + * Close the source and all the sinks if needed + *----------------------------------------------------------------------------*/ +void +Connector :: close ( void ) throw ( Exception ) +{ + unsigned int u; + + source->close(); + for ( u = 0; u < numSinks; ++u ) { + sinks[u]->close(); + } +} + + diff --git a/darkice/tags/darkice-1_3/src/Connector.h b/darkice/tags/darkice-1_3/src/Connector.h new file mode 100644 index 0000000..5183a38 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/Connector.h @@ -0,0 +1,264 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : Connector.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef CONNECTOR_H +#define CONNECTOR_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Referable.h" +#include "Ref.h" +#include "Reporter.h" +#include "Source.h" +#include "Sink.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * Connects a source to one or more sinks. + * + * @author $Author$ + * @version $Revision$ + */ +class Connector : public virtual Referable, public virtual Reporter +{ + private: + + /** + * Initialize the object. + * + * @param source the source to read from. + * @exception Exception + */ + void + init ( Source * source ) throw ( Exception ); + + /** + * De-initialize the object. + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + protected: + + /** + * The source to read from. + */ + Ref source; + + /** + * The sinks to connect the source to. + */ + Ref * sinks; + + /** + * Total number of sinks. + */ + unsigned int numSinks; + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + Connector ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Detach an already attached Sink from the Source of this Connector. + * + * @param sink the Sink to detach. + * @return true if the detachment was successful, false otherwise. + * @exception Exception + */ + virtual bool + detach ( Sink * sink ) throw ( Exception ); + + + public: + + /** + * Constructor based on a Source. + * + * @param source the source to connect to the sinks. + * @exception Exception + */ + inline + Connector ( Source * source ) throw ( Exception ) + { + init( source); + } + + /** + * Constructor based on a Source and a Sink. + * + * @param source the source to connect to the sinks. + * @param sink a sink to connect to the source. + * @exception Exception + */ + inline + Connector ( Source * source, + Sink * sink ) throw ( Exception ) + { + init( source); + attach( sink); + } + + /** + * Copy constructor. + * + * @param connector the object to copy. + * @exception Exception + */ + Connector ( const Connector & connector ) throw ( Exception ); + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~Connector( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param connector the object to assign to this one. + * @return a reference to this object. + * @exception Exception + */ + virtual Connector & + operator= ( const Connector & connector ) throw ( Exception ); + + /** + * Get the number of Sinks in the Connector. + * + * @return the number of Sinks in the Connector. + * @exception Exception + */ + inline virtual unsigned int + getNumSinks ( void ) const throw () + { + return numSinks; + } + + /** + * Attach a Sink to the Source of this Connector. + * + * @param sink the Sink to attach. + * @exception Exception + */ + virtual void + attach ( Sink * sink ) throw ( Exception ); + + /** + * Open the connector. Opens the Source and the Sinks if necessary. + * + * @return true if opening was successful, false otherwise. + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Transfer a given amount of data from the Source to all the + * Sinks attached. + * If an attached Sink closes or encounteres an error during the + * process, it is detached and the function carries on with the + * rest of the Sinks. If no Sinks remain, or an error is encountered + * with the Source, the function returns prematurely. + * + * @param bytes the amount of data to transfer, in bytes. + * If 0, transfer forever. + * @param bufSize the size of the buffer to use for transfering. + * This amount of data is read from the Source and + * written to each Sink on each turn. + * @param sec the number of seconds to wait for the Source to have + * data available in each turn, and the number of seconds + * to wait for the Sinks to accept data. + * @param usec the number of micro seconds to wait for the Source to + * have data available in each turn, and the number of + * micro seconds to wait for the Sinks to accept data. + * @return the number of bytes read from the Source. + * @exception Exception + */ + virtual unsigned int + transfer ( unsigned long bytes, + unsigned int bufSize, + unsigned int sec, + unsigned int usec ) throw ( Exception ); + + /** + * Signal to each sink we have that they need to cut what they are + * doing, and start again. For FileSinks, this usually means to + * save the archive file recorded so far, and start a new archive + * file. + */ + virtual void + cut ( void ) throw (); + + /** + * Close the Connector. The Source and all Sinks are closed. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* CONNECTOR_H */ + diff --git a/darkice/tags/darkice-1_3/src/DarkIce.cpp b/darkice/tags/darkice-1_3/src/DarkIce.cpp new file mode 100644 index 0000000..c850edd --- /dev/null +++ b/darkice/tags/darkice-1_3/src/DarkIce.cpp @@ -0,0 +1,1320 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : DarkIce.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STDLIB_H +#include +#else +#error need stdlib.h +#endif + +#ifdef HAVE_UNISTD_H +#include +#else +#error need unistd.h +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#else +#error need sys/types.h +#endif + +#ifdef HAVE_SYS_WAIT_H +#include +#else +#error need sys/wait.h +#endif + +#ifdef HAVE_ERRNO_H +#include +#else +#error need errno.h +#endif + +#ifdef HAVE_SCHED_H +#include +#else +#error need sched.h +#endif + + + +#include "Util.h" +#include "IceCast.h" +#include "IceCast2.h" +#include "ShoutCast.h" +#include "FileCast.h" +#include "MultiThreadedConnector.h" +#include "DarkIce.h" + +#ifdef HAVE_LAME_LIB +#include "LameLibEncoder.h" +#endif + +#ifdef HAVE_TWOLAME_LIB +#include "TwoLameLibEncoder.h" +#endif + +#ifdef HAVE_VORBIS_LIB +#include "VorbisLibEncoder.h" +#endif + +#ifdef HAVE_OPUS_LIB +#include "OpusLibEncoder.h" +#endif + +#ifdef HAVE_FAAC_LIB +#include "FaacEncoder.h" +#endif + +#ifdef HAVE_AACPLUS_LIB +#include "aacPlusEncoder.h" +#endif + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/*------------------------------------------------------------------------------ + * Make sure wait-related stuff is what we expect + *----------------------------------------------------------------------------*/ +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +DarkIce :: init ( const Config & config ) throw ( Exception ) +{ + unsigned int bufferSecs; + const ConfigSection * cs; + const char * str; + unsigned int sampleRate; + unsigned int bitsPerSample; + unsigned int channel; + bool reconnect; + const char * device; + const char * jackClientName; + const char * paSourceName; + + // the [general] section + if ( !(cs = config.get( "general")) ) { + throw Exception( __FILE__, __LINE__, "no section [general] in config"); + } + str = cs->getForSure( "duration", " missing in section [general]"); + duration = Util::strToL( str); + str = cs->getForSure( "bufferSecs", " missing in section [general]"); + bufferSecs = Util::strToL( str); + if (bufferSecs == 0) { + throw Exception(__FILE__, __LINE__, + "setting bufferSecs to 0 not supported"); + } + str = cs->get( "reconnect"); + reconnect = str ? (Util::strEq( str, "yes") ? true : false) : true; + + // real-time scheduling is enabled by default + str = cs->get( "realtime" ); + enableRealTime = str ? (Util::strEq( str, "yes") ? true : false) : true; + + // get realtime scheduling priority. If unspecified, set it to 4. + // Why 4? jackd's default priority is 10, jackd client threads run + // at 5, so make the encoder thread use 4. jackd automatically sets + // the process callback priority to the right value, so all we have + // to care about is the encoder priority. + str = cs->get( "rtprio" ); + realTimeSchedPriority = (str != NULL) ? Util::strToL( str ) : 4; + + // the [input] section + if ( !(cs = config.get( "input")) ) { + throw Exception( __FILE__, __LINE__, "no section [input] in config"); + } + + str = cs->getForSure( "sampleRate", " missing in section [input]"); + sampleRate = Util::strToL( str); + str = cs->getForSure( "bitsPerSample", " missing in section [input]"); + bitsPerSample = Util::strToL( str); + str = cs->getForSure( "channel", " missing in section [input]"); + channel = Util::strToL( str); + device = cs->getForSure( "device", " missing in section [input]"); + jackClientName = cs->get ( "jackClientName"); + paSourceName = cs->get ( "paSourceName"); + + dsp = AudioSource::createDspSource( device, + jackClientName, + paSourceName, + sampleRate, + bitsPerSample, + channel ); + encConnector = new MultiThreadedConnector( dsp.get(), reconnect ); + + noAudioOuts = 0; + configIceCast( config, bufferSecs); + configIceCast2( config, bufferSecs); + configShoutCast( config, bufferSecs); + configFileCast( config); +} + + +/*------------------------------------------------------------------------------ + * Look for the IceCast stream outputs in the config file + *----------------------------------------------------------------------------*/ +void +DarkIce :: configIceCast ( const Config & config, + unsigned int bufferSecs ) + throw ( Exception ) +{ + // look for IceCast encoder output streams, + // sections [icecast-0], [icecast-1], ... + char stream[] = "icecast- "; + size_t streamLen = Util::strLen( stream); + unsigned int u; + + for ( u = noAudioOuts; u < maxOutput; ++u ) { + const ConfigSection * cs; + + // ugly hack to change the section name to "stream0", "stream1", etc. + stream[streamLen-1] = '0' + (u - noAudioOuts); + + if ( !(cs = config.get( stream)) ) { + break; + } + +#if !defined HAVE_LAME_LIB && !defined HAVE_TWOLAME_LIB + throw Exception( __FILE__, __LINE__, + "DarkIce not compiled with lame or twolame support, " + "thus can't connect to IceCast 1.x, stream: ", + stream); +#else + + const char * str; + + unsigned int sampleRate = 0; + unsigned int channel = 0; + AudioEncoder::BitrateMode bitrateMode; + unsigned int bitrate = 0; + double quality = 0.0; + const char * server = 0; + unsigned int port = 0; + const char * password = 0; + const char * mountPoint = 0; + const char * remoteDumpFile = 0; + const char * name = 0; + const char * description = 0; + const char * url = 0; + const char * genre = 0; + bool isPublic = false; + int lowpass = 0; + int highpass = 0; + const char * localDumpName = 0; + FileSink * localDumpFile = 0; + bool fileAddDate = false; + const char * fileDateFormat = 0; + BufferedSink * audioOut = 0; + int bufferSize = 0; + + str = cs->get( "sampleRate"); + sampleRate = str ? Util::strToL( str) : dsp->getSampleRate(); + str = cs->get( "channel"); + channel = str ? Util::strToL( str) : dsp->getChannel(); + + str = cs->get( "bitrate"); + bitrate = str ? Util::strToL( str) : 0; + str = cs->get( "quality"); + quality = str ? Util::strToD( str) : 0.0; + + str = cs->getForSure( "bitrateMode", + " not specified in section ", + stream); + if ( Util::strEq( str, "cbr") ) { + bitrateMode = AudioEncoder::cbr; + + if ( bitrate == 0 ) { + throw Exception( __FILE__, __LINE__, + "bitrate not specified for CBR encoding"); + } + if ( cs->get( "quality" ) == 0 ) { + throw Exception( __FILE__, __LINE__, + "quality not specified for CBR encoding"); + } + } else if ( Util::strEq( str, "abr") ) { + bitrateMode = AudioEncoder::abr; + + if ( bitrate == 0 ) { + throw Exception( __FILE__, __LINE__, + "bitrate not specified for ABR encoding"); + } + } else if ( Util::strEq( str, "vbr") ) { + bitrateMode = AudioEncoder::vbr; + + if ( cs->get( "quality" ) == 0 ) { + throw Exception( __FILE__, __LINE__, + "quality not specified for VBR encoding"); + } + } else { + throw Exception( __FILE__, __LINE__, + "invalid bitrate mode: ", str); + } + + + + server = cs->getForSure( "server", " missing in section ", stream); + str = cs->getForSure( "port", " missing in section ", stream); + port = Util::strToL( str); + password = cs->getForSure("password"," missing in section ",stream); + mountPoint = cs->getForSure( "mountPoint", + " missing in section ", + stream); + remoteDumpFile = cs->get( "remoteDumpFile"); + name = cs->get( "name"); + description = cs->get("description"); + url = cs->get( "url"); + genre = cs->get( "genre"); + str = cs->get( "public"); + isPublic = str ? (Util::strEq( str, "yes") ? true : false) : false; + str = cs->get( "lowpass"); + lowpass = str ? Util::strToL( str) : 0; + str = cs->get( "highpass"); + highpass = str ? Util::strToL( str) : 0; + str = cs->get("fileAddDate"); + fileAddDate = str ? (Util::strEq( str, "yes") ? true : false) : false; + fileDateFormat = cs->get("fileDateFormat"); + + bufferSize = dsp->getSampleSize() * dsp->getSampleRate() * bufferSecs; + reportEvent( 3, "buffer size: ", bufferSize); + + localDumpName = cs->get( "localDumpFile"); + + // go on and create the things + + // check for and create the local dump file if needed + if ( localDumpName != 0 ) { + if ( fileAddDate ) { + if (fileDateFormat == 0) { + localDumpName = Util::fileAddDate(localDumpName); + } + else { + localDumpName = Util::fileAddDate( localDumpName, + fileDateFormat ); + } + } + + localDumpFile = new FileSink( stream, localDumpName); + if ( !localDumpFile->exists() ) { + if ( !localDumpFile->create() ) { + reportEvent( 1, "can't create local dump file", + localDumpName); + localDumpFile = 0; + } + } + if ( fileAddDate ) { + delete[] localDumpName; + } + } + // streaming related stuff + audioOuts[u].socket = new TcpSocket( server, port); + audioOuts[u].server = new IceCast( audioOuts[u].socket.get(), + password, + mountPoint, + bitrate, + name, + description, + url, + genre, + isPublic, + remoteDumpFile, + localDumpFile); + + str = cs->getForSure( "format", " missing in section ", stream); + + if (!Util::strEq(str, "mp3") && !Util::strEq(str, "mp2")) { + throw Exception( __FILE__, __LINE__, + "unsupported stream format: ", str); + + } + + // augment audio outs with a buffer when used from encoder + audioOut = new BufferedSink( audioOuts[u].server.get(), + bufferSize, 1); + +#ifdef HAVE_LAME_LIB + if ( Util::strEq( str, "mp3") ) { + audioOuts[u].encoder = new LameLibEncoder( audioOut, + dsp.get(), + bitrateMode, + bitrate, + quality, + sampleRate, + channel, + lowpass, + highpass ); + } +#endif +#ifdef HAVE_TWOLAME_LIB + if ( Util::strEq( str, "mp2") ) { + audioOuts[u].encoder = new TwoLameLibEncoder( + audioOut, + dsp.get(), + bitrateMode, + bitrate, + sampleRate, + channel ); + } +#endif + + encConnector->attach( audioOuts[u].encoder.get()); +#endif // HAVE_LAME_LIB || HAVE_TWOLAME_LIB + } + + noAudioOuts += u; +} + + +/*------------------------------------------------------------------------------ + * Look for the IceCast2 stream outputs in the config file + *----------------------------------------------------------------------------*/ +void +DarkIce :: configIceCast2 ( const Config & config, + unsigned int bufferSecs ) + throw ( Exception ) +{ + // look for IceCast2 encoder output streams, + // sections [icecast2-0], [icecast2-1], ... + char stream[] = "icecast2- "; + size_t streamLen = Util::strLen( stream); + unsigned int u; + + for ( u = noAudioOuts; u < maxOutput; ++u ) { + const ConfigSection * cs; + + // ugly hack to change the section name to "stream0", "stream1", etc. + stream[streamLen-1] = '0' + (u - noAudioOuts); + + if ( !(cs = config.get( stream)) ) { + break; + } + + const char * str; + + IceCast2::StreamFormat format; + unsigned int sampleRate = 0; + unsigned int channel = 0; + AudioEncoder::BitrateMode bitrateMode; + unsigned int bitrate = 0; + unsigned int maxBitrate = 0; + double quality = 0.0; + const char * server = 0; + unsigned int port = 0; + const char * password = 0; + const char * mountPoint = 0; + const char * name = 0; + const char * description = 0; + const char * url = 0; + const char * genre = 0; + bool isPublic = false; + int lowpass = 0; + int highpass = 0; + const char * localDumpName = 0; + FileSink * localDumpFile = 0; + bool fileAddDate = false; + const char * fileDateFormat = 0; + BufferedSink * audioOut = 0; + int bufferSize = 0; + + str = cs->getForSure( "format", " missing in section ", stream); + if ( Util::strEq( str, "vorbis") ) { + format = IceCast2::oggVorbis; + } else if ( Util::strEq( str, "opus") ) { + format = IceCast2::oggOpus; + } else if ( Util::strEq( str, "mp3") ) { + format = IceCast2::mp3; + } else if ( Util::strEq( str, "mp2") ) { + format = IceCast2::mp2; + } else if ( Util::strEq( str, "aac") ) { + format = IceCast2::aac; + } else if ( Util::strEq( str, "aacp") ) { + format = IceCast2::aacp; + } else { + throw Exception( __FILE__, __LINE__, + "unsupported stream format: ", str); + } + + str = cs->get( "sampleRate"); + sampleRate = str ? Util::strToL( str) : dsp->getSampleRate(); + str = cs->get( "channel"); + channel = str ? Util::strToL( str) : dsp->getChannel(); + + // determine fixed bitrate or variable bitrate quality + str = cs->get( "bitrate"); + bitrate = str ? Util::strToL( str) : 0; + str = cs->get( "maxBitrate"); + maxBitrate = str ? Util::strToL( str) : 0; + str = cs->get( "quality"); + quality = str ? Util::strToD( str) : 0.0; + + str = cs->getForSure( "bitrateMode", + " not specified in section ", + stream); + if ( Util::strEq( str, "cbr") ) { + bitrateMode = AudioEncoder::cbr; + + if ( bitrate == 0 ) { + throw Exception( __FILE__, __LINE__, + "bitrate not specified for CBR encoding"); + } + } else if ( Util::strEq( str, "abr") ) { + bitrateMode = AudioEncoder::abr; + + if ( bitrate == 0 ) { + throw Exception( __FILE__, __LINE__, + "bitrate not specified for ABR encoding"); + } + } else if ( Util::strEq( str, "vbr") ) { + bitrateMode = AudioEncoder::vbr; + + if ( cs->get( "quality" ) == 0 ) { + throw Exception( __FILE__, __LINE__, + "quality not specified for VBR encoding"); + } + } else { + throw Exception( __FILE__, __LINE__, + "invalid bitrate mode: ", str); + } + + server = cs->getForSure( "server", " missing in section ", stream); + str = cs->getForSure( "port", " missing in section ", stream); + port = Util::strToL( str); + password = cs->getForSure("password"," missing in section ",stream); + mountPoint = cs->getForSure( "mountPoint", + " missing in section ", + stream); + name = cs->get( "name"); + description = cs->get( "description"); + url = cs->get( "url"); + genre = cs->get( "genre"); + str = cs->get( "public"); + isPublic = str ? (Util::strEq( str, "yes") ? true : false) : false; + str = cs->get( "lowpass"); + lowpass = str ? Util::strToL( str) : 0; + str = cs->get( "highpass"); + highpass = str ? Util::strToL( str) : 0; + str = cs->get( "fileAddDate"); + fileAddDate = str ? (Util::strEq( str, "yes") ? true : false) : false; + fileDateFormat = cs->get( "fileDateFormat"); + + bufferSize = dsp->getSampleSize() * dsp->getSampleRate() * bufferSecs; + reportEvent( 3, "buffer size: ", bufferSize); + + localDumpName = cs->get( "localDumpFile"); + + // go on and create the things + + // check for and create the local dump file if needed + if ( localDumpName != 0 ) { + if ( fileAddDate ) { + if (fileDateFormat == 0) { + localDumpName = Util::fileAddDate(localDumpName); + } + else { + localDumpName = Util::fileAddDate( localDumpName, + fileDateFormat ); + } + } + + localDumpFile = new FileSink( stream, localDumpName); + if ( !localDumpFile->exists() ) { + if ( !localDumpFile->create() ) { + reportEvent( 1, "can't create local dump file", + localDumpName); + localDumpFile = 0; + } + } + if ( fileAddDate ) { + delete[] localDumpName; + } + } + + // streaming related stuff + audioOuts[u].socket = new TcpSocket( server, port); + audioOuts[u].server = new IceCast2( audioOuts[u].socket.get(), + password, + mountPoint, + format, + bitrate, + name, + description, + url, + genre, + isPublic, + localDumpFile); + + audioOut = new BufferedSink( audioOuts[u].server.get(), + bufferSize, 1); + + switch ( format ) { + case IceCast2::mp3: +#ifndef HAVE_LAME_LIB + throw Exception( __FILE__, __LINE__, + "DarkIce not compiled with lame support, " + "thus can't create mp3 stream: ", + stream); +#else + audioOuts[u].encoder = new LameLibEncoder( + audioOut, + dsp.get(), + bitrateMode, + bitrate, + quality, + sampleRate, + channel, + lowpass, + highpass ); + +#endif // HAVE_LAME_LIB + break; + + + case IceCast2::oggVorbis: +#ifndef HAVE_VORBIS_LIB + throw Exception( __FILE__, __LINE__, + "DarkIce not compiled with Ogg Vorbis support, " + "thus can't Ogg Vorbis stream: ", + stream); +#else + + audioOuts[u].encoder = new VorbisLibEncoder( + audioOut, + dsp.get(), + bitrateMode, + bitrate, + quality, + sampleRate, + dsp->getChannel(), + maxBitrate); + +#endif // HAVE_VORBIS_LIB + break; + + case IceCast2::oggOpus: +#ifndef HAVE_OPUS_LIB + throw Exception( __FILE__, __LINE__, + "DarkIce not compiled with Ogg Opus support, " + "thus can't Ogg Opus stream: ", + stream); +#else + + audioOuts[u].encoder = new OpusLibEncoder( + audioOut, + dsp.get(), + bitrateMode, + bitrate, + quality, + sampleRate, + dsp->getChannel(), + maxBitrate); + +#endif // HAVE_OPUS_LIB + break; + + case IceCast2::mp2: +#ifndef HAVE_TWOLAME_LIB + throw Exception( __FILE__, __LINE__, + "DarkIce not compiled with TwoLame support, " + "thus can't create mp2 stream: ", + stream); +#else + audioOuts[u].encoder = new TwoLameLibEncoder( + audioOut, + dsp.get(), + bitrateMode, + bitrate, + sampleRate, + channel ); + +#endif // HAVE_TWOLAME_LIB + break; + + + case IceCast2::aac: +#ifndef HAVE_FAAC_LIB + throw Exception( __FILE__, __LINE__, + "DarkIce not compiled with AAC support, " + "thus can't aac stream: ", + stream); +#else + audioOuts[u].encoder = new FaacEncoder( + audioOut, + dsp.get(), + bitrateMode, + bitrate, + quality, + sampleRate, + dsp->getChannel()); + +#endif // HAVE_FAAC_LIB + break; + + case IceCast2::aacp: +#ifndef HAVE_AACPLUS_LIB + throw Exception( __FILE__, __LINE__, + "DarkIce not compiled with AAC+ support, " + "thus can't aacp stream: ", + stream); +#else + audioOuts[u].encoder = new aacPlusEncoder( + audioOut, + dsp.get(), + bitrateMode, + bitrate, + quality, + sampleRate, + channel ); + +#endif // HAVE_AACPLUS_LIB + break; + + default: + throw Exception( __FILE__, __LINE__, + "Illegal stream format: ", format); + } + + encConnector->attach( audioOuts[u].encoder.get()); + } + + noAudioOuts += u; +} + + +/*------------------------------------------------------------------------------ + * Look for the ShoutCast stream outputs in the config file + *----------------------------------------------------------------------------*/ +void +DarkIce :: configShoutCast ( const Config & config, + unsigned int bufferSecs ) + throw ( Exception ) +{ + // look for Shoutcast encoder output streams, + // sections [shoutcast-0], [shoutcast-1], ... + char stream[] = "shoutcast- "; + size_t streamLen = Util::strLen( stream); + unsigned int u; + + for ( u = noAudioOuts; u < maxOutput; ++u ) { + const ConfigSection * cs; + + // ugly hack to change the section name to "stream0", "stream1", etc. + stream[streamLen-1] = '0' + (u - noAudioOuts); + + if ( !(cs = config.get( stream)) ) { + break; + } + +#ifndef HAVE_LAME_LIB + throw Exception( __FILE__, __LINE__, + "DarkIce not compiled with lame support, " + "thus can't connect to ShoutCast, stream: ", + stream); +#else + + const char * str; + + unsigned int sampleRate = 0; + unsigned int channel = 0; + AudioEncoder::BitrateMode bitrateMode; + unsigned int bitrate = 0; + double quality = 0.0; + const char * server = 0; + unsigned int port = 0; + const char * password = 0; + const char * name = 0; + const char * url = 0; + const char * genre = 0; + bool isPublic = false; + const char * mountPoint = 0; + int lowpass = 0; + int highpass = 0; + const char * irc = 0; + const char * aim = 0; + const char * icq = 0; + const char * localDumpName = 0; + FileSink * localDumpFile = 0; + bool fileAddDate = false; + const char * fileDateFormat = 0; + BufferedSink * audioOut = 0; + int bufferSize = 0; + + str = cs->get( "sampleRate"); + sampleRate = str ? Util::strToL( str) : dsp->getSampleRate(); + str = cs->get( "channel"); + channel = str ? Util::strToL( str) : dsp->getChannel(); + + str = cs->get( "bitrate"); + bitrate = str ? Util::strToL( str) : 0; + str = cs->get( "quality"); + quality = str ? Util::strToD( str) : 0.0; + + str = cs->getForSure( "bitrateMode", + " not specified in section ", + stream); + if ( Util::strEq( str, "cbr") ) { + bitrateMode = AudioEncoder::cbr; + + if ( bitrate == 0 ) { + throw Exception( __FILE__, __LINE__, + "bitrate not specified for CBR encoding"); + } + if ( cs->get( "quality" ) == 0 ) { + throw Exception( __FILE__, __LINE__, + "quality not specified for CBR encoding"); + } + } else if ( Util::strEq( str, "abr") ) { + bitrateMode = AudioEncoder::abr; + + if ( bitrate == 0 ) { + throw Exception( __FILE__, __LINE__, + "bitrate not specified for ABR encoding"); + } + } else if ( Util::strEq( str, "vbr") ) { + bitrateMode = AudioEncoder::vbr; + + if ( cs->get( "quality" ) == 0 ) { + throw Exception( __FILE__, __LINE__, + "quality not specified for VBR encoding"); + } + } else { + throw Exception( __FILE__, __LINE__, + "invalid bitrate mode: ", str); + } + + server = cs->getForSure( "server", " missing in section ", stream); + str = cs->getForSure( "port", " missing in section ", stream); + port = Util::strToL( str); + password = cs->getForSure("password"," missing in section ",stream); + name = cs->get( "name"); + mountPoint = cs->get( "mountPoint" ); + url = cs->get( "url"); + genre = cs->get( "genre"); + str = cs->get( "public"); + isPublic = str ? (Util::strEq( str, "yes") ? true : false) : false; + str = cs->get( "lowpass"); + lowpass = str ? Util::strToL( str) : 0; + str = cs->get( "highpass"); + highpass = str ? Util::strToL( str) : 0; + irc = cs->get( "irc"); + aim = cs->get( "aim"); + icq = cs->get( "icq"); + str = cs->get("fileAddDate"); + fileAddDate = str ? (Util::strEq( str, "yes") ? true : false) : false; + fileDateFormat = cs->get( "fileDateFormat"); + + bufferSize = dsp->getBitsPerSample() / 8 * dsp->getSampleRate() * dsp->getChannel() * bufferSecs; + reportEvent( 3, "buffer size: ", bufferSize); + + localDumpName = cs->get( "localDumpFile"); + + // go on and create the things + + // check for and create the local dump file if needed + if ( localDumpName != 0 ) { + if ( fileAddDate ) { + if (fileDateFormat == 0) { + localDumpName = Util::fileAddDate(localDumpName); + } + else { + localDumpName = Util::fileAddDate( localDumpName, + fileDateFormat ); + } + } + + localDumpFile = new FileSink( stream, localDumpName); + if ( !localDumpFile->exists() ) { + if ( !localDumpFile->create() ) { + reportEvent( 1, "can't create local dump file", + localDumpName); + localDumpFile = 0; + } + } + if ( fileAddDate ) { + delete[] localDumpName; + } + } + + // streaming related stuff + audioOuts[u].socket = new TcpSocket( server, port); + audioOuts[u].server = new ShoutCast( audioOuts[u].socket.get(), + password, + mountPoint, + bitrate, + name, + url, + genre, + isPublic, + irc, + aim, + icq, + localDumpFile); + + + audioOut = new BufferedSink(audioOuts[u].socket.get(), bufferSize, 1); + audioOuts[u].encoder = new LameLibEncoder( + audioOut, + dsp.get(), + bitrateMode, + bitrate, + quality, + sampleRate, + channel, + lowpass, + highpass ); + + encConnector->attach( audioOuts[u].encoder.get()); +#endif // HAVE_LAME_LIB + } + + noAudioOuts += u; +} + + +/*------------------------------------------------------------------------------ + * Look for the FileCast stream outputs in the config file + *----------------------------------------------------------------------------*/ +void +DarkIce :: configFileCast ( const Config & config ) + throw ( Exception ) +{ + // look for FileCast encoder output streams, + // sections [file-0], [file-1], ... + char stream[] = "file- "; + size_t streamLen = Util::strLen( stream); + unsigned int u; + + for ( u = noAudioOuts; u < maxOutput; ++u ) { + const ConfigSection * cs; + + // ugly hack to change the section name to "stream0", "stream1", etc. + stream[streamLen-1] = '0' + (u - noAudioOuts); + + if ( !(cs = config.get( stream)) ) { + break; + } + + const char * str; + + const char * format = 0; + AudioEncoder::BitrateMode bitrateMode; + unsigned int bitrate = 0; + double quality = 0.0; + const char * targetFileName = 0; + unsigned int sampleRate = 0; + int lowpass = 0; + int highpass = 0; + bool fileAddDate = false; + const char * fileDateFormat = 0; + + format = cs->getForSure( "format", " missing in section ", stream); + if ( !Util::strEq( format, "vorbis") + && !Util::strEq( format, "opus") + && !Util::strEq( format, "mp3") + && !Util::strEq( format, "mp2") + && !Util::strEq( format, "aac") + && !Util::strEq( format, "aacp") ) { + throw Exception( __FILE__, __LINE__, + "unsupported stream format: ", format); + } + + str = cs->getForSure("bitrate", " missing in section ", stream); + bitrate = Util::strToL( str); + targetFileName = cs->getForSure( "fileName", + " missing in section ", + stream); + + str = cs->get( "fileAddDate"); + fileAddDate = str ? (Util::strEq( str, "yes") ? true : false) : false; + fileDateFormat = cs->get( "fileDateFormat"); + + str = cs->get( "sampleRate"); + sampleRate = str ? Util::strToL( str) : dsp->getSampleRate(); + + str = cs->get( "bitrate"); + bitrate = str ? Util::strToL( str) : 0; + str = cs->get( "quality"); + quality = str ? Util::strToD( str) : 0.0; + + str = cs->getForSure( "bitrateMode", + " not specified in section ", + stream); + if ( Util::strEq( str, "cbr") ) { + bitrateMode = AudioEncoder::cbr; + + if ( bitrate == 0 ) { + throw Exception( __FILE__, __LINE__, + "bitrate not specified for CBR encoding"); + } + } else if ( Util::strEq( str, "abr") ) { + bitrateMode = AudioEncoder::abr; + + if ( bitrate == 0 ) { + throw Exception( __FILE__, __LINE__, + "bitrate not specified for ABR encoding"); + } + } else if ( Util::strEq( str, "vbr") ) { + bitrateMode = AudioEncoder::vbr; + + if ( cs->get( "quality" ) == 0 ) { + throw Exception( __FILE__, __LINE__, + "quality not specified for VBR encoding"); + } + } else { + throw Exception( __FILE__, __LINE__, + "invalid bitrate mode: ", str); + } + + if (Util::strEq(format, "aac") && bitrateMode != AudioEncoder::abr) { + throw Exception(__FILE__, __LINE__, + "currently the AAC format only supports " + "average bitrate mode"); + } + + if (Util::strEq(format, "aacp") && bitrateMode != AudioEncoder::cbr) { + throw Exception(__FILE__, __LINE__, + "currently the AAC+ format only supports " + "constant bitrate mode"); + } + + str = cs->get( "lowpass"); + lowpass = str ? Util::strToL( str) : 0; + str = cs->get( "highpass"); + highpass = str ? Util::strToL( str) : 0; + + // go on and create the things + + // the underlying file + if ( fileAddDate ) { + if (fileDateFormat == 0) { + targetFileName = Util::fileAddDate( targetFileName); + } + else { + targetFileName = Util::fileAddDate( targetFileName, + fileDateFormat ); + } + } + + FileSink * targetFile = new FileSink( stream, targetFileName); + if ( !targetFile->exists() ) { + if ( !targetFile->create() ) { + throw Exception( __FILE__, __LINE__, + "can't create output file", targetFileName); + } + } + + // streaming related stuff + audioOuts[u].socket = 0; + audioOuts[u].server = new FileCast( targetFile ); + + if ( Util::strEq( format, "mp3") ) { +#ifndef HAVE_LAME_LIB + throw Exception( __FILE__, __LINE__, + "DarkIce not compiled with lame support, " + "thus can't create mp3 stream: ", + stream); +#else + audioOuts[u].encoder = new LameLibEncoder( + audioOuts[u].server.get(), + dsp.get(), + bitrateMode, + bitrate, + quality, + sampleRate, + dsp->getChannel(), + lowpass, + highpass ); +#endif // HAVE_TWOLAME_LIB + } else if ( Util::strEq( format, "mp2") ) { +#ifndef HAVE_TWOLAME_LIB + throw Exception( __FILE__, __LINE__, + "DarkIce not compiled with TwoLAME support, " + "thus can't create MPEG Audio Layer 2 stream: ", + stream); +#else + audioOuts[u].encoder = new TwoLameLibEncoder( + audioOuts[u].server.get(), + dsp.get(), + bitrateMode, + bitrate, + sampleRate, + dsp->getChannel() ); +#endif // HAVE_TWOLAME_LIB + } else if ( Util::strEq( format, "vorbis") ) { +#ifndef HAVE_VORBIS_LIB + throw Exception( __FILE__, __LINE__, + "DarkIce not compiled with Ogg Vorbis support, " + "thus can't Ogg Vorbis stream: ", + stream); +#else + audioOuts[u].encoder = new VorbisLibEncoder( + audioOuts[u].server.get(), + dsp.get(), + bitrateMode, + bitrate, + quality, + dsp->getSampleRate(), + dsp->getChannel() ); +#endif // HAVE_VORBIS_LIB + } else if ( Util::strEq( format, "opus") ) { +#ifndef HAVE_OPUS_LIB + throw Exception( __FILE__, __LINE__, + "DarkIce not compiled with Ogg Opus support, " + "thus can't Ogg Opus stream: ", + stream); +#else + audioOuts[u].encoder = new OpusLibEncoder( + audioOuts[u].server.get(), + dsp.get(), + bitrateMode, + bitrate, + quality, + dsp->getSampleRate(), + dsp->getChannel() ); +#endif // HAVE_OPUS_LIB + } else if ( Util::strEq( format, "aac") ) { +#ifndef HAVE_FAAC_LIB + throw Exception( __FILE__, __LINE__, + "DarkIce not compiled with AAC support, " + "thus can't aac stream: ", + stream); +#else + audioOuts[u].encoder = new FaacEncoder( + audioOuts[u].server.get(), + dsp.get(), + bitrateMode, + bitrate, + quality, + sampleRate, + dsp->getChannel()); +#endif // HAVE_FAAC_LIB + } else if ( Util::strEq( format, "aacp") ) { +#ifndef HAVE_AACPLUS_LIB + throw Exception( __FILE__, __LINE__, + "DarkIce not compiled with AAC+ support, " + "thus can't aacplus stream: ", + stream); +#else + audioOuts[u].encoder = new aacPlusEncoder( + audioOuts[u].server.get(), + dsp.get(), + bitrateMode, + bitrate, + quality, + sampleRate, + dsp->getChannel()); +#endif // HAVE_AACPLUS_LIB + } else { + throw Exception( __FILE__, __LINE__, + "Illegal stream format: ", format); + } + + encConnector->attach( audioOuts[u].encoder.get()); + } + + noAudioOuts += u; +} + + +/*------------------------------------------------------------------------------ + * Set POSIX real-time scheduling + *----------------------------------------------------------------------------*/ +void +DarkIce :: setRealTimeScheduling ( void ) throw ( Exception ) +{ +// Only if the OS has the POSIX real-time scheduling functions implemented. +#if defined( HAVE_SCHED_GETSCHEDULER ) && defined( HAVE_SCHED_GETPARAM ) + int high_priority; + struct sched_param param; + + /* store the old scheduling parameters */ + if ( (origSchedPolicy = sched_getscheduler(0)) == -1 ) { + throw Exception( __FILE__, __LINE__, "sched_getscheduler", errno); + } + + if ( sched_getparam( 0, ¶m) == -1 ) { + throw Exception( __FILE__, __LINE__, "sched_getparam", errno); + } + origSchedPriority = param.sched_priority; + + /* set SCHED_FIFO with max - 1 priority or user configured value */ + if ( (high_priority = sched_get_priority_max(SCHED_FIFO)) == -1 ) { + throw Exception(__FILE__,__LINE__,"sched_get_priority_max",errno); + } + reportEvent( 8, "scheduler high priority", high_priority); + + if (realTimeSchedPriority > high_priority) { + param.sched_priority = high_priority - 1; + } else { + param.sched_priority = realTimeSchedPriority; + } + + if ( sched_setscheduler( 0, SCHED_FIFO, ¶m) == -1 ) { + reportEvent( 1, + "Could not set POSIX real-time scheduling, " + "this may cause recording skips.\n" + "Try to run darkice as the super-user."); + } else { + /* ask the new priortiy and report it */ + if ( sched_getparam( 0, ¶m) == -1 ) { + throw Exception( __FILE__, __LINE__, "sched_getparam", errno); + } + + reportEvent( 1, + "Using POSIX real-time scheduling, priority", + param.sched_priority ); + } +#else + reportEvent( 1, "POSIX scheduling not supported on this system, " + "this may cause recording skips"); +#endif // HAVE_SCHED_GETSCHEDULER && HAVE_SCHED_GETPARAM +} + + +/*------------------------------------------------------------------------------ + * Set the original scheduling of the process, the one prior to the + * setRealTimeScheduling call. + * WARNING: make sure you don't call this before setRealTimeScheduling!! + *----------------------------------------------------------------------------*/ +void +DarkIce :: setOriginalScheduling ( void ) throw ( Exception ) +{ +// Only if the OS has the POSIX real-time scheduling functions implemented. +#if defined( HAVE_SCHED_GETSCHEDULER ) && defined( HAVE_SCHED_GETPARAM ) + uid_t euid; + + euid = geteuid(); + + if ( euid == 0 ) { + struct sched_param param; + + if ( sched_getparam( 0, ¶m) == -1 ) { + throw Exception( __FILE__, __LINE__, "sched_getparam", errno); + } + + param.sched_priority = origSchedPriority; + + if ( sched_setscheduler( 0, origSchedPolicy, ¶m) == -1 ) { + throw Exception( __FILE__, __LINE__, "sched_setscheduler", errno); + } + + reportEvent( 5, "reverted to original scheduling"); + } +#endif // HAVE_SCHED_GETSCHEDULER && HAVE_SCHED_GETPARAM +} + + +/*------------------------------------------------------------------------------ + * Run the encoder + *----------------------------------------------------------------------------*/ +bool +DarkIce :: encode ( void ) throw ( Exception ) +{ + unsigned int len; + unsigned long bytes; + + if ( !encConnector->open() ) { + throw Exception( __FILE__, __LINE__, "can't open connector"); + } + + bytes = dsp->getSampleRate() * dsp->getSampleSize() * duration; + + len = encConnector->transfer( bytes, 4096, 1, 0 ); + + reportEvent( 1, len, "bytes transferred to the encoders"); + + encConnector->close(); + + return true; +} + + +/*------------------------------------------------------------------------------ + * Run + *----------------------------------------------------------------------------*/ +int +DarkIce :: run ( void ) throw ( Exception ) +{ + reportEvent( 3, "encoding"); + + if (enableRealTime) { + setRealTimeScheduling(); + } + encode(); + if (enableRealTime) { + setOriginalScheduling(); + } + reportEvent( 3, "encoding ends"); + + return 0; +} + + +/*------------------------------------------------------------------------------ + * Tell each sink to cut what they are doing, and start again. + *----------------------------------------------------------------------------*/ +void +DarkIce :: cut ( void ) throw () +{ + reportEvent( 5, "cutting"); + + encConnector->cut(); + + reportEvent( 5, "cutting ends"); +} diff --git a/darkice/tags/darkice-1_3/src/DarkIce.h b/darkice/tags/darkice-1_3/src/DarkIce.h new file mode 100644 index 0000000..49ae2a5 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/DarkIce.h @@ -0,0 +1,324 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : DarkIce.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef DARK_ICE_H +#define DARK_ICE_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_UNISTD_H +#include +#else +#error need unistd.h +#endif + +#include + +#include "Referable.h" +#include "Reporter.h" +#include "Exception.h" +#include "Ref.h" +#include "AudioSource.h" +#include "BufferedSink.h" +#include "Connector.h" +#include "AudioEncoder.h" +#include "TcpSocket.h" +#include "CastSink.h" +#include "DarkIceConfig.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * Program main object. + * + * @author $Author$ + * @version $Revision$ + */ +class DarkIce : public virtual Referable, public virtual Reporter +{ + private: + + /** + * The maximum number of supported outputs. This should be + * * + */ + static const unsigned int maxOutput = 4 * 7; + + /** + * Type describing each lame library output. + */ + typedef struct { + Ref encoder; + Ref socket; + Ref server; + } Output; + + /** + * The outputs. + */ + Output audioOuts[maxOutput]; + + /** + * Number of lame library outputs. + */ + unsigned int noAudioOuts; + + /** + * Duration of playing, in seconds. + */ + unsigned int duration; + + /** + * The dsp to record from. + */ + Ref dsp; + + /** + * The encoding Connector, connecting the dsp to the encoders. + */ + Ref encConnector; + + /** + * Should we turn real-time scheduling on ? + */ + int enableRealTime; + + /** + * Scheduling priority for the realtime threads + */ + int realTimeSchedPriority; + + /** + * Original scheduling policy + */ + int origSchedPolicy; + + /** + * Original scheduling priority + */ + int origSchedPriority; + + /** + * Initialize the object. + * + * @param config the config Object to read initialization + * information from. + * @exception Exception + */ + void + init ( const Config & config ) throw ( Exception ); + + /** + * Look for the icecast stream outputs from the config file. + * Called from init() + * + * @param config the config Object to read initialization + * information from. + * @param bufferSecs number of seconds to buffer audio for + * @exception Exception + */ + void + configIceCast ( const Config & config, + unsigned int bufferSecs ) throw ( Exception ); + + /** + * Look for the icecast2 stream outputs from the config file. + * Called from init() + * + * @param config the config Object to read initialization + * information from. + * @param bufferSecs number of seconds to buffer audio for + * @exception Exception + */ + void + configIceCast2 ( const Config & config, + unsigned int bufferSecs ) throw ( Exception ); + + /** + * Look for the shoutcast stream outputs from the config file. + * Called from init() + * + * @param config the config Object to read initialization + * information from. + * @param bufferSecs number of seconds to buffer audio for + * @exception Exception + */ + void + configShoutCast ( const Config & config, + unsigned int bufferSecs ) throw ( Exception ); + + /** + * Look for file outputs from the config file. + * Called from init() + * + * @param config the config Object to read initialization + * information from. + * @exception Exception + */ + void + configFileCast ( const Config & config ) + throw ( Exception ); + + /** + * Set POSIX real-time scheduling for the encoding process, + * if user permissions enable it. + * + * @exception Exception + */ + void + setRealTimeScheduling ( void ) throw ( Exception ); + + /** + * Set the scheduling that was before setting real-time scheduling. + * This function must be called _only_ after setRealTimeScheduling. + * + * @exception Exception + */ + void + setOriginalScheduling ( void ) throw ( Exception ); + + /** + * Start encoding. Spawns all encoders, opens the dsp and + * starts sending data to the encoders. + * + * @return if encoding was successful. + * @exception Exception + */ + bool + encode ( void ) throw ( Exception ); + + /** + * Start shouting. fork()-s a process for each output, reads + * the output of the encoders and sends them to an IceCast server. + * + * @return if shouting was successful. + * @exception Exception + */ + bool + shout ( unsigned int ) throw ( Exception ); + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + DarkIce ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + + public: + + /** + * Constructor based on a configuration object. + * + * @param config the config Object to read initialization + * information from. + * @exception Exception + */ + inline + DarkIce ( const Config & config ) throw ( Exception ) + { + init( config); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~DarkIce ( void ) throw ( Exception ) + { + } + +/* TODO + + inline + DarkIce ( const DarkIce & di ) throw ( Exception ) + { + } + + + inline DarkIce & + operator= ( const DarkIce * di ) throw ( Exception ) + { + } +*/ + + /** + * Run the process of recording / encoding / sending to the servers. + * + * @return 0 on success + * @exception Exception + */ + virtual int + run ( void ) throw ( Exception ); + + /** + * Signal to each sink we have that they need to cut what they are + * doing, and start again. For FileSinks, this usually means to + * save the archive file recorded so far, and start a new archive + * file. + */ + virtual void + cut ( void ) throw (); + +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* DARK_ICE_H */ + diff --git a/darkice/tags/darkice-1_3/src/DarkIceConfig.cpp b/darkice/tags/darkice-1_3/src/DarkIceConfig.cpp new file mode 100644 index 0000000..c71f399 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/DarkIceConfig.cpp @@ -0,0 +1,166 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell Config + + File : DarkIceConfig.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + + +#include "DarkIceConfig.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/*------------------------------------------------------------------------------ + * Max line size + *----------------------------------------------------------------------------*/ +#define LINE_SIZE 256 + + +/*------------------------------------------------------------------------------ + * string containing all white space characters + *----------------------------------------------------------------------------*/ +#define WHITE_SPACE_STR " \t" + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Get a value for a key + *----------------------------------------------------------------------------*/ +const ConfigSection * +Config :: get ( const char * key ) const throw ( Exception ) +{ + if ( !key ) { + throw Exception( __FILE__, __LINE__, "no key"); + } + + TableType::const_iterator it = table.find( key); + if ( it == table.end() ) { + return 0; + } + return &(it->second); +} + + +/*------------------------------------------------------------------------------ + * Add a configuration line + *----------------------------------------------------------------------------*/ +bool +Config :: addLine ( const char * line ) throw ( Exception ) +{ + if ( !line ) { + throw Exception( __FILE__, __LINE__, "no line"); + } + + std::string::size_type ix; + std::string str( line); + + /* delete everything after the first # */ + if ( (ix = str.find( '#')) != str.npos ) { + str.erase( ix); + } + /* eat up all white space from the front */ + if ( (ix = str.find_first_not_of( WHITE_SPACE_STR)) != str.npos ) { + str.erase( 0, ix); + } + /* eat up all white space from the end */ + if ( (ix = str.find_last_not_of( WHITE_SPACE_STR)) != str.npos ) { + str.erase( ix + 1); + } + + if ( !str.length() ) { + return true; + } + if ( str[0] == '[' && str[str.size()-1] == ']' ) { + // a new section starts + + std::string section( str, 1, str.size()-2); + ConfigSection cSection; + std::pair + element( section, cSection); + std::pair res; + + res = table.insert( element); + + currentSection = section; + return res.second; + } else { + // it's a line for the current section + + TableType::iterator it = table.find( currentSection); + if ( it == table.end() ) { + throw Exception( __FILE__, __LINE__, "no current section"); + } + + return it->second.addLine( line); + } +} + + +/*------------------------------------------------------------------------------ + * Add a configuration line + *----------------------------------------------------------------------------*/ +void +Config :: read ( std::istream & is ) throw ( Exception ) +{ + char line[LINE_SIZE]; + unsigned int num; + + for ( num = 0; !is.fail() && !is.eof(); ++num ) { + is.getline( line, LINE_SIZE); + if ( is.eof() ) { + break; + } else if ( is.fail() ) { + throw Exception( __FILE__, __LINE__, "line too long", num); + } + + addLine( line); + } +} + + diff --git a/darkice/tags/darkice-1_3/src/DarkIceConfig.h b/darkice/tags/darkice-1_3/src/DarkIceConfig.h new file mode 100644 index 0000000..d3d41fa --- /dev/null +++ b/darkice/tags/darkice-1_3/src/DarkIceConfig.h @@ -0,0 +1,209 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell Config + + File : DarkIceConfig.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef CONFIG_H +#define CONFIG_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include +#include + +#include + +#include "Referable.h" +#include "ConfigSection.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A configuration file representation. The file is of the syntax: + * + *
+ *  [section1]
+ *  # this is a whole line comment
+ *  key = value
+ *  an ugly key name = long value    # this end is a comment too
+ *
+ *  [section2]
+ *  # this is a whole line comment in section 2
+ *  key = value
+ *  an ugly key name = long value    # this end is a comment too
+ *  
+ * + * also empty lines are ignored and all white space is removed + * from the front and end of keys / values + * + * Knwon problem: you can't use '#' in any part of a key / value pair + * + * @author $Author$ + * @version $Revision$ + */ +class Config : public virtual Referable +{ + private: + + /** + * Type declaration of the hash table type. + */ + typedef std::map TableType; + + /** + * Hash table holding the configuration sections. + * + * @see ConfigSection + */ + TableType table; + + /** + * Hash table holding the configuration sections. + * + * @see ConfigSection + */ + std::string currentSection; + + + protected: + + + public: + + /** + * Default constructor. + * + * @exception Exception + */ + inline + Config ( void ) throw ( Exception ) + { + } + + /** + * Constructor based on an input stream. + * + * @param is configuration will be read from this input stream + * until end of stream is reached. + * @exception Exception + */ + inline + Config ( std::istream & is ) throw ( Exception ) + { + read( is ); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~Config ( void ) throw ( Exception ) + { + } + + +/* TODO + + inline + Config ( const Config & di ) throw ( Exception ) + { + } + + + inline Config & + operator= ( const Config * di ) throw ( Exception ) + { + } +*/ + + /** + * Delete the configuration information stored in the object. + * Resets the object to a clean state. + * + * @exception Exception + */ + inline virtual void + reset ( void ) throw ( Exception ) + { + table.clear(); + currentSection = ""; + } + + /** + * Read a line of confiugration information. + * + * @param line the line to read. + * @return true if the line was correct, false otherwise. + * @exception Exception + */ + virtual bool + addLine ( const char * line ) throw ( Exception ); + + /** + * Read a line of confiugration information. + * + * @param is the input stream to read from + * @return true if the line was correct, false otherwise. + * @exception Exception + */ + virtual void + read ( std::istream & is ) throw ( Exception ); + + /** + * Get a ConfigSection by name. + * + * @param key the name of the ConfigSection + * @return the ConfigSection requested, or NULL if it doesn't exists. + * @exception Exception + */ + virtual const ConfigSection * + get ( const char * key ) const throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* CONFIG_H */ + diff --git a/darkice/tags/darkice-1_3/src/Exception.cpp b/darkice/tags/darkice-1_3/src/Exception.cpp new file mode 100644 index 0000000..6594293 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/Exception.cpp @@ -0,0 +1,201 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : Exception.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + + +#include "Exception.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Constructor + *----------------------------------------------------------------------------*/ +Exception :: Exception ( const char * file, + unsigned int line, + const char * description1, + const char * description2, + int code ) throw () +{ + size_t len = 0; + + if ( description1 ) { + len += strlen( description1); + } + if ( description2 ) { + len += strlen( description2); + } + + if ( len ) { + char * str = new char[len+1]; + + str[0] = '\0'; + if ( description1 ) { + strcat( str, description1); + } + if ( description2 ) { + strcat( str, description2); + } + + init( file, line, str, code); + delete[] str; + + } else { + + init( file, line, 0, code); + } +} + + +/*------------------------------------------------------------------------------ + * Constructor + *----------------------------------------------------------------------------*/ +Exception :: Exception ( const char * file, + unsigned int line, + const char * description1, + const char * description2, + const char * description3, + int code ) throw () +{ + size_t len = 0; + + if ( description1 ) { + len += strlen( description1); + } + if ( description2 ) { + len += strlen( description2); + } + if ( description3 ) { + len += strlen( description3); + } + + if ( len ) { + char * str = new char[len+1]; + + str[0] = '\0'; + if ( description1 ) { + strcat( str, description1); + } + if ( description2 ) { + strcat( str, description2); + } + if ( description3 ) { + strcat( str, description3); + } + + init( file, line, str, code); + delete[] str; + + } else { + + init( file, line, 0, code); + } +} + + +/*------------------------------------------------------------------------------ + * Initialize the class + *----------------------------------------------------------------------------*/ +void +Exception :: init ( const char * file, + unsigned int line, + const char * description = 0, + int code = 0 ) throw () +{ + if ( !file ) { + this->file = 0; + } else { + size_t len; + + len = strlen( file ) + 1; + this->file = new char[len]; + if ( this->file ) { + memcpy( this->file, file, len); + } + } + + if ( !description ) { + this->description = 0; + } else { + size_t len; + + len = strlen( description ) + 1; + this->description = new char[len]; + if ( this->description ) { + memcpy( this->description, description, len); + } + } + + this->line = line; + this->code = code; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the class + *----------------------------------------------------------------------------*/ +void +Exception :: strip ( void ) throw () +{ + if ( description ) { + delete[] description; + } + + if ( file ) { + delete[] file; + } +} + + + diff --git a/darkice/tags/darkice-1_3/src/Exception.h b/darkice/tags/darkice-1_3/src/Exception.h new file mode 100644 index 0000000..4a482d5 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/Exception.h @@ -0,0 +1,298 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : Exception.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef EXCEPTION_H +#define EXCEPTION_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * An exception class. + * + * This class should not depend on any other class + * should not throw any exceptions itself. + * + * Typical usage: + * + *
+ *  throw Exception( __FILE__, __LINE__, "describe the exception", code);
+ *  
+ * + * @author $Author$ + * @version $Revision$ + */ +class Exception +{ + private: + + /** + * Source file the exception was thrown in. + */ + char * file; + + /** + * Line number in the source file the exception was thrown in. + */ + unsigned int line; + + /** + * Textual description of the exception. + */ + char * description; + + /** + * Numerical error code. + */ + int code; + + /** + * Initalize the object. + * + * @param file the source file the exception was thrown in. + * @param line the line in the source file. + * @param description textual description of the exception. + * @param code numerical error code. + */ + void + init ( const char * file, + unsigned int line, + const char * description, + int code ) throw (); + + /** + * De-initalize the object. + */ + void + strip () throw (); + + + protected: + + + public: + + /** + * Default constructor. + */ + inline + Exception ( void ) throw () + { + init( 0, 0, 0, 0); + } + + /** + * Copy constructor. + */ + inline + Exception ( const Exception & e ) throw () + { + init( e.file, e.line, e.description, e.code); + } + + /** + * Construct by a description and error code. + * + * @param description textual description of the exception. + * @param code numerical error code. + */ + inline + Exception ( const char * description, + int code = 0 ) throw () + { + init( 0, 0, description, code); + } + + /** + * Construct by source file information, a description and error code. + * + * @param file the source file the exception was thrown in. + * @param line the line in the source file. + * @param description textual description of the exception. + * @param code numerical error code. + */ + inline + Exception ( const char * file, + unsigned int line, + const char * description = 0, + int code = 0 ) throw () + { + init( file, line, description, code); + } + + /** + * Construct by source file information, a description and error code. + * The description is constructed from two strings, any of which + * may be NULL. + * + * @param file the source file the exception was thrown in. + * @param line the line in the source file. + * @param description1 textual description of the exception part 1. + * @param description2 textual description of the exception part 2. + * @param code numerical error code. + */ + Exception ( const char * file, + unsigned int line, + const char * description1, + const char * description2, + int code = 0 ) throw (); + + /** + * Construct by source file information, a description and error code. + * The description is constructed from three strings, any of + * which may be NULL. + * + * @param file the source file the exception was thrown in. + * @param line the line in the source file. + * @param description1 textual description of the exception part 1. + * @param description2 textual description of the exception part 2. + * @param description3 textual description of the exception part 3. + * @param code numerical error code. + */ + Exception ( const char * file, + unsigned int line, + const char * description1, + const char * description2, + const char * description3, + int code = 0 ) throw (); + + /** + * Desctructor. + */ + inline + ~Exception ( void ) throw () + { + strip(); + } + + /** + * Assignment operator. + * + * @param e the Exception to assign this to. + * @return a reference to this Exception. + */ + inline Exception & + operator= ( const Exception & e ) throw () + { + if ( this != &e ) { + strip(); + init( e.file, e.line, e.description, e.code); + } + + return *this; + } + + /** + * Return the textual description of the Exception. + * + * @return the textual description of the Exception. + */ + inline const char * + getDescription( void ) const throw () + { + return description; + } + + /** + * Return the line number in the source file this Exception was + * thrown in. + * + * @return the line number in the source file this Exception was + * thrown in. + */ + inline unsigned int + getLine ( void ) const throw () + { + return line; + } + + /** + * Return the source file this Exception was thrown in. + * + * @return the source file this Exception was thrown in. + */ + inline const char * + getFile ( void ) const throw () + { + return file; + } + + /** + * Return the numerical code of the Exception. + * + * @return the numerical code of the Exception. + */ + inline int + getCode ( void ) const throw () + { + return code; + } +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + +/** + * Print an Exception to an ostream. + * + * @param os the output stream to print to. + * @param e the Exception to print. + * @return a reference to the supplied output stream. + */ +inline std::ostream & +operator<< ( std::ostream & os, + const Exception & e ) +{ + os << e.getFile() << ":" << e.getLine() << ": " + << e.getDescription() << " [" << e.getCode() << "]"; + + return os; +} + + + +#endif /* EXCEPTION_H */ + diff --git a/darkice/tags/darkice-1_3/src/FaacEncoder.cpp b/darkice/tags/darkice-1_3/src/FaacEncoder.cpp new file mode 100644 index 0000000..1100226 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/FaacEncoder.cpp @@ -0,0 +1,279 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : FaacEncoder.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// compile the whole file only if faac support configured in +#ifdef HAVE_FAAC_LIB + + + +#include "Exception.h" +#include "Util.h" +#include "FaacEncoder.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Open an encoding session + *----------------------------------------------------------------------------*/ +bool +FaacEncoder :: open ( void ) + throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + // open the underlying sink + if ( !getSink()->open() ) { + throw Exception( __FILE__, __LINE__, + "faac lib opening underlying sink error"); + } + + char * faacVersion; + char * faacCopyright; + faacEncGetVersion(&faacVersion, &faacCopyright); + reportEvent(1, "Using faac codec version", faacVersion); + + encoderHandle = faacEncOpen(getOutSampleRate(), + getInChannel(), + &inputSamples, + &maxOutputBytes); + + faacEncConfiguration * faacConfig; + + faacConfig = faacEncGetCurrentConfiguration(encoderHandle); + + faacConfig->aacObjectType = MAIN; + faacConfig->mpegVersion = MPEG2; + faacConfig->useTns = 1; + faacConfig->shortctl = SHORTCTL_NORMAL; + faacConfig->useLfe = 0; + faacConfig->allowMidside = 1; + faacConfig->bitRate = getOutBitrate() * 1000 / getOutChannel(); + faacConfig->bandWidth = lowpass; + faacConfig->quantqual = (unsigned long) (getOutQuality() * 1000.0); + faacConfig->outputFormat = 1; + faacConfig->inputFormat = FAAC_INPUT_16BIT; + + if (!faacEncSetConfiguration(encoderHandle, faacConfig)) { + throw Exception(__FILE__, __LINE__, + "error configuring faac library"); + } + + // initialize the resampling coverter if needed + if ( converter ) { + +#ifdef HAVE_SRC_LIB + converterData.input_frames = 4096/((getInBitsPerSample() / 8) * getInChannel()); + converterData.data_in = new float[converterData.input_frames*getInChannel()]; + converterData.output_frames = (int) (converterData.input_frames * resampleRatio + 1); + if ((int) inputSamples > getInChannel() * converterData.output_frames) { + resampledOffset = new float[2 * inputSamples]; + } else { + resampledOffset = new float[2 * getInChannel() * converterData.input_frames]; + } + converterData.src_ratio = resampleRatio; + converterData.end_of_input = 0; +#else + converter->initialize( resampleRatio, getInChannel()); + //needed 2x(converted input samples) to handle offsets + int outCount = 2 * getInChannel() * (inputSamples + 1); + if (resampleRatio > 1) + outCount = (int) (outCount * resampleRatio); + resampledOffset = new short int[outCount]; +#endif + resampledOffsetSize = 0; + } + + faacOpen = true; + + return true; +} + + +/*------------------------------------------------------------------------------ + * Write data to the encoder + *----------------------------------------------------------------------------*/ +unsigned int +FaacEncoder :: write ( const void * buf, + unsigned int len ) throw ( Exception ) +{ + if ( !isOpen() || len == 0 ) { + return 0; + } + + unsigned int channels = getInChannel(); + unsigned int bitsPerSample = getInBitsPerSample(); + unsigned int sampleSize = (bitsPerSample / 8) * channels; + unsigned char * b = (unsigned char*) buf; + unsigned int processed = len - (len % sampleSize); + unsigned int nSamples = processed / sampleSize; + unsigned char * faacBuf = new unsigned char[maxOutputBytes]; + int samples = (int) nSamples * channels; + int processedSamples = 0; + + + + if ( converter ) { + unsigned int converted; +#ifdef HAVE_SRC_LIB + src_short_to_float_array ((short *) b, converterData.data_in, samples); + converterData.input_frames = nSamples; + converterData.data_out = resampledOffset + (resampledOffsetSize * channels); + int srcError = src_process (converter, &converterData); + if (srcError) + throw Exception (__FILE__, __LINE__, "libsamplerate error: ", src_strerror (srcError)); + converted = converterData.output_frames_gen; +#else + int inCount = nSamples; + short int * shortBuffer = new short int[samples]; + int outCount = (int) (inCount * resampleRatio); + Util::conv( bitsPerSample, b, processed, shortBuffer, isInBigEndian()); + converted = converter->resample( inCount, + outCount+1, + shortBuffer, + &resampledOffset[resampledOffsetSize*channels]); + delete[] shortBuffer; +#endif + resampledOffsetSize += converted; + + // encode samples (if enough) + while(resampledOffsetSize - processedSamples >= inputSamples/channels) { + int outputBytes; +#ifdef HAVE_SRC_LIB + short *shortData = new short[inputSamples]; + src_float_to_short_array(resampledOffset + (processedSamples * channels), + shortData, inputSamples) ; + outputBytes = faacEncEncode(encoderHandle, + (int32_t*) shortData, + inputSamples, + faacBuf, + maxOutputBytes); + delete [] shortData; +#else + outputBytes = faacEncEncode(encoderHandle, + (int32_t*) &resampledOffset[processedSamples*channels], + inputSamples, + faacBuf, + maxOutputBytes); +#endif + getSink()->write(faacBuf, outputBytes); + processedSamples+=inputSamples/channels; + } + + if (processedSamples && (int) resampledOffsetSize >= processedSamples) { + resampledOffsetSize -= processedSamples; + //move least part of resampled data to beginning + if(resampledOffsetSize) +#ifdef HAVE_SRC_LIB + resampledOffset = (float *) memmove(resampledOffset, &resampledOffset[processedSamples*channels], + resampledOffsetSize*channels*sizeof(float)); +#else + resampledOffset = (short *) memmove(resampledOffset, &resampledOffset[processedSamples*channels], + resampledOffsetSize*sampleSize); +#endif + } + } else { + while (processedSamples < samples) { + int outputBytes; + int inSamples = samples - processedSamples < (int) inputSamples + ? samples - processedSamples + : inputSamples; + + outputBytes = faacEncEncode(encoderHandle, + (int32_t*) (b + processedSamples/sampleSize), + inSamples, + faacBuf, + maxOutputBytes); + getSink()->write(faacBuf, outputBytes); + + processedSamples += inSamples; + } + } + + delete[] faacBuf; + + return samples * sampleSize; +} + + +/*------------------------------------------------------------------------------ + * Flush the data from the encoder + *----------------------------------------------------------------------------*/ +void +FaacEncoder :: flush ( void ) + throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + getSink()->flush(); +} + + +/*------------------------------------------------------------------------------ + * Close the encoding session + *----------------------------------------------------------------------------*/ +void +FaacEncoder :: close ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + flush(); + faacEncClose(encoderHandle); + faacOpen = false; + + getSink()->close(); + } +} + + +#endif // HAVE_FAAC_LIB + diff --git a/darkice/tags/darkice-1_3/src/FaacEncoder.h b/darkice/tags/darkice-1_3/src/FaacEncoder.h new file mode 100644 index 0000000..1b222c0 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/FaacEncoder.h @@ -0,0 +1,517 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : FaacEncoder.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef AAC_ENCODER_H +#define AAC_ENCODER_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_FAAC_LIB +#include +#else +#error configure with faac +#endif + + +#include "Ref.h" +#include "Exception.h" +#include "Reporter.h" +#include "AudioEncoder.h" +#include "Sink.h" +#ifdef HAVE_SRC_LIB +#include +#else +#include "aflibConverter.h" +#endif + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A class representing faac AAC encoder. + * + * @author $Author$ + * @version $Revision$ + */ +class FaacEncoder : public AudioEncoder, public virtual Reporter +{ + private: + + /** + * A flag to indicate if the encoding session is open. + */ + bool faacOpen; + + /** + * The handle to the AAC encoder instance. + */ + faacEncHandle encoderHandle; + + /** + * The maximum number of input samples to supply to the encoder. + */ + unsigned long inputSamples; + + /** + * The maximum number of output bytes the encoder returns in one call. + */ + unsigned long maxOutputBytes; + + /** + * Lowpass filter. Sound frequency in Hz, from where up the + * input is cut. + */ + int lowpass; + + /** + * Resample ratio + */ + double resampleRatio; + + /** + * sample rate converter object for possible resampling + */ +#ifdef HAVE_SRC_LIB + SRC_STATE *converter; + SRC_DATA converterData; + float *resampledOffset; +#else + aflibConverter *converter; + short *resampledOffset; +#endif + unsigned int resampledOffsetSize; + + /** + * Initialize the object. + * + * @param lowpass frequency threshold for the lowpass filter. + * Input above this frequency is cut. + * If 0, faac's default values are used, + * which depends on the out sample rate. + * @exception Exception + */ + inline void + init ( int lowpass) throw (Exception) + { + this->faacOpen = false; + this->lowpass = lowpass; + + if ( getInBitsPerSample() != 16 && getInBitsPerSample() != 8 ) { + throw Exception( __FILE__, __LINE__, + "specified bits per sample not supported", + getInBitsPerSample() ); + } + + if ( getInChannel() != 1 && getInChannel() != 2 ) { + throw Exception( __FILE__, __LINE__, + "unsupported number of input channels for the encoder", + getInChannel() ); + } + if ( getOutChannel() != 1 && getOutChannel() != 2 ) { + throw Exception( __FILE__, __LINE__, + "unsupported number of output channels for the encoder", + getOutChannel() ); + } + if ( getInChannel() != getOutChannel() ) { + throw Exception( __FILE__, __LINE__, + "input channels and output channels do not match"); + } + if ( getOutSampleRate() == getInSampleRate() ) { + resampleRatio = 1; + converter = 0; + } else if (getInBitsPerSample() == 16) { + resampleRatio = ( (double) getOutSampleRate() / + (double) getInSampleRate() ); + + // Determine if we can use linear interpolation. + // The inverse of the ratio must be a power of two for linear mode to + // be of sufficient quality. + + bool useLinear = true; + double inverse = 1 / resampleRatio; + int integer = (int) inverse; + + // Check that the inverse of the ratio is an integer + if( integer == inverse ) { + while( useLinear && integer ) { // Loop through the bits + // If the lowest order bit is not the only one set + if( integer & 1 && integer != 1 ) { + // Not a power of two; cannot use linear + useLinear = false; + } else { + // Shift all the bits over and try again + integer >>= 1; + } + } + } else { + useLinear = false; + } + + // If we get here and useLinear is still true, then we have + // a power of two. + + // open the aflibConverter in + // - high quality + // - linear or quadratic (non-linear) based on algorithm + // - not filter interpolation +#ifdef HAVE_SRC_LIB + int srcError = 0; + converter = src_new(useLinear == true ? SRC_LINEAR : SRC_SINC_FASTEST, + getInChannel(), &srcError); + if(srcError) + throw Exception (__FILE__, __LINE__, "libsamplerate error: ", src_strerror (srcError)); +#else + converter = new aflibConverter( true, useLinear, false); +#endif + } else { + throw Exception( __FILE__, __LINE__, + "specified bits per sample with samplerate conversion not supported", + getInBitsPerSample() ); + } + } + + /** + * De-initialize the object. + * + * @exception Exception + */ + inline void + strip ( void ) throw ( Exception ) + { + if ( converter ) { +#ifdef HAVE_SRC_LIB + delete [] converterData.data_in; + src_delete (converter); +#else + delete converter; +#endif + delete [] resampledOffset; + } + } + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + FaacEncoder ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + + public: + + /** + * Constructor. + * + * @param sink the sink to send mp3 output to + * @param inSampleRate sample rate of the input. + * @param inBitsPerSample number of bits per sample of the input. + * @param inChannel number of channels of the input. + * @param inBigEndian shows if the input is big or little endian + * @param outBitrateMode the bit rate mode of the output. + * @param outBitrate bit rate of the output (kbits/sec). + * @param outQuality the quality of the stream. + * @param outSampleRate sample rate of the output. + * If 0, inSampleRate is used. + * @param outChannel number of channels of the output. + * If 0, inChannel is used. + * @param lowpass frequency threshold for the lowpass filter. + * Input above this frequency is cut. + * If 0, faac's default values are used, + * which depends on the out sample rate. + * @exception Exception + */ + inline + FaacEncoder ( Sink * sink, + unsigned int inSampleRate, + unsigned int inBitsPerSample, + unsigned int inChannel, + bool inBigEndian, + BitrateMode outBitrateMode, + unsigned int outBitrate, + double outQuality, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0, + int lowpass = 0) + throw ( Exception ) + + : AudioEncoder ( sink, + inSampleRate, + inBitsPerSample, + inChannel, + inBigEndian, + outBitrateMode, + outBitrate, + outQuality, + outSampleRate, + outChannel ) + { + init( lowpass); + } + + /** + * Constructor. + * + * @param sink the sink to send mp3 output to + * @param as get input sample rate, bits per sample and channels + * from this AudioSource. + * @param outBitrateMode the bit rate mode of the output. + * @param outBitrate bit rate of the output (kbits/sec). + * @param outQuality the quality of the stream. + * @param outSampleRate sample rate of the output. + * If 0, input sample rate is used. + * @param outChannel number of channels of the output. + * If 0, input channel is used. + * @param lowpass frequency threshold for the lowpass filter. + * Input above this frequency is cut. + * If 0, faac's default values are used, + * which depends on the out sample rate. + * @exception Exception + */ + inline + FaacEncoder ( Sink * sink, + const AudioSource * as, + BitrateMode outBitrateMode, + unsigned int outBitrate, + double outQuality, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0, + int lowpass = 0) + throw ( Exception ) + + : AudioEncoder ( sink, + as, + outBitrateMode, + outBitrate, + outQuality, + outSampleRate, + outChannel ) + { + init( lowpass); + } + + /** + * Copy constructor. + * + * @param encoder the FaacEncoder to copy. + */ + inline + FaacEncoder ( const FaacEncoder & encoder ) + throw ( Exception ) + : AudioEncoder( encoder ) + { + init( encoder.lowpass); + } + + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~FaacEncoder ( void ) throw ( Exception ) + { + if ( isOpen() ) { + close(); + } + strip(); + } + + /** + * Assignment operator. + * + * @param encoder the FaacEncoder to assign this to. + * @return a reference to this FaacEncoder. + * @exception Exception + */ + inline virtual FaacEncoder & + operator= ( const FaacEncoder & encoder ) throw ( Exception ) + { + if ( this != &encoder ) { + strip(); + AudioEncoder::operator=( encoder); + init( encoder.lowpass); + } + + return *this; + } + + /** + * Get the version string of the underlying faac library. + * + * @return the version string of the underlying faac library. + */ + inline const char * + getFaacVersion( void ) + { + char * id; + char * copyright; + + faacEncGetVersion(&id, ©right); + return id; + } + + /** + * Check whether encoding is in progress. + * + * @return true if encoding is in progress, false otherwise. + */ + inline virtual bool + isRunning ( void ) const throw () + { + return isOpen(); + } + + /** + * Start encoding. This function returns as soon as possible, + * with encoding started in the background. + * + * @return true if encoding has started, false otherwise. + * @exception Exception + */ + inline virtual bool + start ( void ) throw ( Exception ) + { + return open(); + } + + /** + * Stop encoding. Stops the encoding running in the background. + * + * @exception Exception + */ + inline virtual void + stop ( void ) throw ( Exception ) + { + return close(); + } + + /** + * Open an encoding session. + * + * @return true if opening was successfull, false otherwise. + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the encoding session is open. + * + * @return true if the encoding session is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return faacOpen; + } + + /** + * Check if the encoder is ready to accept data. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the encoder is ready to accept data, + * false otherwise. + * @exception Exception + */ + inline virtual bool + canWrite ( unsigned int sec, + unsigned int usec ) throw ( Exception ) + { + if ( !isOpen() ) { + return false; + } + + return true; + } + + /** + * Write data to the encoder. + * Buf is expected to be a sequence of big-endian 16 bit values, + * with left and right channels interleaved. Len is the number of + * bytes, must be a multiple of 4. + * + * @param buf the data to write. + * @param len number of bytes to write from buf. + * @return the number of bytes written (may be less than len). + * @exception Exception + */ + virtual unsigned int + write ( const void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Flush all data that was written to the encoder to the underlying + * connection. + * + * @exception Exception + */ + virtual void + flush ( void ) throw ( Exception ); + + /** + * Close the encoding session. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + +#endif /* AAC_ENCODER_H */ + diff --git a/darkice/tags/darkice-1_3/src/FileCast.cpp b/darkice/tags/darkice-1_3/src/FileCast.cpp new file mode 100644 index 0000000..34c01bd --- /dev/null +++ b/darkice/tags/darkice-1_3/src/FileCast.cpp @@ -0,0 +1,89 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : FileCast.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STDIO_H +#include +#else +#error need stdio.h +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + + +#include "Exception.h" +#include "Source.h" +#include "Sink.h" +#include "Util.h" +#include "FileCast.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Open the connection + *----------------------------------------------------------------------------*/ +bool +FileCast :: open ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + return false; + } + + if ( !targetFile->open() ) { + return false; + } + + return true; +} + + diff --git a/darkice/tags/darkice-1_3/src/FileCast.h b/darkice/tags/darkice-1_3/src/FileCast.h new file mode 100644 index 0000000..45258aa --- /dev/null +++ b/darkice/tags/darkice-1_3/src/FileCast.h @@ -0,0 +1,274 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : FileCast.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef FILE_CAST_H +#define FILE_CAST_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Ref.h" +#include "Sink.h" +#include "CastSink.h" +#include "FileSink.h" +#include "FileCast.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * Class representing output to a local file. + * + * @author $Author$ + * @version $Revision$ + */ +class FileCast : public CastSink +{ + private: + + /** + * The file to send the encoded data to. + */ + Ref targetFile; + + /** + * Initalize the object. + * + * @param targetFile the file to send the encoded data to. + * @exception Exception + */ + inline void + init ( FileSink * targetFile ) + throw ( Exception ) + { + this->targetFile = targetFile; + } + + /** + * De-initalize the object. + * + * @exception Exception + */ + inline void + strip ( void ) throw ( Exception ) + { + if ( isOpen() ) { + close(); + } + } + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + FileCast ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Log in to the server using the socket avialable. + * No need to log in to a file. + * + * @return true if login was successful, false otherwise. + * @exception Exception + */ + inline virtual bool + sendLogin ( void ) throw ( Exception ) + { + return true; + } + + + public: + + /** + * Constructor. + * + * @param targetFile the file to send all the data to. + * @exception Exception + */ + inline + FileCast ( FileSink * targetFile ) + throw ( Exception ) + : CastSink( 0, 0, 0) + { + init( targetFile ); + } + + /** + * Copy constructor. + * + * @param cs the FileCast to copy. + */ + inline + FileCast( const FileCast & cs ) throw ( Exception ) + { + init( targetFile.get() ); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~FileCast( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param cs the FileCast to assign this to. + * @return a reference to this FileCast. + * @exception Exception + */ + inline virtual FileCast & + operator= ( const FileCast & cs ) throw ( Exception ) + { + if ( this != &cs ) { + strip(); + init( targetFile.get() ); + } + return *this; + } + + /** + * Open the FileCast. + * + * @return true if opening was successfull, false otherwise. + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the FileCast is open. + * + * @return true if the FileCast is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return targetFile->isOpen(); + } + + /** + * Check if the FileCast is ready to accept data. + * Blocks until the specified time for data to be available. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the FileCast is ready to accept data, + * false otherwise. + * @exception Exception + */ + inline virtual bool + canWrite ( unsigned int sec, + unsigned int usec ) throw ( Exception ) + { + return targetFile->canWrite( sec, usec); + } + + /** + * Write data to the FileCast. + * + * @param buf the data to write. + * @param len number of bytes to write from buf. + * @return the number of bytes written (may be less than len). + * @exception Exception + */ + inline virtual unsigned int + write ( const void * buf, + unsigned int len ) throw ( Exception ) + { + return targetFile->write( buf, len); + } + + /** + * Flush all data that was written to the FileCast to the server. + * + * @exception Exception + */ + inline virtual void + flush ( void ) throw ( Exception ) + { + return targetFile->flush(); + } + + /** + * Cut what the sink has been doing so far, and start anew. + * This usually means separating the data sent to the sink up + * until now, and start saving a new chunk of data. + */ + inline virtual void + cut ( void ) throw () + { + targetFile->cut(); + } + + /** + * Close the FileCast. + * + * @exception Exception + */ + inline virtual void + close ( void ) throw ( Exception ) + { + return targetFile->close(); + } + +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* FILE_CAST_H */ + diff --git a/darkice/tags/darkice-1_3/src/FileSink.cpp b/darkice/tags/darkice-1_3/src/FileSink.cpp new file mode 100644 index 0000000..e3c2000 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/FileSink.cpp @@ -0,0 +1,384 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : FileSink.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_UNISTD_H +#include +#else +#error need unistd.h +#endif + +#ifdef HAVE_STDLIB_H +#include +#else +#error need stdlib.h +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#else +#error need sys/types.h +#endif + +#ifdef HAVE_ERRNO_H +#include +#else +#error need errno.h +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#else +#error need sys/stat.h +#endif + +#ifdef HAVE_FCNTL_H +#include +#else +#error need fcntl.h +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#else +#error need sys/time.h +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + +#ifdef HAVE_SIGNAL_H +#include +#else +#error need signal.h +#endif + + +#include +#include +#include + + +#include "Util.h" +#include "Exception.h" +#include "FileSink.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +FileSink :: init ( const char * configName, + const char * name ) throw ( Exception ) +{ + this->configName = Util::strDup(configName); + fileName = Util::strDup(name); + fileDescriptor = 0; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +FileSink :: strip ( void) throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + delete[] fileName; +} + + +/*------------------------------------------------------------------------------ + * Copy Constructor + *----------------------------------------------------------------------------*/ +FileSink :: FileSink ( const FileSink & fs ) throw ( Exception ) + : Sink( fs ) +{ + int fd; + + init( fs.configName, fs.fileName); + + if ( (fd = fs.fileDescriptor ? dup( fs.fileDescriptor) : 0) == -1 ) { + strip(); + throw Exception( __FILE__, __LINE__, "dup failure"); + } + + fileDescriptor = fd; +} + + +/*------------------------------------------------------------------------------ + * Assignment operator + *----------------------------------------------------------------------------*/ +FileSink & +FileSink :: operator= ( const FileSink & fs ) throw ( Exception ) +{ + if ( this != &fs ) { + int fd; + + /* first strip */ + strip(); + + + /* then build up */ + Sink::operator=( fs ); + + init( fs.configName, fs.fileName); + + if ( (fd = fs.fileDescriptor ? dup( fs.fileDescriptor) : 0) == -1 ) { + strip(); + throw Exception( __FILE__, __LINE__, "dup failure"); + } + + fileDescriptor = fd; + } + + return *this; +} + + +/*------------------------------------------------------------------------------ + * Check whether a file exists and is regular file + *----------------------------------------------------------------------------*/ +bool +FileSink :: exists ( void ) const throw () +{ + struct stat st; + + if ( stat( (const char*)fileName, &st) == -1 ) { + return false; + } + + return S_ISREG( st.st_mode); +} + + +/*------------------------------------------------------------------------------ + * Create a file, truncate if already exists + *----------------------------------------------------------------------------*/ +bool +FileSink :: create ( void ) throw ( Exception ) +{ + int fd; + + if ( isOpen() ) { + return false; + } + /* filemode default to 0666 */ + const int filemode = (S_IRUSR|S_IWUSR|S_IWGRP|S_IRGRP|S_IROTH|S_IWOTH) ; + /* create the file */ + if ( (fd = ::creat( fileName, filemode )) == -1 ) { + reportEvent( 3, "can't create file", fileName, errno); + return false; + } + + ::close( fd); + return true; +} + + +/*------------------------------------------------------------------------------ + * Open the file + *----------------------------------------------------------------------------*/ +bool +FileSink :: open ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + return false; + } + + if ( (fileDescriptor = ::open( fileName, O_WRONLY | O_TRUNC, 0)) == -1 ) { + fileDescriptor = 0; + return false; + } + + return true; +} + + +/*------------------------------------------------------------------------------ + * Check whether the file can be written to + *----------------------------------------------------------------------------*/ +bool +FileSink :: canWrite ( unsigned int sec, + unsigned int usec ) throw ( Exception ) +{ + fd_set fdset; + struct timespec timespec; + sigset_t sigset; + int ret; + + if ( !isOpen() ) { + return false; + } + + FD_ZERO( &fdset); + FD_SET( fileDescriptor, &fdset); + + timespec.tv_sec = sec; + timespec.tv_nsec = usec * 1000L; + + // mask out SIGUSR1, as we're expecting that signal for other reasons + sigemptyset(&sigset); + sigaddset(&sigset, SIGUSR1); + + ret = pselect( fileDescriptor + 1, NULL, &fdset, NULL, ×pec, &sigset); + + if ( ret == -1 ) { + throw Exception( __FILE__, __LINE__, "select error"); + } + + return ret > 0; +} + + +/*------------------------------------------------------------------------------ + * Write to the FileSink + *----------------------------------------------------------------------------*/ +unsigned int +FileSink :: write ( const void * buf, + unsigned int len ) throw ( Exception ) +{ + ssize_t ret; + + if ( !isOpen() ) { + return 0; + } + + ret = ::write( fileDescriptor, buf, len); + + if ( ret == -1 ) { + if ( errno == EAGAIN ) { + ret = 0; + } else { + throw Exception( __FILE__, __LINE__, "write error", errno); + } + } + + return ret; +} + + +/*------------------------------------------------------------------------------ + * Get the file name to where to move the data saved so far. + * The trick is to read the file name from a file named + * /tmp/darkice.$configName.$PID , where: + * - $configName is the name of the configuration section for this file sink + * - $PID is the current process id + *----------------------------------------------------------------------------*/ +std::string +FileSink :: getArchiveFileName ( void ) throw ( Exception ) +{ + pid_t pid = getpid(); + std::stringstream metaFileName; + + metaFileName << "/tmp/darkice." << configName << "." << pid; + + std::ifstream ifs(metaFileName.str().c_str()); + if (!ifs.good()) { + throw Exception(__FILE__, __LINE__, + "can't find file ", metaFileName.str().c_str(), 0); + } + + std::string archiveFileName; + ifs >> archiveFileName; + ifs.close(); + + return archiveFileName; +} + +/*------------------------------------------------------------------------------ + * Cut what we've done so far, and start anew. + *----------------------------------------------------------------------------*/ +void +FileSink :: cut ( void ) throw () +{ + flush(); + close(); + + try { + std::string archiveFileName = getArchiveFileName(); + + if (::rename(fileName, archiveFileName.c_str()) != 0) { + reportEvent(2, "couldn't move file", fileName, + "to", archiveFileName); + } + + } catch ( Exception &e ) { + reportEvent(2, "error during archive cut", e); + } + + create(); + open(); +} + + +/*------------------------------------------------------------------------------ + * Close the FileSink + *----------------------------------------------------------------------------*/ +void +FileSink :: close ( void ) throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + flush(); + ::close( fileDescriptor); + fileDescriptor = 0; +} + + diff --git a/darkice/tags/darkice-1_3/src/FileSink.h b/darkice/tags/darkice-1_3/src/FileSink.h new file mode 100644 index 0000000..26f39ee --- /dev/null +++ b/darkice/tags/darkice-1_3/src/FileSink.h @@ -0,0 +1,278 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : FileSink.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef FILE_SINK_H +#define FILE_SINK_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Reporter.h" +#include "Sink.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * File data output + * + * @author $Author$ + * @version $Revision$ + */ +class FileSink : public Sink, public virtual Reporter +{ + private: + + /** + * The name of the configuration related to + * this file sink. something like "file-0" or "file-2". + */ + char * configName; + + /** + * Name of the file represented by the FileSink. + */ + char * fileName; + + /** + * Initialize the object. + * + * @param configName the name of the configuration related to + * this file sink. something like "file-0" or "file-2". + * @param name name of the file to be represented by the object. + * @exception Exception + */ + void + init ( const char * configName, + const char * name ) throw ( Exception ); + + /** + * De-initialize the object. + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + /** + * Get the file name to where to move the data saved so far. + * Used in cut(). + * + * @return the file name where to move the data saved so far. + * @throws Exception on file operation errors + */ + std::string + getArchiveFileName( void ) throw ( Exception ); + + + protected: + + /** + * Low-level file descriptor for the file represented by this object. + */ + int fileDescriptor; + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + FileSink ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + + public: + + /** + * Constructor by a file name. + * + * @param configName the name of the configuration related to + * this file sink. something like "file-0" or "file-2". + * @param name name of the file to be represented by the object. + * @exception Exception + */ + inline + FileSink( const char * configName, + const char * name ) throw ( Exception ) + { + init( configName, name); + } + + /** + * Copy constructor. + * + * @param fsink the FileSink to copy. + * @exception Exception + */ + FileSink( const FileSink & fsink ) throw ( Exception ); + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~FileSink( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param fs the FileSink to assign to this object. + * @return a reference to this object. + * @exception Exception + */ + virtual FileSink & + operator= ( const FileSink & fs ) throw ( Exception ); + + /** + * Get the file name this FileSink represents. + * + * @return the file name this FileSink represents. + */ + inline const char * + getFileName ( void ) const throw () + { + return fileName; + } + + /** + * Check for the existence of the file this FileSink represents. + * + * @return true if the file exists and is a regular file, + * false otherwise. + */ + virtual bool + exists ( void ) const throw (); + + /** + * Create the file. + * + * @return true if creation was successful, false otherwise. + * @exception Exception + */ + virtual bool + create ( void ) throw ( Exception ); + + /** + * Open the file. Truncates the file. + * + * @return true if opening was successful, false otherwise. + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the FileSink is open. + * + * @return true if the FileSink is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return fileDescriptor != 0; + } + + /** + * Check if the FileSink is ready to accept data. + * Blocks until the specified time for data to be available. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the Sink is ready to accept data, false otherwise. + * @exception Exception + */ + virtual bool + canWrite ( unsigned int sec, + unsigned int usec ) throw ( Exception ); + + /** + * Write data to the FileSink. + * + * @param buf the data to write. + * @param len number of bytes to write from buf. + * @return the number of bytes written (may be less than len). + * @exception Exception + */ + virtual unsigned int + write ( const void * buf, + unsigned int len ) throw ( Exception ); + + /** + * This is a no-op in this FileSink. + * + * @exception Exception + */ + inline virtual void + flush ( void ) throw ( Exception ) + { + } + + /** + * Cut what the sink has been doing so far, and start anew. + * This usually means separating the data sent to the sink up + * until now, and start saving a new chunk of data. + */ + virtual void + cut ( void ) throw (); + + /** + * Close the FileSink. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* FILE_SINK_H */ + diff --git a/darkice/tags/darkice-1_3/src/FileSource.cpp b/darkice/tags/darkice-1_3/src/FileSource.cpp new file mode 100644 index 0000000..0624133 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/FileSource.cpp @@ -0,0 +1,270 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : FileSource.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "configure.h" +#endif + +#ifdef HAVE_UNISTD_H +#include +#else +#error need unistd.h +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#else +#error need sys/types.h +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#else +#error need sys/stat.h +#endif + +#ifdef HAVE_FCNTL_H +#include +#else +#error need fcntl.h +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#else +#error need sys/time.h +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + +#ifdef HAVE_SIGNAL_H +#include +#else +#error need signal.h +#endif + + +#include "Exception.h" +#include "Util.h" +#include "FileSource.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +FileSource :: init ( const char * name ) throw ( Exception ) +{ + fileName = Util::strDup( name); + fileDescriptor = 0; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +FileSource :: strip ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + delete[] fileName; + fileDescriptor = 0; +} + + +/*------------------------------------------------------------------------------ + * Copy Constructor + *----------------------------------------------------------------------------*/ +FileSource :: FileSource ( const FileSource & fs ) throw ( Exception ) +{ + init( fs.fileName); + + fileDescriptor = fs.fileDescriptor ? dup( fs.fileDescriptor) : 0; + + if ( fileDescriptor == -1 ) { + strip(); + throw Exception( __FILE__, __LINE__, "dup failure"); + } +} + + +/*------------------------------------------------------------------------------ + * Assignment operator + *----------------------------------------------------------------------------*/ +FileSource & +FileSource :: operator= ( const FileSource & fs ) throw ( Exception ) +{ + if ( this != &fs ) { + init( fs.fileName); + + fileDescriptor = fs.fileDescriptor ? dup( fs.fileDescriptor) : 0; + + if ( fileDescriptor == -1 ) { + strip(); + throw Exception( __FILE__, __LINE__, "dup failure"); + } + } + + return *this; +} + + +/*------------------------------------------------------------------------------ + * Check wether a file exists + *----------------------------------------------------------------------------*/ +bool +FileSource :: exists ( void ) const throw () +{ + struct stat st; + + if ( stat( (const char*)fileName, &st) == -1 ) { + return false; + } + + return true; +} + + +/*------------------------------------------------------------------------------ + * Open the source + *----------------------------------------------------------------------------*/ +bool +FileSource :: open ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + return false; + } + + if ( (fileDescriptor = ::open( fileName, O_RDONLY)) == -1 ) { + fileDescriptor = 0; + return false; + } + + return true; +} + + +/*------------------------------------------------------------------------------ + * Check wether read() would return anything + *----------------------------------------------------------------------------*/ +bool +FileSource :: canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ) +{ + fd_set fdset; + struct timespec timespec; + sigset_t sigset; + int ret; + + if ( !isOpen() ) { + return false; + } + + FD_ZERO( &fdset); + FD_SET( fileDescriptor, &fdset); + + timespec.tv_sec = sec; + timespec.tv_nsec = usec * 1000L; + + // mask out SIGUSR1, as we're expecting that signal for other reasons + sigemptyset(&sigset); + sigaddset(&sigset, SIGUSR1); + + ret = pselect( fileDescriptor + 1, &fdset, NULL, NULL, ×pec, &sigset); + + if ( ret == -1 ) { + throw Exception( __FILE__, __LINE__, "select error"); + } + + return ret > 0; +} + + +/*------------------------------------------------------------------------------ + * Read from the audio source + *----------------------------------------------------------------------------*/ +unsigned int +FileSource :: read ( void * buf, + unsigned int len ) throw ( Exception ) +{ + ssize_t ret; + + if ( !isOpen() ) { + return 0; + } + + ret = ::read( fileDescriptor, buf, len); + + if ( ret == -1 ) { + throw Exception( __FILE__, __LINE__, "read error"); + } + + return ret; +} + + +/*------------------------------------------------------------------------------ + * Close the audio source + *----------------------------------------------------------------------------*/ +void +FileSource :: close ( void ) throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + ::close( fileDescriptor); + fileDescriptor = 0; +} + diff --git a/darkice/tags/darkice-1_3/src/IceCast.cpp b/darkice/tags/darkice-1_3/src/IceCast.cpp new file mode 100644 index 0000000..839e1b4 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/IceCast.cpp @@ -0,0 +1,226 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : IceCast.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STDIO_H +#include +#else +#error need stdio.h +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + +#ifdef HAVE_MATH_H +#include +#else +#error need math.h +#endif + + +#include "Exception.h" +#include "Source.h" +#include "Sink.h" +#include "Util.h" +#include "IceCast.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/*------------------------------------------------------------------------------ + * Size of string conversion buffer + *----------------------------------------------------------------------------*/ +#define STRBUF_SIZE 32 + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +IceCast :: init ( const char * mountPoint, + const char * description, + const char * remoteDumpFile ) + throw ( Exception ) +{ + this->mountPoint = Util::strDup( mountPoint); + this->description = description ? Util::strDup( description) : 0; + this->remoteDumpFile = remoteDumpFile ? Util::strDup( remoteDumpFile) : 0; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +IceCast :: strip ( void ) throw ( Exception ) +{ + delete[] mountPoint; + if ( description ) { + delete[] description; + } + if ( remoteDumpFile ) { + delete[] remoteDumpFile; + } +} + + +/*------------------------------------------------------------------------------ + * Log in to the IceCast server + *----------------------------------------------------------------------------*/ +bool +IceCast :: sendLogin ( void ) throw ( Exception ) +{ + Sink * sink = getSink(); + Source * source = getSocket(); + const char * str; + char resp[STRBUF_SIZE]; + unsigned int len; + + if ( !source->isOpen() ) { + return false; + } + if ( !sink->isOpen() ) { + return false; + } + + /* send the request, a string like: + * "SOURCE /\n" */ + str = "SOURCE "; + sink->write( str, strlen( str)); + str = getPassword(); + sink->write( str, strlen( str)); + str = " /"; + sink->write( str, strlen( str)); + str = getMountPoint(); + sink->write( str, strlen( str)); + + /* send the x-audiocast headers */ + str = "\nx-audiocast-bitrate: "; + sink->write( str, strlen( str)); + if ( log10(getBitRate()) >= (STRBUF_SIZE-2) ) { + throw Exception( __FILE__, __LINE__, + "bitrate does not fit string buffer", getBitRate()); + } + sprintf( resp, "%d", getBitRate()); + sink->write( resp, strlen( resp)); + + str = "\nx-audiocast-public: "; + sink->write( str, strlen( str)); + str = getIsPublic() ? "1" : "0"; + sink->write( str, strlen( str)); + + if ( getName() ) { + str = "\nx-audiocast-name: "; + sink->write( str, strlen( str)); + str = getName(); + sink->write( str, strlen( str)); + } + + if ( getDescription() ) { + str = "\nx-audiocast-description: "; + sink->write( str, strlen( str)); + str = getDescription(); + sink->write( str, strlen( str)); + } + + if ( getUrl() ) { + str = "\nx-audiocast-url: "; + sink->write( str, strlen( str)); + str = getUrl(); + sink->write( str, strlen( str)); + } + + if ( getGenre() ) { + str = "\nx-audiocast-genre: "; + sink->write( str, strlen( str)); + str = getGenre(); + sink->write( str, strlen( str)); + } + + if ( getRemoteDumpFile() ) { + str = "\nx-audiocast-dumpfile: "; + sink->write( str, strlen( str)); + str = getRemoteDumpFile(); + sink->write( str, strlen( str)); + } + + str = "\n\n"; + sink->write( str, strlen( str)); + sink->flush(); + + /* read the anticipated response: "OK" */ + len = source->read( resp, STRBUF_SIZE); + + reportEvent(5,resp); + + if ( Util::strEq( resp, "ERROR - Bad Password",20) ) { + throw Exception( __FILE__, __LINE__, + "Icecast - wrong password"); + } + if ( Util::strEq( resp, "ERROR - Mount Point Taken or Inv",32) ) { + throw Exception( __FILE__, __LINE__, + "Icecast - Mount point taken or invalid"); + } + if ( len < 2 || resp[0] != 'O' || resp[1] != 'K' ) { + return false; + } + + /* suck anything that the other side has to say */ + while ( source->canRead( 0, 0) && + (len = source->read( resp, STRBUF_SIZE)) ) { + ; + } + + + return true; +} + + diff --git a/darkice/tags/darkice-1_3/src/IceCast.h b/darkice/tags/darkice-1_3/src/IceCast.h new file mode 100644 index 0000000..5d3eb1d --- /dev/null +++ b/darkice/tags/darkice-1_3/src/IceCast.h @@ -0,0 +1,259 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : IceCast.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef ICE_CAST_H +#define ICE_CAST_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Sink.h" +#include "TcpSocket.h" +#include "CastSink.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * Class representing output to an IceCast server with + * x-audiocast login + * + * @author $Author$ + * @version $Revision$ + */ +class IceCast : public CastSink +{ + private: + + /** + * Mount point of the stream on the server. + */ + char * mountPoint; + + /** + * Remote dump file if any. + */ + char * remoteDumpFile; + + /** + * Description of the stream. + */ + char * description; + + /** + * Initalize the object. + * + * @param mountPoint mount point of the stream on the server. + * @param remoteDumpFile remote dump file (may be NULL). + * @param description description of the stream. + * @exception Exception + */ + void + init ( const char * mountPoint, + const char * description, + const char * remoteDumpFile ) + throw ( Exception ); + + /** + * De-initalize the object. + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + IceCast ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Log in to the server using the socket avialable. + * + * @return true if login was successful, false otherwise. + * @exception Exception + */ + virtual bool + sendLogin ( void ) throw ( Exception ); + + + public: + + /** + * Constructor. + * + * @param socket socket connection to the server. + * @param password password to the server. + * @param mountPoint mount point of the stream on the server. + * @param remoteDumpFile remote dump file (may be NULL). + * @param name name of the stream. + * @param description description of the stream. + * @param url URL associated with the stream. + * @param genre genre of the stream. + * @param bitRate bitrate of the stream (e.g. mp3 bitrate). + * @param isPublic is the stream public? + * @param streamDump an optional sink to dump the binary stream + * data to. + * @param bufferDuration duration of the BufferedSink buffer + * in seconds. + * @exception Exception + */ + inline + IceCast ( TcpSocket * socket, + const char * password, + const char * mountPoint, + unsigned int bitRate, + const char * name = 0, + const char * description = 0, + const char * url = 0, + const char * genre = 0, + bool isPublic = false, + const char * remoteDumpFile = 0, + Sink * streamDump = 0 ) + throw ( Exception ) + : CastSink( socket, + password, + bitRate, + name, + url, + genre, + isPublic, + streamDump ) + { + init( mountPoint, description, remoteDumpFile); + } + + /** + * Copy constructor. + * + * @param cs the IceCast to copy. + */ + inline + IceCast( const IceCast & cs ) throw ( Exception ) + : CastSink( cs ) + { + init( cs.getMountPoint(), + cs.getDescription(), + cs.getRemoteDumpFile() ); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~IceCast( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param cs the IceCast to assign this to. + * @return a reference to this IceCast. + * @exception Exception + */ + inline virtual IceCast & + operator= ( const IceCast & cs ) throw ( Exception ) + { + if ( this != &cs ) { + strip(); + CastSink::operator=( cs ); + init( cs.getMountPoint(), + cs.getDescription(), + cs.getRemoteDumpFile() ); + } + return *this; + } + + /** + * Get the mount point of the stream on the server. + * + * @return the mount point of the stream on the server. + */ + inline const char * + getMountPoint ( void ) const throw () + { + return mountPoint; + } + + /** + * Get the remote dump file if any. + * + * @return the remote dump file. May be NULL. + */ + inline const char * + getRemoteDumpFile ( void ) const throw () + { + return remoteDumpFile; + } + + /** + * Get the description of the stream. + * + * @return the description of the stream. + */ + inline const char * + getDescription ( void ) const throw () + { + return description; + } + +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* ICE_CAST_H */ + diff --git a/darkice/tags/darkice-1_3/src/IceCast2.cpp b/darkice/tags/darkice-1_3/src/IceCast2.cpp new file mode 100644 index 0000000..da86035 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/IceCast2.cpp @@ -0,0 +1,273 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : IceCast2.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STDIO_H +#include +#else +#error need stdio.h +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + +#ifdef HAVE_MATH_H +#include +#else +#error need math.h +#endif + + +#include "Exception.h" +#include "Source.h" +#include "Sink.h" +#include "Util.h" +#include "IceCast2.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/*------------------------------------------------------------------------------ + * Expected positive response from server begins like this. + *----------------------------------------------------------------------------*/ +static const char responseOK[] = "HTTP/1.0 200"; +static const char responseWrongPasswd[] = "HTTP/1.0 401"; +static const char responseForbidden[] = "HTTP/1.0 403"; + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +IceCast2 :: init ( StreamFormat format, + const char * mountPoint, + const char * description ) + throw ( Exception ) +{ + this->format = format; + this->mountPoint = Util::strDup( mountPoint); + this->description = description ? Util::strDup( description) : 0; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +IceCast2 :: strip ( void ) throw ( Exception ) +{ + delete[] mountPoint; + if ( description ) { + delete[] description; + } +} + + +/*------------------------------------------------------------------------------ + * Log in to the IceCast2 server + *----------------------------------------------------------------------------*/ +bool +IceCast2 :: sendLogin ( void ) throw ( Exception ) +{ + Sink * sink = getSink(); + Source * source = getSocket(); + const char * str; + const int buflen = 1024; // some small buffer size + char resp[buflen]; // a little buffer + unsigned int len; + unsigned int lenExpected; + + if ( !source->isOpen() ) { + return false; + } + if ( !sink->isOpen() ) { + return false; + } + + // send the request, a string like: + // "SOURCE ICE/1.0" + str = "SOURCE /"; + sink->write( str, strlen( str)); + str = getMountPoint(); + sink->write( str, strlen( str)); + str = " HTTP/1.0"; + sink->write( str, strlen( str)); + + // send the content type, Ogg Vorbis + str = "\nContent-type: "; + sink->write( str, strlen( str)); + switch ( format ) { + case mp3: + case mp2: + str = "audio/mpeg"; + break; + + case oggVorbis: + str = "application/ogg"; + break; + + case oggOpus: + str = "application/ogg"; + break; + + case aac: + str = "audio/aac"; + break; + + case aacp: + str = "audio/aacp"; + break; + + default: + throw Exception( __FILE__, __LINE__, + "unsupported stream format", format); + break; + } + sink->write( str, strlen( str)); + + // send the authentication info + str = "\nAuthorization: Basic "; + sink->write( str, strlen(str)); + { + // send source: encoded as base64 + const char * source = "source:"; + const char * pwd = getPassword(); + char * tmp = new char[Util::strLen(source) + + Util::strLen(pwd) + 1]; + Util::strCpy( tmp, source); + Util::strCat( tmp, pwd); + char * base64 = Util::base64Encode( tmp); + delete[] tmp; + sink->write( base64, strlen(base64)); + delete[] base64; + } + + // send user agent info + str = "\nUser-Agent: DarkIce/" VERSION " (http://code.google.com/p/darkice/)"; + sink->write( str, strlen( str)); + + // send the ice- headers + str = "\nice-bitrate: "; + sink->write( str, strlen( str)); + + sprintf( resp, "%d", getBitRate()); + sink->write( resp, strlen( resp)); + + str = "\nice-public: "; + sink->write( str, strlen( str)); + str = getIsPublic() ? "1" : "0"; + sink->write( str, strlen( str)); + + if ( getName() ) { + str = "\nice-name: "; + sink->write( str, strlen( str)); + str = getName(); + sink->write( str, strlen( str)); + } + + if ( getDescription() ) { + str = "\nice-description: "; + sink->write( str, strlen( str)); + str = getDescription(); + sink->write( str, strlen( str)); + } + + if ( getUrl() ) { + str = "\nice-url: "; + sink->write( str, strlen( str)); + str = getUrl(); + sink->write( str, strlen( str)); + } + + if ( getGenre() ) { + str = "\nice-genre: "; + sink->write( str, strlen( str)); + str = getGenre(); + sink->write( str, strlen( str)); + } + + str = "\r\n\r\n"; + sink->write( str, strlen( str)); + sink->flush(); + + // read the response, expected response begins with responseOK + lenExpected = Util::strLen( responseOK); + if ( (len = source->read( resp, buflen )) < lenExpected ) { + return false; // short read, no need to continue + } + resp[lenExpected] = '\x00'; // end string, truncate to expected length + + reportEvent(5,resp); + + if ( Util::strEq( resp, responseWrongPasswd) ) { + throw Exception( __FILE__, __LINE__, + "Icecast2 - wrong password"); + } + + if ( Util::strEq( resp, responseForbidden) ) { + throw Exception( __FILE__, __LINE__, + "Icecast2 - forbidden. Is the mountpoint occupied, or maximum sources reached?"); + } + + if ( !Util::strEq( resp, responseOK) ) { + // some unexpected response from server + throw Exception( __FILE__, __LINE__, + "Icecast2 - Unexpected response from server"); + } + + // suck anything that the other side has to say + while ( source->canRead( 0, 0) && + (len = source->read( resp, buflen ))); + + // all is well, we are connected + return true; +} + + diff --git a/darkice/tags/darkice-1_3/src/IceCast2.h b/darkice/tags/darkice-1_3/src/IceCast2.h new file mode 100644 index 0000000..9719815 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/IceCast2.h @@ -0,0 +1,267 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : IceCast2.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef ICE_CAST2_H +#define ICE_CAST2_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Sink.h" +#include "TcpSocket.h" +#include "CastSink.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * Class representing output to an IceCast2 server with + * ice login + * + * @author $Author$ + * @version $Revision$ + */ +class IceCast2 : public CastSink +{ + public: + + /** + * Type for specifying the format of the stream. + */ + enum StreamFormat { mp3, mp2, oggVorbis, oggOpus, aac, aacp }; + + + private: + + /** + * The format of the stream. + */ + StreamFormat format; + + /** + * Mount point of the stream on the server. + */ + char * mountPoint; + + /** + * Description of the stream. + */ + char * description; + + /** + * Initalize the object. + * + * @param mountPoint mount point of the stream on the server. + * @param remoteDumpFile remote dump file (may be NULL). + * @param description description of the stream. + * @exception Exception + */ + void + init ( StreamFormat format, + const char * mountPoint, + const char * description ) + throw ( Exception ); + + /** + * De-initalize the object. + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + IceCast2 ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Log in to the server using the socket avialable. + * + * @return true if login was successful, false otherwise. + * @exception Exception + */ + virtual bool + sendLogin ( void ) throw ( Exception ); + + + public: + + /** + * Constructor. + * + * @param socket socket connection to the server. + * @param password password to the server. + * @param mountPoint mount point of the stream on the server. + * @param format the format of the stream. + * @param name name of the stream. + * @param description description of the stream. + * @param url URL associated with the stream. + * @param genre genre of the stream. + * @param bitRate bitrate of the stream (e.g. mp3 bitrate). + * @param isPublic is the stream public? + * @param streamDump an optional sink to dump the binary stream + * data to. + * @param bufferDuration duration of the BufferedSink buffer + * in seconds. + * @exception Exception + */ + inline + IceCast2 ( TcpSocket * socket, + const char * password, + const char * mountPoint, + StreamFormat format, + unsigned int bitRate, + const char * name = 0, + const char * description = 0, + const char * url = 0, + const char * genre = 0, + bool isPublic = false, + Sink * streamDump = 0 ) + throw ( Exception ) + : CastSink( socket, + password, + bitRate, + name, + url, + genre, + isPublic, + streamDump ) + { + init( format, mountPoint, description); + } + + /** + * Copy constructor. + * + * @param cs the IceCast2 to copy. + */ + inline + IceCast2( const IceCast2 & cs ) throw ( Exception ) + : CastSink( cs ) + { + init( cs.getFormat(), + cs.getMountPoint(), + cs.getDescription() ); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~IceCast2( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param cs the IceCast2 to assign this to. + * @return a reference to this IceCast2. + * @exception Exception + */ + inline virtual IceCast2 & + operator= ( const IceCast2 & cs ) throw ( Exception ) + { + if ( this != &cs ) { + strip(); + CastSink::operator=( cs ); + init( cs.getFormat(), + cs.getMountPoint(), + cs.getDescription() ); + } + return *this; + } + + /** + * Get the format of the stream. + * + * @return the format of the stream. + */ + inline StreamFormat + getFormat ( void ) const throw () + { + return format; + } + + /** + * Get the mount point of the stream on the server. + * + * @return the mount point of the stream on the server. + */ + inline const char * + getMountPoint ( void ) const throw () + { + return mountPoint; + } + + /** + * Get the description of the stream. + * + * @return the description of the stream. + */ + inline const char * + getDescription ( void ) const throw () + { + return description; + } + +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* ICE_CAST2_H */ + diff --git a/darkice/tags/darkice-1_3/src/JackDspSource.cpp b/darkice/tags/darkice-1_3/src/JackDspSource.cpp new file mode 100644 index 0000000..9cca161 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/JackDspSource.cpp @@ -0,0 +1,506 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Copyright (c) 2005 Nicholas Humfrey. All rights reserved. + + Tyrell DarkIce + + File : JackDspSource.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#include "AudioSource.h" + +#ifdef SUPPORT_JACK_DSP +// only compile this code if there is support for it + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STDIO_H +#include +#else +#error need stdio.h +#endif + +#ifdef HAVE_UNISTD_H +#include +#else +#error need unistd.h +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#else +#error need sys/types.h +#endif + +#ifdef HAVE_MATH_H +#include +#else +#error need math.h +#endif + +#ifdef HAVE_STDLIB_H +#include +#else +#error needs stdlib.h +#endif + +#ifdef HAVE_LIMITS_H +#include +#else +#error need limits.h +#endif + +#ifdef HAVE_STDIO_H +#include +#endif + +#include + +#include "Util.h" +#include "Exception.h" +#include "JackDspSource.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +JackDspSource :: init ( const char* name ) throw ( Exception ) +{ + // Set defaults + ports[0] = NULL; // Left Port + ports[1] = NULL; // Right Port + rb[0] = NULL; // Left Ring Buffer + rb[1] = NULL; // Right Ring Buffer + client = NULL; + auto_connect = false; // Default is to not auto connect the JACK ports + tmp_buffer = NULL; // Buffer big enough for one 'read' of audio + + // Auto connect the ports ? + if ( Util::strEq( name, "jack_auto", 9) ) { + auto_connect = true; + } + + // Check the sample size + if (getBitsPerSample() != 16) { + throw Exception( __FILE__, __LINE__, + "JackDspSource doesn't support non 16-bit samples"); + } +} + + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +JackDspSource :: strip ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + // Free the temporary buffer + if (tmp_buffer) { + free(tmp_buffer); + tmp_buffer = NULL; + } + +} + +/*------------------------------------------------------------------------------ + * Attempt to connect up the JACK ports automatically + * - Just connect left&right to the first two output ports we find + *----------------------------------------------------------------------------*/ +void +JackDspSource :: do_auto_connect ( void ) throw ( Exception ) +{ + const char **all_ports; + unsigned int ch = 0; + int i; + + Reporter::reportEvent( 10, "JackDspSource :: do_auto_connect"); + + // Get a list of all the jack ports + all_ports = jack_get_ports (client, NULL, NULL, JackPortIsOutput); + if (!ports) { + throw Exception( __FILE__, __LINE__, "jack_get_ports() returned NULL."); + } + + // Step through each port name + for (i = 0; all_ports[i]; ++i) { + + const char* in = all_ports[i]; + const char* out = jack_port_name( ports[ch] ); + + Reporter::reportEvent( 2, "Connecting", in, "to", out); + + if (jack_connect(client, in, out)) { + throw Exception( __FILE__, __LINE__, + "Failed to jack_connect() ports", in, out); + } + + // Found enough ports ? + if (++ch >= getChannel()) break; + } + + free( all_ports ); + +} + + +/*------------------------------------------------------------------------------ + * Open the audio source + *----------------------------------------------------------------------------*/ +bool +JackDspSource :: open ( void ) throw ( Exception ) +{ + char client_name[255]; + size_t rb_size; + unsigned int c; + + if ( isOpen() ) { + return false; + } + + // Register client with Jack + if ( jack_client_name != NULL ) { + snprintf(client_name, 255, "%s", jack_client_name); + } else { + snprintf(client_name, 255, "darkice-%d", getpid()); + } + + if ((client = jack_client_open(client_name, (jack_options_t)0, NULL)) == NULL) { + throw Exception( __FILE__, __LINE__, "JACK server not running?"); + } + Reporter::reportEvent( 1, "Registering as JACK client", client_name); + + + // Check the sample rate is correct + if (jack_get_sample_rate( client ) != (jack_nframes_t)getSampleRate()) { + throw Exception( __FILE__, __LINE__, + "JACK server sample rate is different than " + "sample rate in darkice config file"); + } + + + // Register ports with Jack + if (getChannel() == 1) { + if (!(ports[0] = jack_port_register(client, + "mono", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, + 0))) { + throw Exception( __FILE__, __LINE__, + "Cannot register input port", "mono"); + } + } else if (getChannel() == 2) { + if (!(ports[0] = jack_port_register(client, + "left", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, + 0))) { + throw Exception( __FILE__, __LINE__, + "Cannot register input port", "left"); + } + if (!(ports[1] = jack_port_register(client, + "right", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, 0))) { + throw Exception( __FILE__, __LINE__, + "Cannot register input port", "right"); + } + } else { + throw Exception( __FILE__, __LINE__, + "Invalid number of channels", getChannel()); + } + + + // Create a ring buffer for each channel + /* will take about 1 MB buffer for each channel */ + rb_size = 5 /* number of seconds */ + * jack_get_sample_rate(client) /* eg 48000 */ + * sizeof (jack_default_audio_sample_t); /* eg 4 bytes */ + + for (c=0; c < getChannel(); c++) { + rb[c] = jack_ringbuffer_create(rb_size); + if (!rb[c]) { + throw Exception( __FILE__, __LINE__, + "Failed to create ringbuffer for", "channel", c); + } + } + + + // Set the callbacks + jack_on_shutdown(client, JackDspSource::shutdown_callback, (void*)this); + if (jack_set_process_callback(client, + JackDspSource::process_callback, + (void*)this)) { + throw Exception( __FILE__, __LINE__, "Failed to set process callback"); + } + + // Activate client + if (jack_activate(client)) { + throw Exception( __FILE__, __LINE__, "Can't activate client"); + } + + // Attempt to automatically connect up our input ports to something ? + if (auto_connect) { + do_auto_connect(); + } + + return true; +} + + +/*------------------------------------------------------------------------------ + * Check whether read() would return anything + *----------------------------------------------------------------------------*/ +bool +JackDspSource :: canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ) +{ + const unsigned int max_wait_time = sec * 1000000; + const unsigned int wait_increment = 10000; + unsigned int cur_wait = 0; + + if ( !isOpen() ) { + return false; + } + + while (max_wait_time > cur_wait) { + bool canRead = true; + + for (unsigned int c = 0 ; c < getChannel() ; c++) { + if (jack_ringbuffer_read_space(rb[c]) <= 0) { + canRead = false; + } + } + + if (canRead) { + return true; + } + + cur_wait += wait_increment; + usleep ( wait_increment ); + } + + usleep( usec ); + for (unsigned int c = 0 ; c < getChannel() ; c++) { + if (jack_ringbuffer_read_space(rb[c]) <= 0) { + return false; + } + } + + return true; +} + + +/*------------------------------------------------------------------------------ + * Read from the audio source + *----------------------------------------------------------------------------*/ +unsigned int +JackDspSource :: read ( void * buf, + unsigned int len ) throw ( Exception ) +{ + jack_nframes_t samples = len / 2 / getChannel(); + jack_nframes_t samples_read[2] = { 0, 0 }; + short * output = (short*) buf; + unsigned int c, n; + + if ( !isOpen() ) { + return 0; + } + + + // Ensure the temporary buffer is big enough + tmp_buffer = (jack_default_audio_sample_t*)realloc(tmp_buffer, + samples * sizeof( jack_default_audio_sample_t ) ); + if (!tmp_buffer) { + throw Exception( __FILE__, __LINE__, "realloc on tmp_buffer failed"); + } + + // We must be sure to fetch as many data on both channels + int minBytesAvailable = samples * sizeof( jack_default_audio_sample_t ); + + for (c=0; c < getChannel(); c++) { + int readable = jack_ringbuffer_read_space(rb[c]); + if (readable < minBytesAvailable) { + minBytesAvailable = readable; + } + } + + for (c=0; c < getChannel(); c++) { + // Copy frames from ring buffer to temporary buffer + // and then convert samples to output buffer + int bytes_read = jack_ringbuffer_read(rb[c], + (char*)tmp_buffer, + minBytesAvailable); + samples_read[c] = bytes_read / sizeof( jack_default_audio_sample_t ); + + + // Convert samples from float to short and put in output buffer + for(n=0; n SHRT_MAX) { + output[n*getChannel()+c] = SHRT_MAX; + } else if (tmp < SHRT_MIN) { + output[n*getChannel()+c] = SHRT_MIN; + } else { + output[n*getChannel()+c] = (short) tmp; + } + } + } + + // Didn't get as many samples as we wanted ? + if (getChannel() == 2 && samples_read[0] != samples_read[1]) { + Reporter::reportEvent( 2, + "Warning: Read a different number of samples " + "for left and right channels"); + } + + // Return the number of bytes put in the output buffer + return samples_read[0] * 2 * getChannel(); +} + + +/*------------------------------------------------------------------------------ + * Close the audio source + *----------------------------------------------------------------------------*/ +void +JackDspSource :: close ( void ) throw ( Exception ) +{ + unsigned int i; + + if ( !isOpen() ) { + return; + } + + for(i = 0; i < getChannel(); i++) { + // Close the port for channel + if ( ports[i] ) { + jack_port_unregister( client, ports[i] ); + ports[i] = NULL; + } + + // Free up the ring buffer for channel + if ( rb[i] ) { + jack_ringbuffer_free( rb[i] ); + rb[i] = NULL; + } + } + + /* Leave the jack graph */ + if (client) { + jack_client_close(client); + client = NULL; + } + +} + + +/*------------------------------------------------------------------------------ + * Callback called by JACK when audio is available + * + * Don't do anything too expensive here + * - just shove audio samples in ring buffer + *----------------------------------------------------------------------------*/ +int +JackDspSource :: process_callback( jack_nframes_t nframes, void *arg ) +{ + JackDspSource* self = (JackDspSource*)arg; + size_t to_write = sizeof (jack_default_audio_sample_t) * nframes; + unsigned int c; + + // Wait until it is ready + if (self->client == NULL) { + return 0; + } + + /* copy data to ringbuffer; one per channel */ + for (c=0; c < self->getChannel(); c++) { + /* check space */ + size_t len; + if (jack_ringbuffer_write_space(self->rb[c]) < to_write) { + /* buffer is overflowing, skip the incoming data */ + jack_ringbuffer_write_advance(self->rb[c], to_write); + /* prevent blocking the ring buffer by updating internal pointers + * jack will now not terminate on xruns + */ + Reporter::reportEvent( 1, "ring buffer full, skipping data"); + /* We do not return error to jack callback handler and keep going */ + } else { + /* buffer has space, put data into ringbuffer */ + len = jack_ringbuffer_write(self->rb[c], (char *) jack_port_get_buffer( + self->ports[c], nframes), to_write); + if (len != to_write) + Reporter::reportEvent( 1, "failed to write to ring buffer (can not happen)"); + } + } + + // Success + return 0; +} + +/*------------------------------------------------------------------------------ + * Callback called when + *----------------------------------------------------------------------------*/ +void +JackDspSource :: shutdown_callback( void *arg ) +{ + //JackDspSource* self = (JackDspSource*)arg; + + Reporter::reportEvent( 1, "JackDspSource :: shutdown_callback"); +} + + +#endif // SUPPORT_JACK_DSP + diff --git a/darkice/tags/darkice-1_3/src/JackDspSource.h b/darkice/tags/darkice-1_3/src/JackDspSource.h new file mode 100644 index 0000000..c7df3e6 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/JackDspSource.h @@ -0,0 +1,284 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Copyright (c) 2005 Nicholas Humfrey. All rights reserved. + + Tyrell DarkIce + + File : JackDspSource.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef JACK_DSP_SOURCE_H +#define JACK_DSP_SOURCE_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + + +#include "Reporter.h" +#include "AudioSource.h" + +#if defined( HAVE_JACK_LIB ) +#include +#include +#else +#error configure for JACK +#endif + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * An audio input based on JACK + * + * @author $Author$ + * @version $Revision$ + */ +class JackDspSource : public AudioSource, public virtual Reporter +{ + private: + /** + * The jack client name. + */ + const char * jack_client_name; + + /** + * The jack port + */ + jack_port_t * ports[2]; + + /** + * The jack ring buffer. + */ + jack_ringbuffer_t * rb[2]; + + /** + * The jack client. + */ + jack_client_t * client; + + /** + * The jack audio sample buffer. + */ + jack_default_audio_sample_t * tmp_buffer; + + /** + * Automatically connect the jack ports ? (default is to not) + */ + bool auto_connect; + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + JackDspSource ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Initialize the object + * + * @exception Exception + */ + void + init ( const char* name ) throw ( Exception ); + + /** + * De-initialize the object + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + /** + * Attempt to connect up the JACK ports automatically + */ + void + do_auto_connect( ) throw ( Exception ); + + /** + * Callback called by JACK when audio is available + */ + static int + process_callback( jack_nframes_t nframes, void *arg ); + + + /** + * Callback called by JACK when jackd is shutting down + */ + static void + shutdown_callback( void *arg ); + + public: + + /** + * Constructor. + * + * @param name the name of the jack device + * @param sampleRate samples per second (e.g. 44100 for 44.1kHz). + * @param bitsPerSample bits per sample (e.g. 16 bits). + * @param channels number of channels of the audio source + * (e.g. 1 for mono, 2 for stereo, etc.). + * @exception Exception + */ + inline + JackDspSource ( const char * name, + const char * jackClientName, + int sampleRate = 44100, + int bitsPerSample = 16, + int channels = 2 ) + throw ( Exception ) + + : AudioSource( sampleRate, bitsPerSample, channels ) + { + jack_client_name = jackClientName; + init( name ); + } + + /** + * Copy Constructor. + * + * @param jds the object to copy. + * @exception Exception + */ + inline + JackDspSource ( const JackDspSource & jds ) throw ( Exception ) + : AudioSource( jds ) + { + throw Exception( __FILE__, __LINE__, "JackDspSource doesn't copy"); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~JackDspSource ( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param ds the object to assign to this one. + * @return a reference to this object. + * @exception Exception + */ + inline virtual JackDspSource & + operator= ( const JackDspSource & ds ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__, "JackDspSource doesn't assign"); + } + + /** + * Open the JackDspSource. + * This does not put the Jack DSP device into recording mode. + * To start getting samples, call either canRead() or read(). + * + * @return true if opening was successful, false otherwise + * @exception Exception + * + * @see #canRead + * @see #read + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the JackDspSource is registered + * + * @return true if Jack client is setup + */ + inline virtual bool + isOpen ( void ) const throw () + { + return client != NULL; + } + + /** + * Check if the JackDspSource can be read from. + * Blocks until the specified time for data to be available. + * Puts the Jack DSP device into recording mode. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the JackDspSource is ready to be read from, + * false otherwise. + * @exception Exception + */ + virtual bool + canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ); + + /** + * Read from the JackDspSource. + * Puts the Jack DSP device into recording mode. + * + * @param buf the buffer to read into. + * @param len the number of bytes to read into buf + * @return the number of bytes read (may be less than len). + * @exception Exception + */ + virtual unsigned int + read ( void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Close the JackDspSource. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); + +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* JACK_DSP_SOURCE_H */ + diff --git a/darkice/tags/darkice-1_3/src/LameLibEncoder.cpp b/darkice/tags/darkice-1_3/src/LameLibEncoder.cpp new file mode 100644 index 0000000..688c2aa --- /dev/null +++ b/darkice/tags/darkice-1_3/src/LameLibEncoder.cpp @@ -0,0 +1,396 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : LameLibEncoder.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// compile the whole file only if lame support configured in +#ifdef HAVE_LAME_LIB + + + +#include "Exception.h" +#include "Util.h" +#include "LameLibEncoder.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Open an encoding session + *----------------------------------------------------------------------------*/ +bool +LameLibEncoder :: open ( void ) + throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + // open the underlying sink + if ( !getSink()->open() ) { + throw Exception( __FILE__, __LINE__, + "lame lib opening underlying sink error"); + } + + lameGlobalFlags = lame_init(); + + // ugly lame returns -1 in a pointer on allocation errors + // this is cast to (long int) so that the pointer can be handled + // on 64 bit systems as well + if ( !lameGlobalFlags || ((long int)lameGlobalFlags) == -1 ) { + throw Exception( __FILE__, __LINE__, + "lame lib init error", + (long int) lameGlobalFlags); + } + + if ( 0 > lame_set_num_channels( lameGlobalFlags, getInChannel()) ) { + throw Exception( __FILE__, __LINE__, + "lame lib setting channels error", + getInChannel() ); + } + + if ( 0 > lame_set_mode( lameGlobalFlags, + getOutChannel() == 1 ? MONO : JOINT_STEREO) ) { + throw Exception( __FILE__, __LINE__, + "lame lib setting mode error", + JOINT_STEREO ); + } + + reportEvent( 5, "set lame mode", lame_get_mode( lameGlobalFlags)); + + reportEvent( 5, + "set lame channels", + lame_get_num_channels( lameGlobalFlags)); + + if ( 0 > lame_set_in_samplerate( lameGlobalFlags, getInSampleRate()) ) { + throw Exception( __FILE__, __LINE__, + "lame lib setting input sample rate error", + getInSampleRate() ); + } + + reportEvent( 5, + "set lame in sample rate", + lame_get_in_samplerate( lameGlobalFlags)); + + if ( 0 > lame_set_out_samplerate( lameGlobalFlags, getOutSampleRate()) ) { + throw Exception( __FILE__, __LINE__, + "lame lib setting output sample rate error", + getOutSampleRate() ); + } + + reportEvent( 5, + "set lame out sample rate", + lame_get_out_samplerate( lameGlobalFlags)); + + switch ( getOutBitrateMode() ) { + + case cbr: { + + if ( 0 > lame_set_brate( lameGlobalFlags, getOutBitrate()) ) { + throw Exception( __FILE__, __LINE__, + "lame lib setting output bit rate error", + getOutBitrate() ); + } + + reportEvent( 5, + "set lame bit rate", + lame_get_brate( lameGlobalFlags)); + + double d = (1.0 - getOutQuality()) * 10.0; + + if ( d > 9 ) { + d = 9; + } + + int q = int (d); + + if ( 0 > lame_set_quality( lameGlobalFlags, q) ) { + throw Exception( __FILE__, __LINE__, + "lame lib setting quality error", q); + } + + reportEvent( 5, + "set lame quality", + lame_get_quality( lameGlobalFlags)); + } break; + + case abr: + + if ( 0 > lame_set_VBR( lameGlobalFlags,vbr_abr)) { + throw Exception( __FILE__, __LINE__, + "lame lib setting abr error", vbr_abr); + } + + reportEvent( 5, + "set lame abr bitrate", + lame_get_VBR( lameGlobalFlags)); + + if ( 0 > lame_set_VBR_mean_bitrate_kbps( lameGlobalFlags, + getOutBitrate())) { + throw Exception( __FILE__, __LINE__, + "lame lib setting abr mean bitrate error", + getOutBitrate()); + } + + reportEvent( 5, + "set lame abr mean bitrate", + lame_get_VBR_mean_bitrate_kbps( lameGlobalFlags)); + break; + + case vbr: { + + if ( 0 > lame_set_VBR( lameGlobalFlags, vbr_mtrh)) { + throw Exception( __FILE__, __LINE__, + "lame lib setting vbr error", vbr_mtrh ); + } + + reportEvent( 5, + "set lame vbr bitrate", + lame_get_VBR( lameGlobalFlags)); + + double d = (1.0 - getOutQuality()) * 10.0; + + if ( d > 9 ) { + d = 9; + } + + int q = int (d); + + if ( 0 > lame_set_VBR_q( lameGlobalFlags, q) ) { + throw Exception( __FILE__, __LINE__, + "lame lib setting vbr quality error", q); + } + + reportEvent( 5, + "set lame vbr quality", + lame_get_VBR_q( lameGlobalFlags)); + } break; + } + + + if ( 0 > lame_set_lowpassfreq( lameGlobalFlags, lowpass) ) { + throw Exception( __FILE__, __LINE__, + "lame lib setting lowpass frequency error", + lowpass ); + } + + reportEvent( 5, + "set lame lowpass frequency", + lame_get_lowpassfreq( lameGlobalFlags)); + + if ( 0 > lame_set_highpassfreq( lameGlobalFlags, highpass) ) { + throw Exception( __FILE__, __LINE__, + "lame lib setting highpass frequency error", + lowpass ); + } + + reportEvent( 5, + "set lame highpass frequency", + lame_get_highpassfreq( lameGlobalFlags)); + + + + + // not configurable lame settings + + if ( 0 > lame_set_exp_nspsytune( lameGlobalFlags, 1) ) { + throw Exception( __FILE__, __LINE__, + "lame lib setting psycho acoustic model error"); + } + + reportEvent( 5, + "set lame psycho acoustic model", + lame_get_exp_nspsytune( lameGlobalFlags)); + + if ( 0 > lame_set_error_protection( lameGlobalFlags, 1) ) { + throw Exception( __FILE__, __LINE__, + "lame lib setting error protection error", + 1 ); + } + + reportEvent( 5, + "set lame error protection", + lame_get_error_protection( lameGlobalFlags)); + + // let lame init its own params based on our settings + if ( 0 > lame_init_params( lameGlobalFlags) ) { + throw Exception( __FILE__, __LINE__, + "lame lib initializing params error" ); + } + + if (getReportVerbosity() >= 3) { + lame_print_config( lameGlobalFlags); + } + + return true; +} + + +/*------------------------------------------------------------------------------ + * Write data to the encoder + *----------------------------------------------------------------------------*/ +unsigned int +LameLibEncoder :: write ( const void * buf, + unsigned int len ) throw ( Exception ) +{ + if ( !isOpen() || len == 0 ) { + return 0; + } + + unsigned int bitsPerSample = getInBitsPerSample(); + unsigned int inChannels = getInChannel(); + + unsigned int sampleSize = (bitsPerSample / 8) * inChannels; + unsigned char * b = (unsigned char*) buf; + unsigned int processed = len - (len % sampleSize); + unsigned int nSamples = processed / sampleSize; + short int * leftBuffer = new short int[nSamples]; + short int * rightBuffer = new short int[nSamples]; + + if ( bitsPerSample == 8 ) { + Util::conv8( b, processed, leftBuffer, rightBuffer, inChannels); + } else if ( bitsPerSample == 16 ) { + Util::conv16( b, + processed, + leftBuffer, + rightBuffer, + inChannels, + isInBigEndian()); + } else { + delete[] leftBuffer; + delete[] rightBuffer; + throw Exception( __FILE__, __LINE__, + "unsupported number of bits per sample for the encoder", + bitsPerSample ); + } + + // data chunk size estimate according to lame documentation + // NOTE: mp3Size is calculated based on the number of input channels + // which may be bigger than need, as output channels can be less + unsigned int mp3Size = (unsigned int) (1.25 * nSamples + 7200); + unsigned char * mp3Buf = new unsigned char[mp3Size]; + int ret; + + ret = lame_encode_buffer( lameGlobalFlags, + leftBuffer, + inChannels == 2 ? rightBuffer : leftBuffer, + nSamples, + mp3Buf, + mp3Size ); + + delete[] leftBuffer; + delete[] rightBuffer; + + if ( ret < 0 ) { + reportEvent( 3, "lame encoding error", ret); + delete[] mp3Buf; + return 0; + } + + unsigned int written = getSink()->write( mp3Buf, ret); + delete[] mp3Buf; + // just let go data that could not be written + if ( written < (unsigned int) ret ) { + reportEvent( 2, + "couldn't write all from encoder to underlying sink", + ret - written); + } + + return processed; +} + + +/*------------------------------------------------------------------------------ + * Flush the data from the encoder + *----------------------------------------------------------------------------*/ +void +LameLibEncoder :: flush ( void ) + throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + // data chunk size estimate according to lame documentation + unsigned int mp3Size = 7200; + unsigned char * mp3Buf = new unsigned char[mp3Size]; + int ret; + + ret = lame_encode_flush( lameGlobalFlags, mp3Buf, mp3Size ); + + unsigned int written = getSink()->write( mp3Buf, ret); + delete[] mp3Buf; + + // just let go data that could not be written + if ( written < (unsigned int) ret ) { + reportEvent( 2, + "couldn't write all from encoder to underlying sink", + ret - written); + } + + getSink()->flush(); +} + + +/*------------------------------------------------------------------------------ + * Close the encoding session + *----------------------------------------------------------------------------*/ +void +LameLibEncoder :: close ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + flush(); + lame_close( lameGlobalFlags); + lameGlobalFlags = 0; + + getSink()->close(); + } +} + + +#endif // HAVE_LAME_LIB + diff --git a/darkice/tags/darkice-1_3/src/LameLibEncoder.h b/darkice/tags/darkice-1_3/src/LameLibEncoder.h new file mode 100644 index 0000000..d744c95 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/LameLibEncoder.h @@ -0,0 +1,438 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : LameLibEncoder.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef LAME_LIB_ENCODER_H +#define LAME_LIB_ENCODER_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_LAME_LIB +#include +#else +#error configure with lame +#endif + + +#include "Ref.h" +#include "Exception.h" +#include "Reporter.h" +#include "AudioEncoder.h" +#include "Sink.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A class representing the lame encoder linked as a shared object or as + * a static library. + * + * @author $Author$ + * @version $Revision$ + */ +class LameLibEncoder : public AudioEncoder, public virtual Reporter +{ + private: + + /** + * Lame library global flags + */ + lame_global_flags * lameGlobalFlags; + + /** + * Lowpass filter. Sound frequency in Hz, from where up the + * input is cut. + */ + int lowpass; + + /** + * Highpass filter. Sound frequency in Hz, from where down the + * input is cut. + */ + int highpass; + + /** + * Initialize the object. + * + * @param lowpass frequency threshold for the lowpass filter. + * Input above this frequency is cut. + * If 0, lame's default values are used, + * which depends on the out sample rate. + * @param highpass frequency threshold for the highpass filter. + * Input below this frequency is cut. + * If 0, lame's default values are used, + * which depends on the out sample rate. + * @exception Exception + */ + inline void + init ( int lowpass, + int highpass ) throw ( Exception ) + { + this->lameGlobalFlags = NULL; + this->lowpass = lowpass; + this->highpass = highpass; + + if ( getInBitsPerSample() != 16 && getInBitsPerSample() != 8 ) { + throw Exception( __FILE__, __LINE__, + "specified bits per sample not supported", + getInBitsPerSample() ); + } + + if ( getInChannel() != 1 && getInChannel() != 2 ) { + throw Exception( __FILE__, __LINE__, + "unsupported number of input channels for the encoder", + getInChannel() ); + } + if ( getOutChannel() != 1 && getOutChannel() != 2 ) { + throw Exception( __FILE__, __LINE__, + "unsupported number of output channels for the encoder", + getOutChannel() ); + } + if ( getInChannel() < getOutChannel() ) { + throw Exception( __FILE__, __LINE__, + "output channels greater then input channels", + getOutChannel() ); + } + } + + /** + * De-initialize the object. + * + * @exception Exception + */ + inline void + strip ( void ) throw ( Exception ) + { + } + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + LameLibEncoder ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + + public: + + /** + * Constructor. + * + * @param sink the sink to send mp3 output to + * @param inSampleRate sample rate of the input. + * @param inBitsPerSample number of bits per sample of the input. + * @param inChannel number of channels of the input. + * @param inBigEndian shows if the input is big or little endian + * @param outBitrateMode the bit rate mode of the output. + * @param outBitrate bit rate of the output (kbits/sec). + * @param outQuality the quality of the stream. + * @param outSampleRate sample rate of the output. + * If 0, inSampleRate is used. + * @param outChannel number of channels of the output. + * If 0, inChannel is used. + * @param lowpass frequency threshold for the lowpass filter. + * Input above this frequency is cut. + * If 0, lame's default values are used, + * which depends on the out sample rate. + * @param highpass frequency threshold for the highpass filter. + * Input below this frequency is cut. + * If 0, lame's default values are used, + * which depends on the out sample rate. + * @exception Exception + */ + inline + LameLibEncoder ( Sink * sink, + unsigned int inSampleRate, + unsigned int inBitsPerSample, + unsigned int inChannel, + bool inBigEndian, + BitrateMode outBitrateMode, + unsigned int outBitrate, + double outQuality, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0, + int lowpass = 0, + int highpass = 0 ) + throw ( Exception ) + + : AudioEncoder ( sink, + inSampleRate, + inBitsPerSample, + inChannel, + inBigEndian, + outBitrateMode, + outBitrate, + outQuality, + outSampleRate, + outChannel ) + { + init( lowpass, highpass); + } + + /** + * Constructor. + * + * @param sink the sink to send mp3 output to + * @param as get input sample rate, bits per sample and channels + * from this AudioSource. + * @param outBitrateMode the bit rate mode of the output. + * @param outBitrate bit rate of the output (kbits/sec). + * @param outQuality the quality of the stream. + * @param outSampleRate sample rate of the output. + * If 0, input sample rate is used. + * @param outChannel number of channels of the output. + * If 0, input channel is used. + * @param lowpass frequency threshold for the lowpass filter. + * Input above this frequency is cut. + * If 0, lame's default values are used, + * which depends on the out sample rate. + * @param highpass frequency threshold for the highpass filter. + * Input below this frequency is cut. + * If 0, lame's default values are used, + * which depends on the out sample rate. + * @exception Exception + */ + inline + LameLibEncoder ( Sink * sink, + const AudioSource * as, + BitrateMode outBitrateMode, + unsigned int outBitrate, + double outQuality, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0, + int lowpass = 0, + int highpass = 0 ) + throw ( Exception ) + + : AudioEncoder ( sink, + as, + outBitrateMode, + outBitrate, + outQuality, + outSampleRate, + outChannel ) + { + init( lowpass, highpass); + } + + /** + * Copy constructor. + * + * @param encoder the LameLibEncoder to copy. + */ + inline + LameLibEncoder ( const LameLibEncoder & encoder ) + throw ( Exception ) + : AudioEncoder( encoder ) + { + init( encoder.lowpass, encoder.highpass ); + } + + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~LameLibEncoder ( void ) throw ( Exception ) + { + if ( isOpen() ) { + close(); + } + strip(); + } + + /** + * Assignment operator. + * + * @param encoder the LameLibEncoder to assign this to. + * @return a reference to this LameLibEncoder. + * @exception Exception + */ + inline virtual LameLibEncoder & + operator= ( const LameLibEncoder & encoder ) throw ( Exception ) + { + if ( this != &encoder ) { + strip(); + AudioEncoder::operator=( encoder); + init( encoder.lowpass, encoder.highpass ); + } + + return *this; + } + + /** + * Get the version string of the underlying lame library. + * + * @return the version string of the underlying lame library. + */ + inline const char * + getLameVersion( void ) + { + return get_lame_version(); + } + + /** + * Check whether encoding is in progress. + * + * @return true if encoding is in progress, false otherwise. + */ + inline virtual bool + isRunning ( void ) const throw () + { + return isOpen(); + } + + /** + * Start encoding. This function returns as soon as possible, + * with encoding started in the background. + * + * @return true if encoding has started, false otherwise. + * @exception Exception + */ + inline virtual bool + start ( void ) throw ( Exception ) + { + return open(); + } + + /** + * Stop encoding. Stops the encoding running in the background. + * + * @exception Exception + */ + inline virtual void + stop ( void ) throw ( Exception ) + { + return close(); + } + + /** + * Open an encoding session. + * + * @return true if opening was successfull, false otherwise. + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the encoding session is open. + * + * @return true if the encoding session is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return lameGlobalFlags != 0; + } + + /** + * Check if the encoder is ready to accept data. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the encoder is ready to accept data, + * false otherwise. + * @exception Exception + */ + inline virtual bool + canWrite ( unsigned int sec, + unsigned int usec ) throw ( Exception ) + { + if ( !isOpen() ) { + return false; + } + + return true; + } + + /** + * Write data to the encoder. + * Buf is expected to be a sequence of big-endian 16 bit values, + * with left and right channels interleaved. Len is the number of + * bytes, must be a multiple of 4. + * + * @param buf the data to write. + * @param len number of bytes to write from buf. + * @return the number of bytes written (may be less than len). + * @exception Exception + */ + virtual unsigned int + write ( const void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Flush all data that was written to the encoder to the underlying + * connection. + * + * @exception Exception + */ + virtual void + flush ( void ) throw ( Exception ); + + /** + * Close the encoding session. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + +#endif /* LAME_LIB_ENCODER_H */ + diff --git a/darkice/tags/darkice-1_3/src/Makefile.am b/darkice/tags/darkice-1_3/src/Makefile.am new file mode 100644 index 0000000..dfaf0bc --- /dev/null +++ b/darkice/tags/darkice-1_3/src/Makefile.am @@ -0,0 +1,113 @@ +bin_PROGRAMS = darkice + +darkice_CXXFLAGS = \ + -O2 -pedantic -Wall \ + $(DEBUG_CXXFLAGS) \ + $(PTHREAD_CFLAGS) \ + $(LAME_CFLAGS) \ + $(VORBIS_CFLAGS) \ + $(OPUS_CFLAGS) \ + $(FAAC_CFLAGS) \ + $(AACPLUS_CFLAGS) \ + $(TWOLAME_CFLAGS) \ + $(ALSA_CFLAGS) \ + $(PULSEAUDIO_CFLAGS) \ + $(JACK_CFLAGS) \ + $(SRC_CFLAGS) + +darkice_LDADD = \ + $(PTHREAD_LIBS) \ + $(LAME_LIBS) \ + $(VORBIS_LIBS) \ + $(OPUS_LIBS) \ + $(FAAC_LIBS) \ + $(AACPLUS_LIBS) \ + $(TWOLAME_LIBS) \ + $(ALSA_LIBS) \ + $(PULSEAUDIO_LIBS) \ + $(JACK_LIBS) \ + $(SRC_LIBS) + +if HAVE_SRC_LIB +AFLIB_SOURCE = +else +AFLIB_SOURCE = aflibDebug.h\ + aflibDebug.cc\ + aflibConverter.h\ + aflibConverter.cc\ + aflibConverterLargeFilter.h\ + aflibConverterSmallFilter.h +endif + +darkice_SOURCES = AudioEncoder.h\ + AudioSource.h\ + AudioSource.cpp\ + BufferedSink.cpp\ + BufferedSink.h\ + CastSink.cpp\ + CastSink.h\ + FileSink.h\ + FileSink.cpp\ + Connector.cpp\ + Connector.h\ + MultiThreadedConnector.cpp\ + MultiThreadedConnector.h\ + DarkIce.cpp\ + DarkIce.h\ + Exception.cpp\ + Exception.h\ + IceCast.cpp\ + IceCast.h\ + IceCast2.cpp\ + IceCast2.h\ + ShoutCast.cpp\ + ShoutCast.h\ + FileCast.h\ + FileCast.cpp\ + LameLibEncoder.cpp\ + LameLibEncoder.h\ + TwoLameLibEncoder.cpp\ + TwoLameLibEncoder.h\ + VorbisLibEncoder.cpp\ + VorbisLibEncoder.h\ + OpusLibEncoder.cpp\ + OpusLibEncoder.h\ + FaacEncoder.cpp\ + FaacEncoder.h\ + aacPlusEncoder.cpp\ + aacPlusEncoder.h\ + OssDspSource.cpp\ + OssDspSource.h\ + SerialUlaw.cpp\ + SerialUlaw.h\ + SolarisDspSource.cpp\ + SolarisDspSource.h\ + Ref.h\ + Referable.h\ + Sink.h\ + Source.h\ + TcpSocket.cpp\ + TcpSocket.h\ + Util.cpp\ + Util.h\ + ConfigSection.h\ + ConfigSection.cpp\ + DarkIceConfig.h\ + DarkIceConfig.cpp\ + Reporter.h\ + Reporter.cpp\ + AlsaDspSource.h\ + AlsaDspSource.cpp\ + PulseAudioDspSource.h\ + PulseAudioDspSource.cpp\ + JackDspSource.h\ + JackDspSource.cpp\ + main.cpp \ + $(AFLIB_SOURCE) + +EXTRA_darkice_SOURCES = aflibDebug.h\ + aflibDebug.cc\ + aflibConverter.h\ + aflibConverter.cc\ + aflibConverterLargeFilter.h\ + aflibConverterSmallFilter.h diff --git a/darkice/tags/darkice-1_3/src/MultiThreadedConnector.cpp b/darkice/tags/darkice-1_3/src/MultiThreadedConnector.cpp new file mode 100644 index 0000000..40c34fa --- /dev/null +++ b/darkice/tags/darkice-1_3/src/MultiThreadedConnector.cpp @@ -0,0 +1,429 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : MultiThreadedConnector.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#else +#error need sys/types.h +#endif + + +#include "Exception.h" +#include "MultiThreadedConnector.h" +#include "Util.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +MultiThreadedConnector :: init ( bool reconnect ) throw ( Exception ) +{ + this->reconnect = reconnect; + + pthread_mutex_init( &mutexProduce, 0); + pthread_cond_init( &condProduce, 0); + threads = 0; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +MultiThreadedConnector :: strip ( void ) throw ( Exception ) +{ + if ( threads ) { + delete[] threads; + threads = 0; + } + + pthread_cond_destroy( &condProduce); + pthread_mutex_destroy( &mutexProduce); +} + + +/*------------------------------------------------------------------------------ + * Constructor + *----------------------------------------------------------------------------*/ +MultiThreadedConnector :: MultiThreadedConnector ( + const MultiThreadedConnector & connector ) + throw ( Exception ) + : Connector( connector) +{ + reconnect = connector.reconnect; + mutexProduce = connector.mutexProduce; + condProduce = connector.condProduce; + + if ( threads ) { + delete[] threads; + } + threads = new ThreadData[numSinks]; + for ( unsigned int i = 0; i < numSinks; ++i ) { + threads[i] = connector.threads[i]; + } +} + + +/*------------------------------------------------------------------------------ + * Assignment operator + *----------------------------------------------------------------------------*/ +MultiThreadedConnector & +MultiThreadedConnector :: operator= ( const MultiThreadedConnector & connector ) + throw ( Exception ) +{ + if ( this != &connector ) { + Connector::operator=( connector); + + reconnect = connector.reconnect; + mutexProduce = connector.mutexProduce; + condProduce = connector.condProduce; + + if ( threads ) { + delete[] threads; + } + threads = new ThreadData[numSinks]; + for ( unsigned int i = 0; i < numSinks; ++i ) { + threads[i] = connector.threads[i]; + } + } + + return *this; +} + + +/*------------------------------------------------------------------------------ + * Open the source and all the sinks if needed + * Create the sink threads + *----------------------------------------------------------------------------*/ +bool +MultiThreadedConnector :: open ( void ) throw ( Exception ) +{ + unsigned int i; + size_t st; + + if ( !Connector::open() ) { + return false; + } + + running = true; + + pthread_attr_init( &threadAttr); + pthread_attr_getstacksize(&threadAttr, &st); + if (st < 128 * 1024) { + reportEvent( 5, "MultiThreadedConnector :: open, stack size ", + (long)st); + st = 128 * 1024; + pthread_attr_setstacksize(&threadAttr, st); + } + pthread_attr_setdetachstate( &threadAttr, PTHREAD_CREATE_JOINABLE); + + threads = new ThreadData[numSinks]; + for ( i = 0; i < numSinks; ++i ) { + ThreadData * threadData = threads + i; + + threadData->connector = this; + threadData->ixSink = i; + threadData->accepting = true; + threadData->isDone = true; + if ( pthread_create( &(threadData->thread), + &threadAttr, + ThreadData::threadFunction, + threadData ) ) { + break; + } + } + + // if could not create all, delete the ones created + if ( i < numSinks ) { + unsigned int j; + + // signal to stop for all running threads + pthread_mutex_lock( &mutexProduce); + running = false; + pthread_cond_broadcast( &condProduce); + pthread_mutex_unlock( &mutexProduce); + + for ( j = 0; j < i; ++j ) { + pthread_join( threads[j].thread, 0); + } + + delete[] threads; + threads = 0; + + return false; + } + + return true; +} + + +/*------------------------------------------------------------------------------ + * Transfer some data from the source to the sink + *----------------------------------------------------------------------------*/ +unsigned int +MultiThreadedConnector :: transfer ( unsigned long bytes, + unsigned int bufSize, + unsigned int sec, + unsigned int usec ) + throw ( Exception ) +{ + unsigned int b; + + if ( numSinks == 0 ) { + return 0; + } + + if ( bufSize == 0 ) { + return 0; + } + + dataBuffer = new unsigned char[bufSize]; + dataSize = 0; + + reportEvent( 6, "MultiThreadedConnector :: transfer, bytes", bytes); + + for ( b = 0; !bytes || b < bytes; ) { + if ( source->canRead( sec, usec) ) { + unsigned int i; + + pthread_mutex_lock( &mutexProduce); + dataSize = source->read( dataBuffer, bufSize); + b += dataSize; + + // check for EOF + if ( dataSize == 0 ) { + reportEvent( 3, "MultiThreadedConnector :: transfer, EOF"); + pthread_mutex_unlock( &mutexProduce); + break; + } + + for ( i = 0; i < numSinks; ++i ) { + threads[i].isDone = false; + } + + // tell sink threads that there is some data available + pthread_cond_broadcast( &condProduce); + + // wait for all sink threads to get done with this data + while ( true ) { + for ( i = 0; i < numSinks && threads[i].isDone; ++i ); + if ( i == numSinks ) { + break; + } + pthread_cond_wait( &condProduce, &mutexProduce); + } + pthread_mutex_unlock( &mutexProduce); + } else { + reportEvent( 3, "MultiThreadedConnector :: transfer, can't read"); + break; + } + } + + delete[] dataBuffer; + return b; +} + + +/*------------------------------------------------------------------------------ + * The function for each thread. + * Read the presented data + *----------------------------------------------------------------------------*/ +void +MultiThreadedConnector :: sinkThread( int ixSink ) +{ + ThreadData * threadData = &threads[ixSink]; + Sink * sink = sinks[ixSink].get(); + + while ( running ) { + // wait for some data to become available + pthread_mutex_lock( &mutexProduce); + while ( running && threadData->isDone ) { + pthread_cond_wait( &condProduce, &mutexProduce); + } + if ( !running ) { + pthread_mutex_unlock( &mutexProduce); + break; + } + + if ( threadData->cut) { + sink->cut(); + threadData->cut = false; + } + + if ( threadData->accepting ) { + if ( sink->canWrite( 0, 0) ) { + try { + sink->write( dataBuffer, dataSize); + } catch ( Exception & e ) { + // something wrong. don't accept more data, try to + // reopen the sink next time around + threadData->accepting = false; + } + } else { + reportEvent( 4, + "MultiThreadedConnector :: sinkThread can't write ", + ixSink); + // don't care if we can't write + } + } + threadData->isDone = true; + pthread_cond_broadcast( &condProduce); + pthread_mutex_unlock( &mutexProduce); + + if ( !threadData->accepting ) { + if ( reconnect ) { + reportEvent( 4, + "MultiThreadedConnector :: sinkThread reconnecting ", + ixSink); + // if we're not accepting, try to reopen the sink + try { + sink->close(); + Util::sleep(1L, 0L); + sink->open(); + sched_yield(); + threadData->accepting = sink->isOpen(); + } catch ( Exception & e ) { + // don't care, just try and try again + } + } else { + // if !reconnect, just stop the connector + running = false; + } + } + } +} + + +/*------------------------------------------------------------------------------ + * Signal to each sink to cut what they've done so far, and start anew. + *----------------------------------------------------------------------------*/ +void +MultiThreadedConnector :: cut ( void ) throw () +{ + for ( unsigned int i = 0; i < numSinks; ++i ) { + threads[i].cut = true; + } + + // TODO: it might be more appropriate to signal all the threads here + // but, they'll get signaled on new data anyway, and it might be + // enough for them to cut at that time +} + + +/*------------------------------------------------------------------------------ + * Stop the treads + * Close the source and all the sinks if needed + *----------------------------------------------------------------------------*/ +void +MultiThreadedConnector :: close ( void ) throw ( Exception ) +{ + unsigned int i; + + // signal to stop for all threads + pthread_mutex_lock( &mutexProduce); + running = false; + pthread_cond_broadcast( &condProduce); + pthread_mutex_unlock( &mutexProduce); + + // wait for all the threads to finish + for ( i = 0; i < numSinks; ++i ) { + pthread_join( threads[i].thread, 0); + } + pthread_attr_destroy( &threadAttr); + + Connector::close(); +} + + +/*------------------------------------------------------------------------------ + * The thread function + *----------------------------------------------------------------------------*/ +void * +MultiThreadedConnector :: ThreadData :: threadFunction( void * param ) +{ + struct sched_param sched; + int sched_type; + ThreadData * threadData = (ThreadData*) param; + + pthread_getschedparam( threadData->thread, &sched_type, &sched ); + + reportEvent( 5, + "MultiThreadedConnector :: ThreadData :: threadFunction, " + "was (thread, priority, type): ", + param, + sched.sched_priority, + sched_type == SCHED_FIFO ? "SCHED_FIFO" : + sched_type == SCHED_RR ? "SCHED_RR" : + sched_type == SCHED_OTHER ? "SCHED_OTHER" : + "INVALID" + ); + + sched.sched_priority = 1; + pthread_setschedparam( threadData->thread, SCHED_FIFO, &sched); + + pthread_getschedparam( threadData->thread, &sched_type, &sched ); + reportEvent( 5, + "MultiThreadedConnector :: ThreadData :: threadFunction, " + "now is (thread, priority, type): ", + param, + sched.sched_priority, + sched_type == SCHED_FIFO ? "SCHED_FIFO" : + sched_type == SCHED_RR ? "SCHED_RR" : + sched_type == SCHED_OTHER ? "SCHED_OTHER" : + "INVALID" + ); + + threadData->connector->sinkThread( threadData->ixSink); + + return 0; +} + diff --git a/darkice/tags/darkice-1_3/src/MultiThreadedConnector.h b/darkice/tags/darkice-1_3/src/MultiThreadedConnector.h new file mode 100644 index 0000000..eef1345 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/MultiThreadedConnector.h @@ -0,0 +1,359 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : MultiThreadedConnector.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef MULTI_THREADED_CONNECTOR_H +#define MULTI_THREADED_CONNECTOR_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// check for __NetBSD__ because it won't be found by AC_CHECK_HEADER on NetBSD +// as pthread.h is in /usr/pkg/include, not /usr/include +#if defined( HAVE_PTHREAD_H ) || defined( __NetBSD__ ) +#include +#else +#error need pthread.h +#endif + +#include "Referable.h" +#include "Ref.h" +#include "Reporter.h" +#include "Source.h" +#include "Sink.h" +#include "Connector.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * Connects a source to one or more sinks, using a multi-threaded + * producer - consumer approach. + * + * @author $Author$ + * @version $Revision$ + */ +class MultiThreadedConnector : public virtual Connector +{ + private: + + /** + * Helper class to collect information for starting threads. + */ + class ThreadData + { + public: + /** + * The connector starting the thread + */ + MultiThreadedConnector * connector; + + /** + * The index of the sink this thread writes to. + */ + unsigned int ixSink; + + /** + * The POSIX thread itself. + */ + pthread_t thread; + + /** + * Marks if the thread is accepting data. + */ + bool accepting; + + /** + * Marks if the thread has processed the last batch + * of data. + */ + bool isDone; + + /** + * A flag to show that the sink should be made to cut in the + * next iteration. + */ + bool cut; + + /** + * Default constructor. + */ + inline + ThreadData() + { + this->connector = 0; + this->ixSink = 0; + this->thread = 0; + this->accepting = false; + this->isDone = false; + this->cut = false; + } + + /** + * The thread function. + * + * @param param thread parameter, a pointer to a + * ThreadData + * @return nothing + */ + static void * + threadFunction( void * param ); + }; + + /** + * The mutex of this object. + */ + pthread_mutex_t mutexProduce; + + /** + * The conditional variable for presenting new data. + */ + pthread_cond_t condProduce; + + /** + * The thread attributes. + */ + pthread_attr_t threadAttr; + + /** + * The threads for the sinks. + */ + ThreadData * threads; + + /** + * Signal if we're running or not, so the threads no if to stop. + */ + bool running; + + /** + * Flag to show if the connector should try to reconnect if + * the connection is dropped on the other side. + */ + bool reconnect; + + /** + * The buffer of information presented to each thread. + */ + unsigned char * dataBuffer; + + /** + * The amount of information presented to each thread. + */ + unsigned int dataSize; + + /** + * Initialize the object. + * + * @param reconnect flag to indicate if the connector should + * try to reconnect if the connection was + * dropped by the other end + * @exception Exception + */ + void + init ( bool reconnect ) throw ( Exception ); + + /** + * De-initialize the object. + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + MultiThreadedConnector ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + + public: + + /** + * Constructor based on a Source. + * + * @param source the source to connect to the sinks. + * @param reconnect flag to indicate if the connector should + * try to reconnect if the connection was + * dropped by the other end + * @exception Exception + */ + inline + MultiThreadedConnector ( Source * source, + bool reconnect ) + throw ( Exception ) + : Connector( source ) + { + init(reconnect); + } + + /** + * Constructor based on a Source and a Sink. + * + * @param source the source to connect to the sinks. + * @param sink a sink to connect to the source. + * @param reconnect flag to indicate if the connector should + * try to reconnect if the connection was + * dropped by the other end + * @exception Exception + */ + inline + MultiThreadedConnector ( Source * source, + Sink * sink, + bool reconnect ) + throw ( Exception ) + : Connector( source, sink) + { + init(reconnect); + } + + /** + * Copy constructor. + * + * @param connector the object to copy. + * @exception Exception + */ + MultiThreadedConnector ( const MultiThreadedConnector & connector ) + throw ( Exception ); + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~MultiThreadedConnector( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param connector the object to assign to this one. + * @return a reference to this object. + * @exception Exception + */ + virtual MultiThreadedConnector & + operator= ( const MultiThreadedConnector & connector ) + throw ( Exception ); + + /** + * Open the connector. Opens the Source and the Sinks if necessary. + * + * @return true if opening was successful, false otherwise. + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Transfer a given amount of data from the Source to all the + * Sinks attached. + * If an attached Sink closes or encounteres an error during the + * process, it is detached and the function carries on with the + * rest of the Sinks. If no Sinks remain, or an error is encountered + * with the Source, the function returns prematurely. + * + * @param bytes the amount of data to transfer, in bytes. + * If 0, transfer forever. + * @param bufSize the size of the buffer to use for transfering. + * This amount of data is read from the Source and + * written to each Sink on each turn. + * @param sec the number of seconds to wait for the Source to have + * data available in each turn, and the number of seconds + * to wait for the Sinks to accept data. + * @param usec the number of micros seconds to wait for the Source to + * have data available in each turn, and the number of + * micro seconds to wait for the Sinks to accept data. + * @return the number of bytes read from the Source. + * @exception Exception + */ + virtual unsigned int + transfer ( unsigned long bytes, + unsigned int bufSize, + unsigned int sec, + unsigned int usec ) throw ( Exception ); + + /** + * Signal to each sink we have that they need to cut what they are + * doing, and start again. For FileSinks, this usually means to + * save the archive file recorded so far, and start a new archive + * file. + */ + virtual void + cut ( void ) throw (); + + /** + * Close the Connector. The Source and all Sinks are closed. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); + + /** + * This is the worker function for each thread. + * This function has to return fast + * + * @param ixSink the index of the sink this thread works on. + */ + void + sinkThread( int ixSink ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* MULTI_THREADED_CONNECTOR_H */ + diff --git a/darkice/tags/darkice-1_3/src/OpusLibEncoder.cpp b/darkice/tags/darkice-1_3/src/OpusLibEncoder.cpp new file mode 100644 index 0000000..4b55c4f --- /dev/null +++ b/darkice/tags/darkice-1_3/src/OpusLibEncoder.cpp @@ -0,0 +1,572 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : OpusLibEncoder.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// compile only if configured for Ogg / Opus +#ifdef HAVE_OPUS_LIB + +#include +#include +#include + +#include "Exception.h" +#include "Util.h" +#include "OpusLibEncoder.h" +#include "CastSink.h" +#include +#include + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the encoder + *----------------------------------------------------------------------------*/ +void +OpusLibEncoder :: init ( unsigned int outMaxBitrate ) + throw ( Exception ) +{ + this->outMaxBitrate = outMaxBitrate; + + if ( getInBitsPerSample() != 16 && getInBitsPerSample() != 8 ) { + throw Exception( __FILE__, __LINE__, + "specified bits per sample not supported", + getInBitsPerSample() ); + } + + if ( getInChannel() != 1 && getInChannel() != 2 ) { + throw Exception( __FILE__, __LINE__, + "unsupported number of channels for the encoder", + getInChannel() ); + } + + if ( getOutSampleRate() != 48000 ) { + throw Exception( __FILE__, __LINE__, + "unsupported sample rate for this encoder, you should resample your input to 48000Hz", + getOutSampleRate() ); + } + + if ( getOutSampleRate() == getInSampleRate() ) { + resampleRatio = 1; + converter = 0; + } else { + resampleRatio = ( (double) getOutSampleRate() / + (double) getInSampleRate() ); + + // Determine if we can use linear interpolation. + // The inverse of the ratio must be a power of two for linear mode to + // be of sufficient quality. + + bool useLinear = true; + double inverse = 1 / resampleRatio; + int integer = (int) inverse; + + // Check that the inverse of the ratio is an integer + if( integer == inverse ) { + while( useLinear && integer ) { // Loop through the bits + // If the lowest order bit is not the only one set + if( integer & 1 && integer != 1 ) { + // Not a power of two; cannot use linear + useLinear = false; + } else { + // Shift all the bits over and try again + integer >>= 1; + } + } + } else { + useLinear = false; + } + + // If we get here and useLinear is still true, then we have + // a power of two. + + // open the aflibConverter in + // - high quality + // - linear or quadratic (non-linear) based on algorithm + // - not filter interpolation +#ifdef HAVE_SRC_LIB + int srcError = 0; + converter = src_new(useLinear == true ? SRC_LINEAR : SRC_SINC_FASTEST, + getInChannel(), &srcError); + if(srcError) + throw Exception (__FILE__, __LINE__, "libsamplerate error: ", src_strerror (srcError)); +#else + converter = new aflibConverter( true, useLinear, false); +#endif + } + + encoderOpen = false; +} + + +/*------------------------------------------------------------------------------ + * Open an encoding session + *----------------------------------------------------------------------------*/ +bool +OpusLibEncoder :: open ( void ) + throw ( Exception ) +{ + int ret; + + if ( isOpen() ) { + close(); + } + + // open the underlying sink + if ( !getSink()->open() ) { + throw Exception( __FILE__, __LINE__, + "opus lib opening underlying sink error"); + } + + int bufferSize = (getInBitsPerSample()/8) * getInChannel() * 480; + internalBuffer = new unsigned char[bufferSize]; + internalBufferLength = 0; + memset( internalBuffer, 0, bufferSize); + + int err; + opusEncoder = opus_encoder_create( getOutSampleRate(), + getInChannel(), + OPUS_APPLICATION_AUDIO, + &err); + if( err != OPUS_OK ) { + throw Exception( __FILE__, __LINE__, + "opus encoder creation error", + err); + } + + opus_encoder_ctl(opusEncoder, OPUS_SET_COMPLEXITY(10)); + opus_encoder_ctl(opusEncoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC)); + + switch ( getOutBitrateMode() ) { + + case cbr: { + int maxBitrate = getOutBitrate() * 1000; + if ( !maxBitrate ) { + maxBitrate = 96000; + } + opus_encoder_ctl(opusEncoder, OPUS_SET_BITRATE(maxBitrate)); + opus_encoder_ctl(opusEncoder, OPUS_SET_VBR(0)); + } break; + + case abr: { + int maxBitrate = getOutBitrate() * 1000; + if ( !maxBitrate ) { + maxBitrate = 96000; + } + /* set non-managed VBR around the average bitrate */ + opus_encoder_ctl(opusEncoder, OPUS_SET_BITRATE(maxBitrate)); + opus_encoder_ctl(opusEncoder, OPUS_SET_VBR(1)); + opus_encoder_ctl(opusEncoder, OPUS_SET_VBR_CONSTRAINT(1)); + } break; + case vbr: + int maxBitrate = getOutBitrate() * 1000; + if ( !maxBitrate ) { + maxBitrate = 96000; + } + /* set non-managed VBR around the average bitrate */ + opus_encoder_ctl(opusEncoder, OPUS_SET_BITRATE(maxBitrate)); + opus_encoder_ctl(opusEncoder, OPUS_SET_VBR(1)); + opus_encoder_ctl(opusEncoder, OPUS_SET_VBR_CONSTRAINT(0)); + break; + } + + if ( (ret = ogg_stream_init( &oggStreamState, 0)) ) { + throw Exception( __FILE__, __LINE__, "ogg stream init error", ret); + } + + // First, we need to assemble and send a OggOpus header. + OpusIdHeader header; + strncpy(header.magic, "OpusHead", 8); + header.version = 1; + header.channels = getOutChannel(); + header.preskip = 0; + header.samplerate = getInSampleRate(); + header.gain = 0; // technically a fixed-point decimal. + header.chanmap = 0; + + // And, now we need to send a Opus comment header. + // Anything after this can be audio. + + char vendor[8] = "darkice"; + char titlestr[7] = "TITLE="; + OpusCommentHeader::Tags tags[1]; + char name[40]; + CastSink* sink = dynamic_cast(getSink().get()); + if( sink && sink->getName() ) { + strncpy(name, (char*)sink->getName(), 39); + name[39] = 0; + } + else { + strncpy(name, "Darkice Stream", 39); + } + tags[0].tag_len = strlen(titlestr) + strlen(name); + tags[0].tag_str = (char*) malloc( tags[0].tag_len + 1 ); + if( tags[0].tag_str == NULL ) { + throw Exception( __FILE__, __LINE__, "malloc failed"); + } + strncpy( tags[0].tag_str, titlestr, tags[0].tag_len); + strncat( tags[0].tag_str, name, tags[0].tag_len); + + OpusCommentHeader commentHeader; + strncpy(commentHeader.magic, "OpusTags", 8); + commentHeader.vendor_length = strlen(vendor); + commentHeader.vendor_string = vendor; + commentHeader.num_tags = 1; + commentHeader.tags = tags; + + ogg_packet oggHeader; + ogg_packet oggCommentHeader; + memset(&oggHeader, 0, sizeof(oggHeader)); + memset(&oggCommentHeader, 0, sizeof(oggCommentHeader)); + unsigned char* headerData = NULL; + unsigned char* commentData = NULL; + int headerLen = 0; + int commentLen = 0; + + headerLen = header.buildPacket( &headerData); + commentLen = commentHeader.buildPacket( &commentData); + + oggHeader.packet = headerData; + oggHeader.bytes = headerLen; + oggHeader.b_o_s = 1; + oggHeader.e_o_s = 0; + oggHeader.granulepos = 0; + oggHeader.packetno = 0; + + oggCommentHeader.packet = commentData; + oggCommentHeader.bytes = commentLen; + oggCommentHeader.b_o_s = 0; + oggCommentHeader.e_o_s = 0; + oggCommentHeader.granulepos = 0; + oggCommentHeader.packetno = 1; + + oggPacketNumber = 2; + oggGranulePosition = 0; + + ogg_stream_packetin( &oggStreamState, &oggHeader); + ogg_stream_packetin( &oggStreamState, &oggCommentHeader); + + ogg_page oggPage; + while ( ogg_stream_flush( &oggStreamState, &oggPage) ) { + getSink()->write( oggPage.header, oggPage.header_len); + getSink()->write( oggPage.body, oggPage.body_len); + } + + free(tags[0].tag_str); + free(headerData); + free(commentData); + + // initialize the resampling coverter if needed + if ( converter ) { +#ifdef HAVE_SRC_LIB + converterData.input_frames = 4096/((getInBitsPerSample() / 8) * getInChannel()); + converterData.data_in = new float[converterData.input_frames*getInChannel()]; + converterData.output_frames = (int) (converterData.input_frames * resampleRatio + 1); + converterData.data_out = new float[getInChannel() * converterData.output_frames]; + converterData.src_ratio = resampleRatio; + converterData.end_of_input = 0; +#else + converter->initialize( resampleRatio, getInChannel()); +#endif + } + + encoderOpen = true; + reconnectError = false; + + return true; +} + + +/*------------------------------------------------------------------------------ + * Write data to the encoder + *----------------------------------------------------------------------------*/ +unsigned int +OpusLibEncoder :: write ( const void * buf, + unsigned int len ) throw ( Exception ) +{ + if ( !isOpen() || len == 0 ) { + return 0; + } + + unsigned int channels = getInChannel(); + unsigned int bitsPerSample = getInBitsPerSample(); + unsigned int sampleSize = (bitsPerSample / 8) * channels; + + unsigned int i; + + if ( getInChannel() == 2 && getOutChannel() == 1 ) { + for ( i = 0; i < len/sampleSize; i++) { + if ( bitsPerSample == 8 ) { + char * buf8 = (char *) buf; + unsigned int ix = sampleSize * i; + unsigned int iix = ix; + buf8[i] = (buf8[ix] + buf8[++iix]) / 2; + } + if ( bitsPerSample == 16 ) { + short * buf16 = (short *) buf; + unsigned int ix = (bitsPerSample >> 3) * i; + unsigned int iix = ix; + buf16[i] = (buf16[ix] + buf16[++iix]) / 2; + } + } + len >>= 1; + channels = 1; + } + + sampleSize = (bitsPerSample / 8) * channels; + unsigned int processed = 0; + unsigned int bytesToProcess = len - (len % sampleSize); + unsigned int totalProcessed = 0; + unsigned char * b = (unsigned char*) buf; + unsigned char * tempBuffer = NULL; + + if( internalBufferLength > 0 ) { + tempBuffer = new unsigned char[len + internalBufferLength]; + memset( tempBuffer, 0, len + internalBufferLength); + if( !tempBuffer ) { + throw Exception( __FILE__, __LINE__, "could not allocate temp buffer"); + } + memcpy( tempBuffer, internalBuffer, internalBufferLength); + memcpy( tempBuffer+internalBufferLength, buf, len); + b = tempBuffer; + bytesToProcess += internalBufferLength; + } + + + while ( bytesToProcess / resampleRatio >= 480 * sampleSize ) { + unsigned int toProcess = bytesToProcess / (resampleRatio * sampleSize); + if( toProcess >= 480 / resampleRatio) { + processed = 480 / resampleRatio; + } + + int opusBufferSize = (1275*3+7)*channels; + unsigned char* opusBuffer = new unsigned char[opusBufferSize]; + + // convert the byte-based raw input into a short buffer + // with channels still interleaved + unsigned int totalSamples = processed * channels; + short int * shortBuffer = new short int[totalSamples]; + + Util::conv( bitsPerSample, b, processed*sampleSize, shortBuffer, isInBigEndian()); + + if ( converter && processed > 0 ) { + // resample if needed + int inCount = processed; + int outCount = 480; //(int) (inCount * resampleRatio); + short int * resampledBuffer = new short int[(outCount+1)* channels]; + int converted; +#ifdef HAVE_SRC_LIB + (void)inCount; + converterData.input_frames = processed; + src_short_to_float_array (shortBuffer, converterData.data_in, totalSamples); + int srcError = src_process (converter, &converterData); + if (srcError) + throw Exception (__FILE__, __LINE__, "libsamplerate error: ", src_strerror (srcError)); + converted = converterData.output_frames_gen; + + src_float_to_short_array(converterData.data_out, resampledBuffer, converted*channels); + +#else + converted = converter->resample( inCount, + outCount, + shortBuffer, + resampledBuffer ); +#endif + if( converted != 480) { + throw Exception( __FILE__, __LINE__, "resampler error: expected 480 samples", converted); + } + int encBytes = opus_encode( opusEncoder, resampledBuffer, 480, opusBuffer, opusBufferSize); + if( encBytes == -1 ) { + throw Exception( __FILE__, __LINE__, "opus encoder error"); + } + oggGranulePosition += converted; + opusBlocksOut( encBytes, opusBuffer); + + delete[] resampledBuffer; + + } else if( processed > 0) { + memset( opusBuffer, 0, opusBufferSize); + int encBytes = opus_encode( opusEncoder, shortBuffer, processed, opusBuffer, opusBufferSize); + if( encBytes == -1 ) { + throw Exception( __FILE__, __LINE__, "opus encoder error"); + } + oggGranulePosition += processed; + opusBlocksOut( encBytes, opusBuffer); + + } + delete[] shortBuffer; + delete[] opusBuffer; + bytesToProcess -= processed * sampleSize; + totalProcessed += processed * sampleSize; + b = ((unsigned char*)b) + (processed * sampleSize); + } + + int newLen = len - (len % sampleSize) + internalBufferLength - totalProcessed; + newLen -= newLen % sampleSize; + + if( newLen > 0 ) { + memcpy( internalBuffer, b, newLen); + totalProcessed += newLen; + internalBufferLength = newLen; + } else { + internalBufferLength = 0; + } + + if( tempBuffer ) { + delete[] tempBuffer; + tempBuffer = NULL; + } + + return totalProcessed; +} + + +/*------------------------------------------------------------------------------ + * Flush the data from the encoder + *----------------------------------------------------------------------------*/ +void +OpusLibEncoder :: flush ( void ) + throw ( Exception ) +{ + if ( !isOpen() || reconnectError == true ) { + return; + } + + int opusBufferSize = (1275*3+7)*getOutChannel(); + unsigned char * opusBuffer = new unsigned char[opusBufferSize]; + short int * shortBuffer = new short int[480*getInChannel()]; + + // Send an empty audio packet along to flush out the stream. + memset( shortBuffer, 0, 480*getInChannel()*sizeof(*shortBuffer)); + memset( opusBuffer, 0, opusBufferSize); + int encBytes = opus_encode( opusEncoder, shortBuffer, 480, opusBuffer, opusBufferSize); + if( encBytes == -1 ) { + throw Exception( __FILE__, __LINE__, "opus encoder error"); + } + oggGranulePosition += 480; + + // Send the empty block to the Ogg layer, and mark the + // EOS flag. This will trigger any remaining packets to be + // sent. + opusBlocksOut( encBytes, opusBuffer, true); + delete[] opusBuffer; + delete[] shortBuffer; + getSink()->flush(); +} + + +/*------------------------------------------------------------------------------ + * Send pending Opus blocks to the underlying stream + *----------------------------------------------------------------------------*/ +void +OpusLibEncoder :: opusBlocksOut ( int bytes, + unsigned char* data, + bool eos ) throw ( Exception ) +{ + ogg_packet oggPacket; + ogg_page oggPage; + + oggPacket.packet = data; + oggPacket.bytes = bytes; + oggPacket.b_o_s = 0; + oggPacket.e_o_s = ( eos ) ? 1 : 0; + oggPacket.granulepos = oggGranulePosition; + oggPacket.packetno = oggPacketNumber; + oggPacketNumber++; + + if( ogg_stream_packetin( &oggStreamState, &oggPacket) == 0) { + while( ogg_stream_pageout( &oggStreamState, &oggPage) || + ( eos && ogg_stream_flush( &oggStreamState, &oggPage) ) ) { + int written; + + written = getSink()->write(oggPage.header, oggPage.header_len); + written += getSink()->write( oggPage.body, oggPage.body_len); + + if ( written < oggPage.header_len + oggPage.body_len ) { + reconnectError = true; + // just let go data that could not be written + reportEvent( 2, + "couldn't write full opus data to underlying sink", + oggPage.header_len + oggPage.body_len - written); + } + } + } else { + throw Exception( __FILE__, __LINE__, "internal ogg error"); + } +} + + +/*------------------------------------------------------------------------------ + * Close the encoding session + *----------------------------------------------------------------------------*/ +void +OpusLibEncoder :: close ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + flush(); + + ogg_stream_clear( &oggStreamState); + opus_encoder_destroy( opusEncoder); + opusEncoder = NULL; + + encoderOpen = false; + if (internalBuffer) { + delete[] internalBuffer; + internalBuffer = NULL; + } + else { + fprintf(stderr, "Opus internalBuffer is NULL!\n"); + } + + getSink()->close(); + } +} + + +#endif // HAVE_OPUS_LIB + diff --git a/darkice/tags/darkice-1_3/src/OpusLibEncoder.h b/darkice/tags/darkice-1_3/src/OpusLibEncoder.h new file mode 100644 index 0000000..86b60cd --- /dev/null +++ b/darkice/tags/darkice-1_3/src/OpusLibEncoder.h @@ -0,0 +1,566 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : OpusLibEncoder.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef OPUS_LIB_ENCODER_H +#define OPUS_LIB_ENCODER_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#ifdef HAVE_OPUS_LIB +#include +#include +#else +#error configure for Ogg Opus +#endif + + +#include "Ref.h" +#include "Exception.h" +#include "Reporter.h" +#include "AudioEncoder.h" +#include "Sink.h" +#ifdef HAVE_SRC_LIB +#include +#else +#include "aflibConverter.h" +#endif + +#include +#include + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A struct for containing the ogg opus header format, sent at the stream + * beginning. + * + * @author $Author$ + * @version $Revision$ + */ +struct OpusIdHeader { + char magic[8]; /* "OpusHead" */ + unsigned char version; /* Version (currently 1) */ + unsigned char channels; /* Number of channels */ + unsigned short preskip; /* Pre-skip */ + unsigned int samplerate; /* Original samplerate; informational only */ + unsigned short gain; /* Output gain, stored in Q7.8 in dB */ + unsigned char chanmap; /* 0 = mono or stereo L/R, 1=vorbis spec order, 2..254=reserved, 255=undef */ + + /** + * Build an Ogg packet from the header. + * @param packet output pointer, must be freed by caller + * + * @return number of bytes in packet. + */ + inline int buildPacket( unsigned char** packet) throw ( Exception ) { + int i = 0; + // FIXME - doesn't support multistream + unsigned char* out = (unsigned char*)malloc(19); + if( out == NULL ) { + throw Exception( __FILE__, __LINE__, "cannot alloc buffer"); + } + for( ; i < 8; i++) { + out[i] = magic[i]; + } + out[i++] = version; + out[i++] = channels; + out[i++] = preskip & 0xff; + out[i++] = (preskip >> 8) & 0xff; + out[i++] = samplerate & 0xff; + out[i++] = (samplerate >> 8) & 0xff; + out[i++] = (samplerate >> 16) & 0xff; + out[i++] = (samplerate >> 24) & 0xff; + out[i++] = gain & 0xff; + out[i++] = (gain >> 8) & 0xff; + out[i++] = chanmap; + *packet = out; + return i; + } +}; + +/** + * A struct for containing the ogg opus comment header format + * + * @author $Author$ + * @version $Revision$ + */ +struct OpusCommentHeader { + /** + * Struct for each tag pair, in the form of a UTF-8 + * string, "TAG=value" + * + * @author $Author$ + * @version $Revision$ + */ + struct Tags { + unsigned int tag_len; /* For each tag, how long the following tag is */ + char* tag_str; /* For each tag, UTF-8 encoded string, in tag=value */ + }; + char magic[8]; /* "OpusTags" */ + unsigned int vendor_length; /* Length of the vendor string */ + char* vendor_string; /* Vendor string -- parsed as utf-8 */ + unsigned int num_tags; /* Number of tags following */ + Tags* tags; /* Pointer to allocated tag array */ + + /** + * Build an Ogg packet from the header. + * @param packet output pointer, must be freed by caller + * + * @return number of bytes in packet. + */ + inline int buildPacket( unsigned char** packet) throw ( Exception ) { + int len = 8 + sizeof(unsigned int) * 2 + vendor_length; + int pos = 0; + for( unsigned int i = 0; i < num_tags; i++ ) + { + len += sizeof(unsigned int) + tags[i].tag_len; + } + unsigned char* out = (unsigned char*)malloc(len); + if( out == NULL ) { + throw Exception( __FILE__, __LINE__, "cannot alloc buffer"); + } + for( ; pos < 8; pos++) { + out[pos] = magic[pos]; + } + out[pos++] = vendor_length & 0xff; + out[pos++] = (vendor_length >> 8) & 0xff; + out[pos++] = (vendor_length >> 16) & 0xff; + out[pos++] = (vendor_length >> 24) & 0xff; + for( unsigned int i = 0; i < vendor_length; i++ ) { + out[pos++] = vendor_string[i]; + } + out[pos++] = num_tags & 0xff; + out[pos++] = (num_tags >> 8) & 0xff; + out[pos++] = (num_tags >> 16) & 0xff; + out[pos++] = (num_tags >> 24) & 0xff; + for( unsigned int i = 0; i < num_tags; i++ ) { + out[pos++] = tags[i].tag_len & 0xff; + out[pos++] = (tags[i].tag_len >> 8) & 0xff; + out[pos++] = (tags[i].tag_len >> 16) & 0xff; + out[pos++] = (tags[i].tag_len >> 24) & 0xff; + for( unsigned int j = 0; j < tags[i].tag_len; j++ ) { + out[pos++] = tags[i].tag_str[j]; + } + } + *packet = out; + return len; + } +}; + +/** + * A class representing the ogg opus encoder linked as a shared object or + * as a static library. + * + * @author $Author$ + * @version $Revision$ + */ +class OpusLibEncoder : public AudioEncoder, public virtual Reporter +{ + private: + + /** + * Value indicating if the encoding process is going on + */ + bool encoderOpen; + + /** + * Ogg Opus library global info + */ + OpusEncoder* opusEncoder; + + /** + * Ogg library global stream state + */ + ogg_stream_state oggStreamState; + + ogg_int64_t oggGranulePosition; + ogg_int64_t oggPacketNumber; + + unsigned char* internalBuffer; + int internalBufferLength; + bool reconnectError; + + /** + * Maximum bitrate of the output in kbits/sec. If 0, don't care. + */ + unsigned int outMaxBitrate; + + /** + * Resample ratio + */ + double resampleRatio; + + /** + * sample rate converter object for possible resampling + */ +#ifdef HAVE_SRC_LIB + SRC_STATE * converter; + SRC_DATA converterData; +#else + aflibConverter * converter; +#endif + + /** + * Initialize the object. + * + * @param the maximum bit rate + * @exception Exception + */ + void + init ( unsigned int outMaxBitrate ) throw ( Exception ); + + /** + * De-initialize the object. + * + * @exception Exception + */ + inline void + strip ( void ) throw ( Exception ) + { + if ( converter ) { +#ifdef HAVE_SRC_LIB + delete [] converterData.data_in; + delete [] converterData.data_out; + src_delete (converter); +#else + delete converter; +#endif + } + } + + /** + * Send pending Opus blocks to the underlying stream + */ + void + opusBlocksOut( int bytes, + unsigned char* data, + bool eos = false ) throw ( Exception ); + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + OpusLibEncoder ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + + public: + + /** + * Constructor. + * + * @param sink the sink to send encoded output to + * @param inSampleRate sample rate of the input. + * @param inBitsPerSample number of bits per sample of the input. + * @param inChannel number of channels of the input. + * @param inBigEndian shows if the input is big or little endian + * @param outBitrateMode the bit rate mode of the output. + * @param outBitrate bit rate of the output (kbits/sec). + * @param outQuality the quality of the stream. + * @param outSampleRate sample rate of the output. + * If 0, inSampleRate is used. + * @param outMaxBitrate maximum output bitrate. + * 0 if not used. + * @param outChannel number of channels of the output. + * If 0, inChannel is used. + * @exception Exception + */ + inline + OpusLibEncoder ( Sink * sink, + unsigned int inSampleRate, + unsigned int inBitsPerSample, + unsigned int inChannel, + bool inBigEndian, + BitrateMode outBitrateMode, + unsigned int outBitrate, + double outQuality, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0, + unsigned int outMaxBitrate = 0 ) + throw ( Exception ) + + : AudioEncoder ( sink, + inSampleRate, + inBitsPerSample, + inChannel, + inBigEndian, + outBitrateMode, + outBitrate, + outQuality, + outSampleRate, + outChannel ) + { + init( outMaxBitrate); + } + + /** + * Constructor. + * + * @param sink the sink to send encoded output to + * @param as get input sample rate, bits per sample and channels + * from this AudioSource. + * @param outBitrateMode the bit rate mode of the output. + * @param outBitrate bit rate of the output (kbits/sec). + * @param outQuality the quality of the stream. + * @param outSampleRate sample rate of the output. + * If 0, input sample rate is used. + * @param outMaxBitrate maximum output bitrate. + * 0 if not used. + * @param outChannel number of channels of the output. + * If 0, input channel is used. + * @exception Exception + */ + inline + OpusLibEncoder ( Sink * sink, + const AudioSource * as, + BitrateMode outBitrateMode, + unsigned int outBitrate, + double outQuality, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0, + unsigned int outMaxBitrate = 0 ) + throw ( Exception ) + + : AudioEncoder ( sink, + as, + outBitrateMode, + outBitrate, + outQuality, + outSampleRate, + outChannel ) + { + init( outMaxBitrate); + } + + /** + * Copy constructor. + * + * @param encoder the OpusLibEncoder to copy. + */ + inline + OpusLibEncoder ( const OpusLibEncoder & encoder ) + throw ( Exception ) + : AudioEncoder( encoder ) + { + if( encoder.isOpen() ) { + throw Exception(__FILE__, __LINE__, "don't copy open encoders"); + } + init( encoder.getOutMaxBitrate() ); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~OpusLibEncoder ( void ) throw ( Exception ) + { + if ( isOpen() ) { + close(); + } + strip(); + } + + /** + * Assignment operator. + * + * @param encoder the OpusLibEncoder to assign this to. + * @return a reference to this OpusLibEncoder. + * @exception Exception + */ + inline virtual OpusLibEncoder & + operator= ( const OpusLibEncoder & encoder ) throw ( Exception ) + { + if( encoder.isOpen() ) { + throw Exception(__FILE__, __LINE__, "don't copy open encoders"); + } + + if ( this != &encoder ) { + strip(); + AudioEncoder::operator=( encoder); + init( encoder.getOutMaxBitrate() ); + } + + return *this; + } + + /** + * Get the maximum bit rate of the output in kbits/sec, + * for fixed / average bitrate encodings. + * + * @return the maximum bit rate of the output, or 0 if not set. + */ + inline unsigned int + getOutMaxBitrate ( void ) const throw () + { + return outMaxBitrate; + } + + /** + * Check whether encoding is in progress. + * + * @return true if encoding is in progress, false otherwise. + */ + inline virtual bool + isRunning ( void ) const throw () + { + return isOpen(); + } + + /** + * Start encoding. This function returns as soon as possible, + * with encoding started in the background. + * + * @return true if encoding has started, false otherwise. + * @exception Exception + */ + inline virtual bool + start ( void ) throw ( Exception ) + { + return open(); + } + + /** + * Stop encoding. Stops the encoding running in the background. + * + * @exception Exception + */ + inline virtual void + stop ( void ) throw ( Exception ) + { + return close(); + } + + /** + * Open an encoding session. + * + * @return true if opening was successfull, false otherwise. + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the encoding session is open. + * + * @return true if the encoding session is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return encoderOpen; + } + + /** + * Check if the encoder is ready to accept data. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the encoder is ready to accept data, + * false otherwise. + * @exception Exception + */ + inline virtual bool + canWrite ( unsigned int sec, + unsigned int usec ) throw ( Exception ) + { + if ( !isOpen() ) { + return false; + } + + return getSink()->canWrite(sec, usec); + } + + /** + * Write data to the encoder. + * Buf is expected to be a sequence of big-endian 16 bit values, + * with left and right channels interleaved. Len is the number of + * bytes, must be a multiple of 4. + * + * @param buf the data to write. + * @param len number of bytes to write from buf. + * @return the number of bytes written (may be less than len). + * @exception Exception + */ + virtual unsigned int + write ( const void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Flush all data that was written to the encoder to the underlying + * connection. + * + * @exception Exception + */ + virtual void + flush ( void ) throw ( Exception ); + + /** + * Close the encoding session. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* OPUS_LIB_ENCODER_H */ + diff --git a/darkice/tags/darkice-1_3/src/OssDspSource.cpp b/darkice/tags/darkice-1_3/src/OssDspSource.cpp new file mode 100644 index 0000000..23493a8 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/OssDspSource.cpp @@ -0,0 +1,315 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : OssDspSource.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#include "OssDspSource.h" + +#ifdef SUPPORT_OSS_DSP +// only compile this code if there is support for it + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_UNISTD_H +#include +#else +#error need unistd.h +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#else +#error need sys/types.h +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#else +#error need sys/stat.h +#endif + +#ifdef HAVE_FCNTL_H +#include +#else +#error need fcntl.h +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#else +#error need sys/time.h +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include +#else +#error need sys/ioctl.h +#endif + +#ifdef HAVE_SIGNAL_H +#include +#else +#error need signal.h +#endif + +#ifdef HAVE_SYS_SOUNDCARD_H +#include +#else +#error need sys/soundcard.h +#endif + + +#include "Util.h" +#include "Exception.h" +#include "OssDspSource.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + +/*------------------------------------------------------------------------------ + * Define the natural endiannes of 16 bit recording if not defined, + * based on the endiannes of the system + *----------------------------------------------------------------------------*/ +#ifndef AFMT_S16_NE +# ifdef WORDS_BIGENDIAN +# define AFMT_S16_NE AFMT_S16_BE +# else +# define AFMT_S16_NE AFMT_S16_LE +# endif +#endif + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Tell if source id big endian + *----------------------------------------------------------------------------*/ +bool +OssDspSource :: isBigEndian ( void ) const throw () +{ + return AFMT_S16_NE == AFMT_S16_BE; +} + + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +OssDspSource :: init ( const char * name ) throw ( Exception ) +{ + fileName = Util::strDup( name); + fileDescriptor = 0; + running = false; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +OssDspSource :: strip ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + delete[] fileName; +} + + +/*------------------------------------------------------------------------------ + * Open the audio source + *----------------------------------------------------------------------------*/ +bool +OssDspSource :: open ( void ) throw ( Exception ) +{ + int format; + int i; + unsigned int u; + + if ( isOpen() ) { + return false; + } + + switch ( getBitsPerSample() ) { + case 8: + format = AFMT_U8; + break; + + case 16: + format = AFMT_S16_NE; + break; + + default: + return false; + } + + if ( (fileDescriptor = ::open( fileName, O_RDONLY)) == -1 ) { + fileDescriptor = 0; + return false; + } + + i = format; + if ( ioctl( fileDescriptor, SNDCTL_DSP_SETFMT, &i) == -1 || + i != format ) { + + close(); + throw Exception( __FILE__, __LINE__, "can't set format", i); + } + + u = getChannel(); + if ( ioctl( fileDescriptor, SNDCTL_DSP_CHANNELS, &u) == -1 || + u != getChannel() ) { + + close(); + throw Exception( __FILE__, __LINE__, "can't set channels", u); + } + + u = getSampleRate(); + if ( ioctl( fileDescriptor, SNDCTL_DSP_SPEED, &u) == -1 ) { + + close(); + throw Exception( __FILE__, __LINE__, + "can't set soundcard recording sample rate", u); + } + if ( u != getSampleRate() ) { + reportEvent( 2, "sound card recording sample rate set to ", u, + " while trying to set it to ", getSampleRate()); + reportEvent( 2, "this is probably not a problem, but a slight " + "drift in the sound card driver"); + } + + return true; +} + + +/*------------------------------------------------------------------------------ + * Check whether read() would return anything + *----------------------------------------------------------------------------*/ +bool +OssDspSource :: canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ) +{ + fd_set fdset; + struct timespec timespec; + sigset_t sigset; + int ret; + + if ( !isOpen() ) { + return false; + } + + if ( !running ) { + /* ugly workaround to get the dsp into recording state */ + unsigned char * b = + new unsigned char[getChannel()*getBitsPerSample()/8]; + read( b, getChannel()*getBitsPerSample()/8); + delete[] b; + } + + FD_ZERO( &fdset); + FD_SET( fileDescriptor, &fdset); + + timespec.tv_sec = sec; + timespec.tv_nsec = usec * 1000L; + + // mask out SIGUSR1, as we're expecting that signal for other reasons + sigemptyset(&sigset); + sigaddset(&sigset, SIGUSR1); + + ret = pselect( fileDescriptor + 1, &fdset, NULL, NULL, ×pec, &sigset); + + if ( ret == -1 ) { + throw Exception( __FILE__, __LINE__, "select error"); + } + + return ret > 0; +} + + +/*------------------------------------------------------------------------------ + * Read from the audio source + *----------------------------------------------------------------------------*/ +unsigned int +OssDspSource :: read ( void * buf, + unsigned int len ) throw ( Exception ) +{ + ssize_t ret; + + if ( !isOpen() ) { + return 0; + } + + ret = ::read( fileDescriptor, buf, len); + + if ( ret == -1 ) { + throw Exception( __FILE__, __LINE__, "read error"); + } + + running = true; + return ret; +} + + +/*------------------------------------------------------------------------------ + * Close the audio source + *----------------------------------------------------------------------------*/ +void +OssDspSource :: close ( void ) throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + ::close( fileDescriptor); + fileDescriptor = 0; + running = false; +} + +#endif // SUPPORT_OSS_DSP + diff --git a/darkice/tags/darkice-1_3/src/OssDspSource.h b/darkice/tags/darkice-1_3/src/OssDspSource.h new file mode 100644 index 0000000..6734bd7 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/OssDspSource.h @@ -0,0 +1,255 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : OssDspSource.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef OSS_DSP_SOURCE_H +#define OSS_DSP_SOURCE_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Reporter.h" +#include "AudioSource.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * An audio input based on /dev/dsp-like raw devices + * + * @author $Author$ + * @version $Revision$ + */ +class OssDspSource : public AudioSource, public virtual Reporter +{ + private: + + /** + * The file name of the OSS DSP device (e.g. /dev/dsp or /dev/dsp0). + */ + char * fileName; + + /** + * The low-level file descriptor of the OSS DSP device. + */ + int fileDescriptor; + + /** + * Indicates whether the low-level OSS DSP device is in a recording + * state. + */ + bool running; + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + OssDspSource ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Initialize the object + * + * @param name the file name of the OSS DSP device. + * @exception Exception + */ + void + init ( const char * name ) throw ( Exception ); + + /** + * De-iitialize the object + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + public: + + /** + * Constructor. + * + * @param name the file name of the OSS DSP device + * (e.g. /dev/dsp or /dev/dsp0). + * @param sampleRate samples per second (e.g. 44100 for 44.1kHz). + * @param bitsPerSample bits per sample (e.g. 16 bits). + * @param channel number of channels of the audio source + * (e.g. 1 for mono, 2 for stereo, etc.). + * @exception Exception + */ + inline + OssDspSource ( const char * name, + int sampleRate = 44100, + int bitsPerSample = 16, + int channel = 2 ) + throw ( Exception ) + + : AudioSource( sampleRate, bitsPerSample, channel) + { + init( name); + } + + /** + * Copy Constructor. + * + * @param ods the object to copy. + * @exception Exception + */ + inline + OssDspSource ( const OssDspSource & ods ) throw ( Exception ) + : AudioSource( ods ) + { + init( ods.fileName); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~OssDspSource ( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param ds the object to assign to this one. + * @return a reference to this object. + * @exception Exception + */ + inline virtual OssDspSource & + operator= ( const OssDspSource & ds ) throw ( Exception ) + { + if ( this != &ds ) { + strip(); + AudioSource::operator=( ds); + init( ds.fileName); + } + return *this; + } + + /** + * Tell if the data from this source comes in big or little endian. + * + * @return true if the source is big endian, false otherwise + */ + virtual bool + isBigEndian ( void ) const throw (); + + /** + * Open the OssDspSource. + * This does not put the OSS DSP device into recording mode. + * To start getting samples, call either canRead() or read(). + * + * @return true if opening was successful, false otherwise + * @exception Exception + * + * @see #canRead + * @see #read + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the OssDspSource is open. + * + * @return true if the OssDspSource is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return fileDescriptor != 0; + } + + /** + * Check if the OssDspSource can be read from. + * Blocks until the specified time for data to be available. + * Puts the OSS DSP device into recording mode. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the OssDspSource is ready to be read from, + * false otherwise. + * @exception Exception + */ + virtual bool + canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ); + + /** + * Read from the OssDspSource. + * Puts the OSS DSP device into recording mode. + * + * @param buf the buffer to read into. + * @param len the number of bytes to read into buf + * @return the number of bytes read (may be less than len). + * @exception Exception + */ + virtual unsigned int + read ( void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Close the OssDspSource. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* OSS_DSP_SOURCE_H */ + diff --git a/darkice/tags/darkice-1_3/src/PulseAudioDspSource.cpp b/darkice/tags/darkice-1_3/src/PulseAudioDspSource.cpp new file mode 100644 index 0000000..29cd580 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/PulseAudioDspSource.cpp @@ -0,0 +1,237 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Copyright (c) 2004 + LS Informationstechnik (LIKE) + University of Erlangen Nuremberg + All rights reserved. + + Tyrell DarkIce + + File : PulseAudioDspSource.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#include "AudioSource.h" +#include + +// compile only if configured for PULSEAUDIO +#ifdef SUPPORT_PULSEAUDIO_DSP + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "Util.h" +#include "Exception.h" +#include "PulseAudioDspSource.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +PulseAudioDspSource :: init ( const char * paSourceName ) throw ( Exception ) +{ + + if (paSourceName == NULL) + { + throw Exception( __FILE__, __LINE__, "no paSourceName specified"); + } + Reporter::reportEvent( 1, "Using PulseAudio source: ", paSourceName); + Util::strEq( paSourceName , "default" ); + if (Util::strEq( paSourceName , "default" )) + { + sourceName = NULL; + } + else + { + sourceName = Util::strDup( paSourceName); + } + ss.channels = getChannel(); + ss.rate = getSampleRate(); + + running = 0; + + //Supported for some bits per sample, both Big and Little endian + if (isBigEndian()) + { + switch (getBitsPerSample()) + { + case 8: + ss.format = PA_SAMPLE_U8; + break; + case 16: + ss.format = PA_SAMPLE_S16BE; + break; + case 24: + ss.format = PA_SAMPLE_S24BE; + break; + case 32: + ss.format = PA_SAMPLE_S32BE; + break; + default: + ss.format = PA_SAMPLE_INVALID; + } + } + else + { + switch (getBitsPerSample()) + { + case 8: + ss.format = PA_SAMPLE_U8; + break; + case 16: + ss.format = PA_SAMPLE_S16LE; + break; + case 24: + ss.format = PA_SAMPLE_S24LE; + break; + case 32: + ss.format = PA_SAMPLE_S32LE; + break; + default: + ss.format = PA_SAMPLE_INVALID; + } + } +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +PulseAudioDspSource :: strip ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + delete[] sourceName; +} + + +/*------------------------------------------------------------------------------ + * Open the audio source + *----------------------------------------------------------------------------*/ +bool +PulseAudioDspSource :: open ( void ) throw ( Exception ) +{ + + char client_name[255]; + + //to identify each darkice on pulseaudio server + snprintf(client_name, 255, "darkice-%d", getpid()); + + if (!(s = pa_simple_new(NULL, client_name, PA_STREAM_RECORD, sourceName, "darkice record", &ss, NULL, NULL, &error))) { + throw Exception( __FILE__, __LINE__, ": pa_simple_new() failed: %s\n", pa_strerror(error)); + } + + running = 1; + + return true; +} + + +/*------------------------------------------------------------------------------ + * Check whether read() would return anything + *----------------------------------------------------------------------------*/ +bool +PulseAudioDspSource :: canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ) +{ + + /** Strange have to remove this, need to investigate... */ + /* if ( !isOpen() ) { + return false; + } + */ + + if (running == 0) { + char client_name[255]; + + //to identify each darkice on pulseaudio server + snprintf(client_name, 255, "darkice-%d", getpid()); + + if (!(s = pa_simple_new(NULL, client_name, PA_STREAM_RECORD, sourceName, "darkice record", &ss, NULL, NULL, &error))) { + throw Exception( __FILE__, __LINE__, ": pa_simple_new() failed: %s\n", pa_strerror(error)); + } + + running = 1; + } + + return true; +} + + +/*------------------------------------------------------------------------------ + * Read from the audio source + *----------------------------------------------------------------------------*/ +unsigned int +PulseAudioDspSource :: read ( void * buf, + unsigned int len ) throw ( Exception ) +{ + int ret; + + ret = pa_simple_read(s, buf, len, &error); + if ( ret < 0) { + throw Exception(__FILE__, __LINE__, ": pa_simple_read() failed: %s\n", pa_strerror(error)); + } + return len; +} + + +/*------------------------------------------------------------------------------ + * Close the audio source + *----------------------------------------------------------------------------*/ +void +PulseAudioDspSource :: close ( void ) throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + pa_simple_free(s); + running = 0; +} + +#endif // HAVE_PULSEAUDIO_LIB diff --git a/darkice/tags/darkice-1_3/src/PulseAudioDspSource.h b/darkice/tags/darkice-1_3/src/PulseAudioDspSource.h new file mode 100644 index 0000000..f59b7b1 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/PulseAudioDspSource.h @@ -0,0 +1,495 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Copyright (c) 2004 + LS Informationstechnik (LIKE) + University of Erlangen Nuremberg + All rights reserved. + + Tyrell DarkIce + + File : PulseAudioDspSource.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef PULSEAUDIO_SOURCE_H +#define PULSEAUDIO_SOURCE_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "Reporter.h" +#include "AudioSource.h" + +#ifdef HAVE_PULSEAUDIO_LIB + +#include +#include +#include +#else +#error configure for PULSEAUDIO +#endif + +/* ================================================================ constants */ + +/* =================================================================== macros */ + +/* =============================================================== data types */ + +/** + * An audio input based on the PULSEAUDIO sound system + * + * @author $Author$ + * @version $Revision$ + */ +class PulseAudioDspSource : public AudioSource, public virtual Reporter +{ + private: + + /** + * Name of the capture PCM stream. + */ + char *sourceName; + + /** + * Handle for PulseAudio + */ + pa_simple *s ; + + /** + * format definitions for pulseaudio + */ + pa_sample_spec ss; + + int running; + int error; + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + PulseAudioDspSource ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Initialize the object + * + * @param name the PCM to open. + * @exception Exception + */ + void + init ( const char * name ) throw ( Exception ); + + /** + * De-iitialize the object + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + public: + + /** + * Constructor. + * + * @param name the PCM (e.g. "hwplug:0,0"). + * @param sampleRate samples per second (e.g. 44100 for 44.1kHz). + * @param bitsPerSample bits per sample (e.g. 16 bits). + * @param channel number of channels of the audio source + * (e.g. 1 for mono, 2 for stereo, etc.). + * @exception Exception + */ + inline + PulseAudioDspSource ( const char * paSourceName, + int sampleRate = 44100, + int bitsPerSample = 16, + int channel = 2 ) + throw ( Exception ) + : AudioSource( sampleRate, bitsPerSample, channel) + { + init( paSourceName); + } + + /** + * Copy Constructor. + * + * @param ds the object to copy. + * @exception Exception + */ + inline + PulseAudioDspSource ( const PulseAudioDspSource & ds ) throw ( Exception ) + : AudioSource( ds ) + { + init( ds.sourceName); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~PulseAudioDspSource ( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param ds the object to assign to this one. + * @return a reference to this object. + * @exception Exception + */ + inline virtual PulseAudioDspSource & + operator= ( const PulseAudioDspSource & ds ) throw ( Exception ) + { + if ( this != &ds ) { + strip(); + AudioSource::operator=( ds); + init( ds.sourceName); + } + return *this; + } + + /** + * Open the PulseAudioDspSource. + * + * @return true if opening was successful, false otherwise + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the PulseAudioDspSource is open. + * + * @return true if the PulseAudioDspSource is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return s==NULL; + } + + /** + * Check if the PulseAudioDspSource can be read from. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the PulseAudioDspSource is ready to be read from, + * false otherwise. + * @exception Exception + */ + virtual bool + canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ); + + /** + * Read from the PulseAudioDspSource. + * + * @param buf the buffer to read into. + * @param len the number of bytes to read into buf + * @return the number of bytes read (may be less than len). + * @exception Exception + */ + virtual unsigned int + read ( void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Close the PulseAudioDspSource. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); + +}; + +/* ================================================= external data structures */ + +/* ====================================================== function prototypes */ + +#endif /* PULSEAUDIO_SOURCE_H */ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Copyright (c) 2004 + LS Informationstechnik (LIKE) + University of Erlangen Nuremberg + All rights reserved. + + Tyrell DarkIce + + File : PulseAudioDspSource.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef PULSEAUDIO_SOURCE_H +#define PULSEAUDIO_SOURCE_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "Reporter.h" +#include "AudioSource.h" + +#ifdef HAVE_PULSEAUDIO_LIB + +#include +#include +#include +#else +#error configure for PULSEAUDIO +#endif + +/* ================================================================ constants */ + +/* =================================================================== macros */ + +/* =============================================================== data types */ + +/** + * An audio input based on the PULSEAUDIO sound system + * + * @author $Author$ + * @version $Revision$ + */ +class PulseAudioDspSource : public AudioSource, public virtual Reporter +{ + private: + + /** + * Name of the capture PCM stream. + */ + char *sourceName; + + /** + * Handle for PulseAudio + */ + pa_simple *s ; + + /** + * format definitions for pulseaudio + */ + pa_sample_spec ss; + + int error; + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + PulseAudioDspSource ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Initialize the object + * + * @param name the PCM to open. + * @exception Exception + */ + void + init ( const char * name ) throw ( Exception ); + + /** + * De-iitialize the object + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + public: + + /** + * Constructor. + * + * @param name the PCM (e.g. "hwplug:0,0"). + * @param sampleRate samples per second (e.g. 44100 for 44.1kHz). + * @param bitsPerSample bits per sample (e.g. 16 bits). + * @param channel number of channels of the audio source + * (e.g. 1 for mono, 2 for stereo, etc.). + * @exception Exception + */ + inline + PulseAudioDspSource ( const char * paSourceName, + int sampleRate = 44100, + int bitsPerSample = 16, + int channel = 2 ) + throw ( Exception ) + : AudioSource( sampleRate, bitsPerSample, channel) + { + init( paSourceName); + } + + /** + * Copy Constructor. + * + * @param ds the object to copy. + * @exception Exception + */ + inline + PulseAudioDspSource ( const PulseAudioDspSource & ds ) throw ( Exception ) + : AudioSource( ds ) + { + init( ds.sourceName); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~PulseAudioDspSource ( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param ds the object to assign to this one. + * @return a reference to this object. + * @exception Exception + */ + inline virtual PulseAudioDspSource & + operator= ( const PulseAudioDspSource & ds ) throw ( Exception ) + { + if ( this != &ds ) { + strip(); + AudioSource::operator=( ds); + init( ds.sourceName); + } + return *this; + } + + /** + * Open the PulseAudioDspSource. + * + * @return true if opening was successful, false otherwise + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the PulseAudioDspSource is open. + * + * @return true if the PulseAudioDspSource is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return s==NULL; + } + + /** + * Check if the PulseAudioDspSource can be read from. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the PulseAudioDspSource is ready to be read from, + * false otherwise. + * @exception Exception + */ + virtual bool + canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ); + + /** + * Read from the PulseAudioDspSource. + * + * @param buf the buffer to read into. + * @param len the number of bytes to read into buf + * @return the number of bytes read (may be less than len). + * @exception Exception + */ + virtual unsigned int + read ( void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Close the PulseAudioDspSource. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); + +}; + +/* ================================================= external data structures */ + +/* ====================================================== function prototypes */ + +#endif /* PULSEAUDIO_SOURCE_H */ diff --git a/darkice/tags/darkice-1_3/src/Ref.h b/darkice/tags/darkice-1_3/src/Ref.h new file mode 100644 index 0000000..810f7ae --- /dev/null +++ b/darkice/tags/darkice-1_3/src/Ref.h @@ -0,0 +1,296 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : Ref.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef REF_H +#define REF_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Exception.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * Java-like object reference class. + * Objects used with this reference class have to be descandents + * of class Referable. + * + * sample usage: + * + *
+ *  #include "Ref.h"
+ *  #include "Referable.h"
+ *
+ *  class  A : public virtual Referable;
+ *
+ *  ...
+ *   
+ *  A        * a = new A();
+ *  Ref     ref1 = a;       // 1 reference to a
+ *  Ref     ref2 = ref1;    // 2 references to a
+ *
+ *  ref1 = 0;      // 1 reference to a
+ *  ref2 = 0;      // at this point object a is destroyed
+ *  
+ * + * Based on Tima Saarinen's work, + * http://gamma.nic.fi/~timosa/comp/refcount.html + * + * @ref Referable + * + * @author $Author$ + * @version $Revision$ + */ +template +class Ref +{ + private: + + /** + * The object referenced by this Ref. + * Must be a descandant of Referable. + */ + T* object; + + + protected: + + + public: + + /** + * Default constructor. + */ + inline + Ref ( void ) throw () + { + object = NULL; + } + + /** + * Copy constructor. + * + * @param other the Ref to copy. + * @exception Exception + */ + inline + Ref ( const Ref & other ) throw ( Exception ) + { + object = NULL; + set( other.object); + } + + /** + * Constructor based on an object to reference. + * + * @param obj the object to reference. + * @exception Exception + */ + inline + Ref ( T * obj ) throw ( Exception ) + { + object = obj; + obj->increaseReferenceCount(); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~Ref ( void ) throw ( Exception ) + { + set( 0 ); + } + + /** + * Operator overload to make the reference seem like a pointer. + * + * @return the pointer to the object referenced. + */ + inline T* + operator->() const throw ( Exception ) + { + if ( !object ) { + throw Exception( __FILE__, __LINE__, + "reference to NULL object"); + } + return object; + } + + /** + * Assignment operator. + * + * @param other the Ref to assign to this one. + * @return a reference to this Ref. + * @exception Exception + */ + inline Ref & + operator= ( Ref other ) throw ( Exception ) + { + set( other.object); + return *this; + } + + /** + * Assignment operator. + * + * @param obj pointer to the object to assign to this Ref. + * @return a reference to this Ref. + * @exception Exception + */ + inline Ref & + operator= ( T* obj ) throw ( Exception ) + { + set( obj); + return *this; + } + + /** + * Set the object referenced. + * Deletes the old referenced object is this was it's last reference. + * + * @param newobj pointer to the object to reference by this Ref. + * @exception Exception + */ + inline void + set ( T * newobj ) throw ( Exception ) + { + // If equal do nothing + if ( newobj == object ) { + return; + } + + // Increase reference count + if ( newobj ) { + newobj->increaseReferenceCount(); + } + + // Decrease the reference count of the old referable + if ( object ) { + if ( object->decreaseReferenceCount() == 0 ) { + delete object; + } + } + + // Assign + object = newobj; + } + + /** + * Return object pointer. This method should be used with + * care because it breaks the encapsulation. + * Typically this method is needed for the method calls + * which require literal object pointer. + * + * It may not be bad idea to pass the Ref + * objects as method arguments. + * + * @return Object pointer or NULL. + */ + inline T* + get ( void ) const throw () + { + return object; + } + + /** + * Equality operator. + * + * @param other the pointer to compare this with. + * @return true is this Ref refers to the same object as other, + * false otherwise. + */ + inline bool + operator== ( const T * other ) const throw () + { + return object == other; + } + + /** + * Equality operator. + * + * @param other the Ref to compare this with. + * @return true is the two Refs refer to the same object, + * false otherwise. + */ + inline bool + operator== ( const Ref & other ) const throw () + { + return object == other.object; + } + + /** + * Unequality operator. + * + * @param other the pointer to compare this with. + * @return false is this Ref refers to a different object then other, + * true otherwise. + */ + inline bool + operator!= ( const T * other ) const throw () + { + return object != other; + } + + /** + * Unequality operator. + * + * @param other the Ref to compare this with. + * @return false is the two Refs refer to the same object, + * true otherwise. + */ + inline bool + operator!= ( const Ref & other ) const throw () + { + return object != other.object; + } +}; + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* REF_H */ + diff --git a/darkice/tags/darkice-1_3/src/Referable.h b/darkice/tags/darkice-1_3/src/Referable.h new file mode 100644 index 0000000..46b820c --- /dev/null +++ b/darkice/tags/darkice-1_3/src/Referable.h @@ -0,0 +1,170 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : Referable.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef REFERABLE_H +#define REFERABLE_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Exception.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * Base class for an object for which references can be made + * with the reference class Ref. + * + * usage: + * + *
+ *  class A : public virtual Referable
+ *  {
+ *     ...
+ *  };
+ *  
+ * + * @ref Ref + * + * @author $Author$ + * @version $Revision$ + */ +class Referable +{ + private: + + /** + * Number of references to the object. + */ + unsigned int referenceCount; + + /** + * Maximum number of references before an overflow occurs. + */ + static const + unsigned int maxCount = ~((unsigned int)0); + + + protected: + + /** + * Default constructor. + */ + inline + Referable ( void ) throw () + { + referenceCount = 0; + } + + + /** + * Desctructor. + * + * @exception Exception + */ + inline virtual + ~Referable ( void ) throw ( Exception ) + { + if ( referenceCount > 0 ) { + throw Exception( __FILE__, __LINE__, + "reference count positive in destructor", + referenceCount); + } + } + + + public: + + /** + * Increase reference count. + * + * @return the new reference count. + * @exception Exception + */ + inline unsigned int + increaseReferenceCount ( void ) throw ( Exception ) + { + if ( referenceCount >= maxCount ) { + throw Exception( __FILE__, + __LINE__, + "reference count overflow", + referenceCount ); + } + return ++referenceCount; + } + + /** + * Decrease reference count. + * + * @return the new reference count. + * @exception Exception + */ + inline unsigned int + decreaseReferenceCount ( void ) throw ( Exception ) + { + if ( referenceCount == 0 ) { + throw Exception( __FILE__, __LINE__, + "reference count underflow", + referenceCount ); + } + return --referenceCount; + } + + /** + * Get the reference count. + * + * @return the reference count. + */ + inline unsigned int + getReferenceCount ( void ) const throw () + { + return referenceCount; + } +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* REFERABLE_H */ + diff --git a/darkice/tags/darkice-1_3/src/Reporter.cpp b/darkice/tags/darkice-1_3/src/Reporter.cpp new file mode 100644 index 0000000..849a4cc --- /dev/null +++ b/darkice/tags/darkice-1_3/src/Reporter.cpp @@ -0,0 +1,60 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell Reporter + + File : Reporter.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#include + +#include "Reporter.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/*------------------------------------------------------------------------------ + * Initial values for static members of the class + *----------------------------------------------------------------------------*/ +unsigned int Reporter::verbosity = 1; +std::ostream * Reporter::os = &std::cout; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + + diff --git a/darkice/tags/darkice-1_3/src/Reporter.h b/darkice/tags/darkice-1_3/src/Reporter.h new file mode 100644 index 0000000..d30109f --- /dev/null +++ b/darkice/tags/darkice-1_3/src/Reporter.h @@ -0,0 +1,305 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell Reporter + + File : Reporter.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef REPORTER_H +#define REPORTER_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_UNISTD_H +#include +#else +#error need unistd.h +#endif + +#ifdef HAVE_TIME_H +#include +#else +#error need time.h +#endif + + +#include + + +#include "Exception.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * Class for reporting events. All objects of this class share + * the same verbosity level. Typical usage is to inherit this class + * and use the report() function to report events. Only reports + * which are of suffucient importance are really reported. + * + * The default verbosity is 1, and the default ostream is cout. + * + * Known problems: this class is not thread-safe. + * + * @author $Author$ + * @version $Revision$ + */ +class Reporter +{ + + private: + + /** + * Verbosity level shared among all Reporter objects + */ + static unsigned int verbosity; + + /** + * The output stream to report to. + */ + static std::ostream * os; + + /** + * Print timestamp for every report only if verbosity level + * is above this value. + */ + static const unsigned int prefixVerbosity = 3; + + /** + * Print a prefix to each report. + */ + static void + printPrefix( void ) throw () + { + if ( verbosity > prefixVerbosity ) { + char str[32]; + time_t now; + + now = time(NULL); + strftime( str, 32, "%d-%b-%Y %H:%M:%S ", localtime(&now) ); + (*(Reporter::os)) << str; + } + } + + + protected: + + + public: + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~Reporter ( void ) throw ( Exception ) + { + (Reporter::os)->flush(); + } + + /** + * Set the verbosity level. This sets the verbosity for all + * Reporter objects. + * + * @param verbosity the new verbosity level. + */ + static inline void + setReportVerbosity ( unsigned int verbosity ) throw () + { + Reporter::verbosity = verbosity; + } + + /** + * Get the verbosity level. + * + * @return the current verbosity level. + */ + static inline unsigned int + getReportVerbosity ( void ) throw () + { + return Reporter::verbosity; + } + + /** + * Set the output stream to report to. This setting effects all + * Reporter objects. + * + * @param os the output stream + */ + static inline void + setReportOutputStream ( std::ostream & os ) throw () + { + Reporter::os = &os; + } + + /** + * Get the output stream to report to. + * + * @return the output stream + */ + static inline std::ostream & + getReportOutputStream ( void ) throw () + { + return *(Reporter::os); + } + + /** + * Report an event with a given verbosity. + * + * @param verbosity the importance of the event, with 0 being + * the most important. + * @param t the object to report. Must have an + * ostream & operator<<( ostream&, const T) + * operator overload. + */ + template + static inline void + reportEvent ( unsigned int verbosity, + const T t ) throw () + { + if ( Reporter::verbosity >= verbosity ) { + printPrefix(); + (*(Reporter::os)) << t << std::endl; + } + } + + /** + * Report an event with a given verbosity. + * + * @param verbosity the importance of the event, with 0 being + * the most important. + * @param t the object 1 to report. Must have an + * ostream & operator<<( ostream&, const T) + * operator overload. + * @param u the object 2 to report. Must have an + * ostream & operator<<( ostream&, const U) + * operator overload. + */ + template + inline void + static reportEvent ( unsigned int verbosity, + const T t, + const U u ) throw () + { + if ( Reporter::verbosity >= verbosity ) { + printPrefix(); + (*(Reporter::os)) << t << " " + << u << std::endl; + } + } + + /** + * Report an event with a given verbosity. + * + * @param verbosity the importance of the event, with 0 being + * the most important. + * @param t the object 1 to report. Must have an + * ostream & operator<<( ostream&, const T) + * operator overload. + * @param u the object 2 to report. Must have an + * ostream & operator<<( ostream&, const U) + * operator overload. + * @param v the object 3 to report. Must have an + * ostream & operator<<( ostream&, const V) + * operator overload. + */ + template + static inline void + reportEvent ( unsigned int verbosity, + const T t, + const U u, + const V v ) throw () + { + if ( Reporter::verbosity >= verbosity ) { + printPrefix(); + (*(Reporter::os)) << t << " " + << u << " " + << v << std::endl; + } + } + + /** + * Report an event with a given verbosity. + * + * @param verbosity the importance of the event, with 0 being + * the most important. + * @param t the object 1 to report. Must have an + * ostream & operator<<( ostream&, const T) + * operator overload. + * @param u the object 2 to report. Must have an + * ostream & operator<<( ostream&, const U) + * operator overload. + * @param v the object 3 to report. Must have an + * ostream & operator<<( ostream&, const V) + * operator overload. + * @param w the object 4 to report. Must have an + * ostream & operator<<( ostream&, const W) + * operator overload. + */ + template + static inline void + reportEvent ( unsigned int verbosity, + const T t, + const U u, + const V v, + const W w ) throw () + { + if ( Reporter::verbosity >= verbosity ) { + printPrefix(); + (*(Reporter::os)) << t << " " + << u << " " + << v << " " + << w << std::endl; + } + } +}; + + + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* REPORTER_H */ + diff --git a/darkice/tags/darkice-1_3/src/SerialUlaw.cpp b/darkice/tags/darkice-1_3/src/SerialUlaw.cpp new file mode 100644 index 0000000..37ce26a --- /dev/null +++ b/darkice/tags/darkice-1_3/src/SerialUlaw.cpp @@ -0,0 +1,338 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000 Tyrell Corporation. + Copyright (c) 2006 Clyde Stubbs. + + Tyrell DarkIce + + File : SerialUlaw.cpp + Version : $Revision$ + Author : $Author$ + Location : $Source: /cvsroot/darkice/darkice/src/SerialUlaw.cpp,v $ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#include "SerialUlaw.h" + +#ifdef SUPPORT_SERIAL_ULAW +// only compile this code if there's support for it + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STDIO_H +#include +#else +#error need stdio.h +#endif + +#ifdef HAVE_UNISTD_H +#include +#else +#error need unistd.h +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#else +#error need sys/types.h +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#else +#error need sys/stat.h +#endif + +#ifdef HAVE_FCNTL_H +#include +#else +#error need fcntl.h +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#else +#error need sys/time.h +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include +#else +#error need sys/ioctl.h +#endif + +#ifdef HAVE_TERMIOS_H +#include +#else +#error need termios.h +#endif + +#ifdef HAVE_STDIO_H +#include +#endif + + +#include "Util.h" +#include "Exception.h" +#include "SerialUlaw.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/*------------------------------------------------------------------------------ + * Ulaw decode table + *----------------------------------------------------------------------------*/ +static unsigned int ulawdecode[256] = +{ + 0x8284,0x8684,0x8a84,0x8e84,0x9284,0x9684,0x9a84,0x9e84, + 0xa284,0xa684,0xaa84,0xae84,0xb284,0xb684,0xba84,0xbe84, + 0xc184,0xc384,0xc584,0xc784,0xc984,0xcb84,0xcd84,0xcf84, + 0xd184,0xd384,0xd584,0xd784,0xd984,0xdb84,0xdd84,0xdf84, + 0xe104,0xe204,0xe304,0xe404,0xe504,0xe604,0xe704,0xe804, + 0xe904,0xea04,0xeb04,0xec04,0xed04,0xee04,0xef04,0xf004, + 0xf0c4,0xf144,0xf1c4,0xf244,0xf2c4,0xf344,0xf3c4,0xf444, + 0xf4c4,0xf544,0xf5c4,0xf644,0xf6c4,0xf744,0xf7c4,0xf844, + 0xf8a4,0xf8e4,0xf924,0xf964,0xf9a4,0xf9e4,0xfa24,0xfa64, + 0xfaa4,0xfae4,0xfb24,0xfb64,0xfba4,0xfbe4,0xfc24,0xfc64, + 0xfc94,0xfcb4,0xfcd4,0xfcf4,0xfd14,0xfd34,0xfd54,0xfd74, + 0xfd94,0xfdb4,0xfdd4,0xfdf4,0xfe14,0xfe34,0xfe54,0xfe74, + 0xfe8c,0xfe9c,0xfeac,0xfebc,0xfecc,0xfedc,0xfeec,0xfefc, + 0xff0c,0xff1c,0xff2c,0xff3c,0xff4c,0xff5c,0xff6c,0xff7c, + 0xff88,0xff90,0xff98,0xffa0,0xffa8,0xffb0,0xffb8,0xffc0, + 0xffc8,0xffd0,0xffd8,0xffe0,0xffe8,0xfff0,0xfff8,0x0000, + 0x7d7c,0x797c,0x757c,0x717c,0x6d7c,0x697c,0x657c,0x617c, + 0x5d7c,0x597c,0x557c,0x517c,0x4d7c,0x497c,0x457c,0x417c, + 0x3e7c,0x3c7c,0x3a7c,0x387c,0x367c,0x347c,0x327c,0x307c, + 0x2e7c,0x2c7c,0x2a7c,0x287c,0x267c,0x247c,0x227c,0x207c, + 0x1efc,0x1dfc,0x1cfc,0x1bfc,0x1afc,0x19fc,0x18fc,0x17fc, + 0x16fc,0x15fc,0x14fc,0x13fc,0x12fc,0x11fc,0x10fc,0x0ffc, + 0x0f3c,0x0ebc,0x0e3c,0x0dbc,0x0d3c,0x0cbc,0x0c3c,0x0bbc, + 0x0b3c,0x0abc,0x0a3c,0x09bc,0x093c,0x08bc,0x083c,0x07bc, + 0x075c,0x071c,0x06dc,0x069c,0x065c,0x061c,0x05dc,0x059c, + 0x055c,0x051c,0x04dc,0x049c,0x045c,0x041c,0x03dc,0x039c, + 0x036c,0x034c,0x032c,0x030c,0x02ec,0x02cc,0x02ac,0x028c, + 0x026c,0x024c,0x022c,0x020c,0x01ec,0x01cc,0x01ac,0x018c, + 0x0174,0x0164,0x0154,0x0144,0x0134,0x0124,0x0114,0x0104, + 0x00f4,0x00e4,0x00d4,0x00c4,0x00b4,0x00a4,0x0094,0x0084, + 0x0078,0x0070,0x0068,0x0060,0x0058,0x0050,0x0048,0x0040, + 0x0038,0x0030,0x0028,0x0020,0x0018,0x0010,0x0008,0x0000, +}; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Tell if source id big endian + *----------------------------------------------------------------------------*/ +bool +SerialUlaw :: isBigEndian ( void ) const throw () +{ + return false; +} + + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +SerialUlaw :: init ( const char * name ) throw ( Exception ) +{ + fileName = Util::strDup( name); + fileDescriptor = 0; + running = false; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +SerialUlaw :: strip ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + delete[] fileName; +} + + +/*------------------------------------------------------------------------------ + * Open the audio source + *----------------------------------------------------------------------------*/ +bool +SerialUlaw :: open ( void ) throw ( Exception ) +{ + struct termios ts; + + if ( isOpen() ) { + return false; + } + + switch ( getBitsPerSample() ) { + case 16: + break; + + default: + return false; + } + + if (getChannel() != 1) { + reportEvent(3, "Only mono input supported for Serial ULaw"); + return false; + } + if (getSampleRate() != 8000) { + reportEvent(3, "Only 8000 Hz sample rate supported for Serial ULaw"); + return false; + } + + if ( (fileDescriptor = ::open( fileName, O_RDONLY)) == -1 ) { + fileDescriptor = 0; + return false; + } + + if(tcgetattr(fileDescriptor, &ts) < 0) { + close(); + throw Exception( __FILE__, __LINE__, "can't get tty settings"); + } + + cfsetispeed(&ts, B115200); + cfmakeraw(&ts); + ts.c_cflag |= CLOCAL; + if(tcsetattr(fileDescriptor, TCSANOW, &ts) < 0) { + close(); + throw Exception( __FILE__, __LINE__, "can't set tty settings"); + } + + tcflush(fileDescriptor, TCIFLUSH); + + return true; +} + + +/*------------------------------------------------------------------------------ + * Check whether read() would return anything + *----------------------------------------------------------------------------*/ +bool +SerialUlaw :: canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ) +{ + fd_set fdset; + struct timeval tv; + int ret; + + if ( !isOpen() ) { + return false; + } + + FD_ZERO( &fdset); + FD_SET( fileDescriptor, &fdset); + tv.tv_sec = sec; + tv.tv_usec = usec; + + ret = select( fileDescriptor + 1, &fdset, NULL, NULL, &tv); + + if ( ret == -1 ) { + throw Exception( __FILE__, __LINE__, "select error"); + } + + return ret > 0; +} + + +/*------------------------------------------------------------------------------ + * Read from the audio source + *----------------------------------------------------------------------------*/ +unsigned int +SerialUlaw :: read ( void * buf, + unsigned int len ) throw ( Exception ) +{ + ssize_t ret; + unsigned char ubuf[256], * ptr; + int i, plen; + + if ( !isOpen() ) { + return 0; + } + + ret = 0; + ptr = (unsigned char *)buf; + while(len > 1) { + plen = sizeof(ubuf); + if (plen > (int)len/2) { + plen = len/2; + } + plen = ::read( fileDescriptor, ubuf, plen); + if(plen < 0) { + perror("read"); + throw Exception( __FILE__, __LINE__, "read error"); + } + for(i = 0 ; i != plen ; i++) { + *ptr++ = ulawdecode[ubuf[i]] & 0xFF; + *ptr++ = ulawdecode[ubuf[i]] >> 8; + } + len -= plen*2; + ret += plen*2; + } + + running = true; + return ret; +} + + +/*------------------------------------------------------------------------------ + * Close the audio source + *----------------------------------------------------------------------------*/ +void +SerialUlaw :: close ( void ) throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + ::close( fileDescriptor); + fileDescriptor = 0; + running = false; +} + + +#endif // SUPPORT_SERIAL_ULAW diff --git a/darkice/tags/darkice-1_3/src/SerialUlaw.h b/darkice/tags/darkice-1_3/src/SerialUlaw.h new file mode 100644 index 0000000..24ef8a9 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/SerialUlaw.h @@ -0,0 +1,255 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + Copyright (c) 2007 Clyde Stubbs + + Tyrell DarkIce + + File : SerialUlaw.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef SERIAL_ULAW_SOURCE_H +#define SERIAL_ULAW_SOURCE_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Reporter.h" +#include "AudioSource.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * An audio input based on /dev/dsp-like raw devices + * + * @author $Author$ + * @version $Revision$ + */ +class SerialUlaw : public AudioSource, public virtual Reporter +{ + private: + + /** + * The file name of the OSS DSP device (e.g. /dev/dsp or /dev/dsp0). + */ + char * fileName; + + /** + * The low-level file descriptor of the OSS DSP device. + */ + int fileDescriptor; + + /** + * Indicates whether the low-level OSS DSP device is in a recording + * state. + */ + bool running; + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + SerialUlaw ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Initialize the object + * + * @param name the file name of the OSS DSP device. + * @exception Exception + */ + void + init ( const char * name ) throw ( Exception ); + + /** + * De-iitialize the object + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + public: + + /** + * Constructor. + * + * @param name the file name of the OSS DSP device + * (e.g. /dev/dsp or /dev/dsp0). + * @param sampleRate samples per second (e.g. 44100 for 44.1kHz). + * @param bitsPerSample bits per sample (e.g. 16 bits). + * @param channel number of channels of the audio source + * (e.g. 1 for mono, 2 for stereo, etc.). + * @exception Exception + */ + inline + SerialUlaw ( const char * name, + int sampleRate = 44100, + int bitsPerSample = 16, + int channel = 2 ) + throw ( Exception ) + + : AudioSource( sampleRate, bitsPerSample, channel) + { + init( name); + } + + /** + * Copy Constructor. + * + * @param ods the object to copy. + * @exception Exception + */ + inline + SerialUlaw ( const SerialUlaw & ods ) throw ( Exception ) + : AudioSource( ods ) + { + init( ods.fileName); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~SerialUlaw ( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param ds the object to assign to this one. + * @return a reference to this object. + * @exception Exception + */ + inline virtual SerialUlaw & + operator= ( const SerialUlaw & ds ) throw ( Exception ) + { + if ( this != &ds ) { + strip(); + AudioSource::operator=( ds); + init( ds.fileName); + } + return *this; + } + + /** + * Tell if the data from this source comes in big or little endian. + * + * @return true if the source is big endian, false otherwise + */ + virtual bool + isBigEndian ( void ) const throw (); + + /** + * Open the SerialUlaw. + * This does not put the OSS DSP device into recording mode. + * To start getting samples, call either canRead() or read(). + * + * @return true if opening was successful, false otherwise + * @exception Exception + * + * @see #canRead + * @see #read + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the SerialUlaw is open. + * + * @return true if the SerialUlaw is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return fileDescriptor != 0; + } + + /** + * Check if the SerialUlaw can be read from. + * Blocks until the specified time for data to be available. + * Puts the OSS DSP device into recording mode. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the SerialUlaw is ready to be read from, + * false otherwise. + * @exception Exception + */ + virtual bool + canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ); + + /** + * Read from the SerialUlaw. + * Puts the OSS DSP device into recording mode. + * + * @param buf the buffer to read into. + * @param len the number of bytes to read into buf + * @return the number of bytes read (may be less than len). + * @exception Exception + */ + virtual unsigned int + read ( void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Close the SerialUlaw. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* SERIAL_ULAW_SOURCE_H */ diff --git a/darkice/tags/darkice-1_3/src/ShoutCast.cpp b/darkice/tags/darkice-1_3/src/ShoutCast.cpp new file mode 100644 index 0000000..058f394 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/ShoutCast.cpp @@ -0,0 +1,253 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : ShoutCast.cpp + Version : $Revision$ + Author : $Author$ + Location : $Source$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STDIO_H +#include +#else +#error need stdio.h +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + +#ifdef HAVE_MATH_H +#include +#else +#error need math.h +#endif + +#include + + +#include "Exception.h" +#include "Source.h" +#include "Sink.h" +#include "Util.h" +#include "ShoutCast.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/*------------------------------------------------------------------------------ + * Size of string conversion buffer + *----------------------------------------------------------------------------*/ +#define STRBUF_SIZE 32 +#define HEADERLINE_LENGTH 50 + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +ShoutCast :: init ( const char * irc, + const char * aim, + const char * icq, + const char * mountPoint ) + throw ( Exception ) +{ + this->irc = irc ? Util::strDup( irc) : 0; + this->aim = aim ? Util::strDup( aim) : 0; + this->icq = icq ? Util::strDup( icq) : 0; + this->mountPoint = mountPoint ? Util::strDup( mountPoint ) : 0; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +ShoutCast :: strip ( void ) throw ( Exception ) +{ + if ( irc ) { + delete[] irc; + } + if ( aim ) { + delete[] aim; + } + if ( icq ) { + delete[] icq; + } + if (mountPoint ){ + delete[] mountPoint; + } +} + + +/*------------------------------------------------------------------------------ + * Log in to the ShoutCast server using the icy login scheme + *----------------------------------------------------------------------------*/ +bool +ShoutCast :: sendLogin ( void ) throw ( Exception ) +{ + Sink * sink = getSink(); + Source * source = getSocket(); + const char * str; + char resp[STRBUF_SIZE]; + unsigned int len; + bool needsMountPoint = false; + const char * mountPoint = getMountPoint(); + char header_line[HEADERLINE_LENGTH+2]; // ... + \n + \0 + + if ( !source->isOpen() ) { + return false; + } + if ( !sink->isOpen() ) { + return false; + } + + // We will add SOURCE only if really needed: if the mountPoint is not null + // and is different of "/". This is to keep maximum compatibility with + // NullSoft Shoutcast server. + if (mountPoint != 0L + && strlen(mountPoint) > 0 && 0 != strcmp("/", mountPoint)) { + needsMountPoint = true; + } + + std::ostringstream os; + + if (needsMountPoint) { + os << "SOURCE "; + } + + /* first line is the password in itself */ + os << getPassword(); + os << "\n"; + + // send the mount point + if (needsMountPoint) { + os << " "; + if (strncmp("/", mountPoint, 1) != 0) { + os << "/"; + } + os << mountPoint; + os << "\n"; + } + + str = os.str().c_str(); + + // Ok, now we send login which will be different of classical Shoutcast + // if mountPoint is not null and is different from "/" ... + sink->write( str, strlen( str)); + sink->flush(); + + /* read the anticipated response: "OK" */ + len = source->read( resp, STRBUF_SIZE); + reportEvent(8, "server response length: ", len); + reportEvent(8, "server response: ", resp); + + if ( Util::strEq( resp, "invalid password",16) ) { + throw Exception( __FILE__, __LINE__, + "ShoutCast - wrong password"); + } + + if ( len < 2 || resp[0] != 'O' || resp[1] != 'K' ) { + return false; + } + + /* suck anything that the other side has to say */ + while ( source->canRead( 0, 0) && + (len = source->read( resp, STRBUF_SIZE)) ) { + ; + } + + /* send the icy headers */ + if ( getName() ) { + snprintf(header_line, HEADERLINE_LENGTH, "icy-name:%s", getName()); + strcat(header_line, "\n"); + sink->write( header_line, strlen( header_line)); + } + + if ( getUrl() ) { + snprintf(header_line, HEADERLINE_LENGTH, "icy-url:%s", getUrl()); + strcat(header_line, "\n"); + sink->write( header_line, strlen( header_line)); + } + + if ( getGenre() ) { + snprintf(header_line, HEADERLINE_LENGTH, "icy-genre:%s", getGenre()); + strcat(header_line, "\n"); + sink->write( header_line, strlen( header_line)); + } + + if ( getIrc() ) { + snprintf(header_line, HEADERLINE_LENGTH, "icy-irc:%s", getIrc()); + strcat(header_line, "\n"); + sink->write( header_line, strlen( header_line)); + } + + if ( getAim() ) { + snprintf(header_line, HEADERLINE_LENGTH, "icy-aim:%s", getAim()); + strcat(header_line, "\n"); + sink->write( header_line, strlen( header_line)); + } + + if ( getIcq() ) { + snprintf(header_line, HEADERLINE_LENGTH, "icy-icq:%s", getIcq()); + strcat(header_line, "\n"); + sink->write( header_line, strlen( header_line)); + } + + snprintf(header_line, HEADERLINE_LENGTH, "icy-br:%d", getBitRate()); + strcat(header_line, "\n"); + sink->write( header_line, strlen( header_line)); + + snprintf(header_line, HEADERLINE_LENGTH, "icy-pub:%s", getIsPublic() ? "1" : "0"); + strcat(header_line, "\n"); + sink->write( header_line, strlen( header_line)); + + str = "\n"; + sink->write( str, strlen( str)); + sink->flush(); + + return true; +} + + diff --git a/darkice/tags/darkice-1_3/src/ShoutCast.h b/darkice/tags/darkice-1_3/src/ShoutCast.h new file mode 100644 index 0000000..9f0048e --- /dev/null +++ b/darkice/tags/darkice-1_3/src/ShoutCast.h @@ -0,0 +1,279 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : ShoutCast.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef SHOUT_CAST_H +#define SHOUT_CAST_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Sink.h" +#include "TcpSocket.h" +#include "CastSink.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * Class representing output to a ShoutCast server with + * icy login + * + * @author $Author$ + * @version $Revision$ + */ +class ShoutCast : public CastSink +{ + private: + + /** + * IRC info string for the stream + */ + char * irc; + + /** + * AIM info string for the stream + */ + char * aim; + + /** + * ICQ info string for the stream + */ + char * icq; + + /** + * The optional mountPoint + */ + char * mountPoint; + + /** + * Initalize the object. + * + * @param irc IRC info string for the stream. + * @param aim AIM info string for the stream. + * @param icq ICQ info string for the stream. + * @param mountPoint Optional mount point information + * @exception Exception + */ + void + init ( const char * irc, + const char * aim, + const char * icq, + const char * mountPoint ) + throw ( Exception ); + + /** + * De-initalize the object. + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + ShoutCast ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Log in to the server using the socket avialable. + * + * @return true if login was successful, false otherwise. + * @exception Exception + */ + virtual bool + sendLogin ( void ) throw ( Exception ); + + + public: + + /** + * Constructor. + * + * @param socket socket connection to the server. + * @param password password to the server. + * @param mountPoint Optional mount point for DSS. + * @param name name of the stream. + * @param url URL associated with the stream. + * @param genre genre of the stream. + * @param bitRate bitrate of the stream (e.g. mp3 bitrate). + * @param isPublic is the stream public? + * @param irc IRC info string for the stream. + * @param aim AIM info string for the stream. + * @param icq ICQ info string for the stream. + * @param streamDump an optional sink to dump the binary stream + * data to. + * @param bufferDuration duration of the BufferedSink buffer + * in seconds. + * @exception Exception + */ + inline + ShoutCast ( TcpSocket * socket, + const char * password, + const char * mountPoint, + unsigned int bitRate, + const char * name = 0, + const char * url = 0, + const char * genre = 0, + bool isPublic = false, + const char * irc = 0, + const char * aim = 0, + const char * icq = 0, + Sink * streamDump = 0 ) + throw ( Exception ) + : CastSink( socket, + password, + bitRate, + name, + url, + genre, + isPublic, + streamDump ) + { + init( irc, aim, icq, mountPoint ); + } + + /** + * Copy constructor. + * + * @param cs the ShoutCast to copy. + */ + inline + ShoutCast( const ShoutCast & cs ) throw ( Exception ) + : CastSink( cs ) + { + init( cs.getIrc(), cs.getAim(), cs.getIcq(), cs.getMountPoint()); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~ShoutCast( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param cs the ShoutCast to assign this to. + * @return a reference to this ShoutCast. + * @exception Exception + */ + inline virtual ShoutCast & + operator= ( const ShoutCast & cs ) throw ( Exception ) + { + if ( this != &cs ) { + strip(); + CastSink::operator=( cs ); + init( cs.getIrc(), cs.getAim(), cs.getIcq(), getMountPoint()); + } + return *this; + } + + /** + * Get the mount point of the stream on the server. + * The mount point can be null if it has not been set + * (typical Shoutcast server) or not null (for instance + * with Darwin Streaming Server). In that case, the + * authentication process will be slightly different. + * + * @return the mount point of the stream on the server. + */ + inline const char * + getMountPoint ( void ) const throw () + { + return mountPoint; + } + + /** + * Get the IRC info string for the stream. + * + * @return the IRC info string for the stream. + */ + inline const char * + getIrc ( void ) const throw () + { + return irc; + } + + /** + * Get the AIM info string for the stream. + * + * @return the AIM info string for the stream. + */ + inline const char * + getAim ( void ) const throw () + { + return aim; + } + + /** + * Get the ICQ info string for the stream. + * + * @return the ICQ info string for the stream. + */ + inline const char * + getIcq ( void ) const throw () + { + return icq; + } + +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* SHOUT_CAST_H */ + diff --git a/darkice/tags/darkice-1_3/src/Sink.h b/darkice/tags/darkice-1_3/src/Sink.h new file mode 100644 index 0000000..680bf97 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/Sink.h @@ -0,0 +1,185 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : Sink.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef SINK_H +#define SINK_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Referable.h" +#include "Exception.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A general data sink + * + * @author $Author$ + * @version $Revision$ + */ +class Sink : public virtual Referable +{ + private: + + + protected: + + /** + * Default constructor. + */ + inline + Sink ( void ) throw () + { + } + + /** + * Copy constructor. + * + * @param sink the Sink to copy. + */ + inline + Sink ( const Sink & sink ) throw () + { + } + + /** + * Assignment operator. + * + * @param sink the Sink to assign this to. + * @return a reference to this Sink. + * @exception Exception + */ + inline virtual Sink & + operator= ( const Sink & sink ) throw ( Exception ) + { + return *this; + } + + + public: + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~Sink ( void ) throw ( Exception ) + { + } + + /** + * Open the sink. + * + * @return true if opening was successfull, false otherwise. + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ) = 0; + + /** + * Check if the Sink is open. + * + * @return true if the Sink is open, false otherwise. + */ + virtual bool + isOpen ( void ) const throw () = 0; + + /** + * Check if the Sink is ready to accept data. + * Blocks until the specified time for data to be available. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the Sink is ready to accept data, false otherwise. + * @exception Exception + */ + virtual bool + canWrite ( unsigned int sec, + unsigned int usec ) throw ( Exception ) = 0; + + /** + * Write data to the Sink. + * + * @param buf the data to write. + * @param len number of bytes to write from buf. + * @return the number of bytes written (may be less than len). + * @exception Exception + */ + virtual unsigned int + write ( const void * buf, + unsigned int len ) throw ( Exception ) = 0; + + /** + * Flush all data that was written to the Sink to the underlying + * construct. + * + * @exception Exception + */ + virtual void + flush ( void ) throw ( Exception ) = 0; + + /** + * Cut what the sink has been doing so far, and start anew. + * This usually means separating the data sent to the sink up + * until now, and start saving a new chunk of data. + */ + virtual void + cut ( void ) throw () = 0; + + /** + * Close the Sink. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ) = 0; +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* SINK_H */ + diff --git a/darkice/tags/darkice-1_3/src/SolarisDspSource.cpp b/darkice/tags/darkice-1_3/src/SolarisDspSource.cpp new file mode 100644 index 0000000..de3d1c0 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/SolarisDspSource.cpp @@ -0,0 +1,277 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : SolarisDspSource.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#include "SolarisDspSource.h" + +#ifdef SUPPORT_SOLARIS_DSP +// only compile this code if there is support for it + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_UNISTD_H +#include +#else +#error need unistd.h +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#else +#error need sys/types.h +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#else +#error need sys/stat.h +#endif + +#ifdef HAVE_FCNTL_H +#include +#else +#error need fcntl.h +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#else +#error need sys/time.h +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include +#else +#error need sys/ioctl.h +#endif + +#ifdef HAVE_SIGNAL_H +#include +#else +#error need signal.h +#endif + +#if defined( HAVE_SYS_AUDIO_H ) +#include +#elif defined( HAVE_SYS_AUDIOIO_H ) +#include +#else +#error need sys/audio.h or sys/audioio.h +#endif + + +#include "Util.h" +#include "Exception.h" +#include "SolarisDspSource.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +SolarisDspSource :: init ( const char * name ) throw ( Exception ) +{ + fileName = Util::strDup( name); + fileDescriptor = 0; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +SolarisDspSource :: strip ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + delete[] fileName; +} + +#include + +/*------------------------------------------------------------------------------ + * Open the audio source + *----------------------------------------------------------------------------*/ +bool +SolarisDspSource :: open ( void ) throw ( Exception ) +{ + audio_info_t audioInfo; + + if ( isOpen() ) { + return false; + } + + if ( (fileDescriptor = ::open( fileName, O_RDONLY)) == -1 ) { + fileDescriptor = 0; + return false; + } + + AUDIO_INITINFO( &audioInfo); + audioInfo.record.sample_rate = getSampleRate(); + audioInfo.record.channels = getChannel(); + audioInfo.record.precision = getBitsPerSample(); + audioInfo.record.encoding = AUDIO_ENCODING_LINEAR; + // for stupid OpenBSD we need to add the following, as it masks + // read/write calls when using -pthread + audioInfo.record.pause = 0; + + if ( ioctl( fileDescriptor, AUDIO_SETINFO, &audioInfo) == -1 ) { + + close(); + throw Exception( __FILE__, __LINE__, "ioctl error"); + } + + if ( audioInfo.record.channels != getChannel() ) { + close(); + throw Exception( __FILE__, __LINE__, + "can't set channels", audioInfo.record.channels); + } + + if ( audioInfo.record.precision != getBitsPerSample() ) { + close(); + throw Exception( __FILE__, __LINE__, + "can't set bits per sample", + audioInfo.record.precision); + } + + if ( audioInfo.record.sample_rate != getSampleRate() ) { + reportEvent( 2, "sound card recording sample rate set to ", + audioInfo.record.sample_rate, + " while trying to set it to ", getSampleRate()); + reportEvent( 2, "this is probably not a problem, but a slight " + "drift in the sound card driver"); + } + + + return true; +} + + +/*------------------------------------------------------------------------------ + * Check whether read() would return anything + *----------------------------------------------------------------------------*/ +bool +SolarisDspSource :: canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ) +{ + fd_set fdset; + struct timespec timespec; + sigset_t sigset; + int ret; + + if ( !isOpen() ) { + return false; + } + + FD_ZERO( &fdset); + FD_SET( fileDescriptor, &fdset); + + timespec.tv_sec = sec; + timespec.tv_nsec = usec * 1000L; + + // mask out SIGUSR1, as we're expecting that signal for other reasons + sigemptyset(&sigset); + sigaddset(&sigset, SIGUSR1); + + ret = pselect( fileDescriptor + 1, &fdset, NULL, NULL, ×pec, &sigset); + + if ( ret == -1 ) { + throw Exception( __FILE__, __LINE__, "select error"); + } + + return ret > 0; +} + + +/*------------------------------------------------------------------------------ + * Read from the audio source + *----------------------------------------------------------------------------*/ +unsigned int +SolarisDspSource :: read ( void * buf, + unsigned int len ) throw ( Exception ) +{ + ssize_t ret; + + if ( !isOpen() ) { + return 0; + } + + ret = ::read( fileDescriptor, buf, len); + + if ( ret == -1 ) { + throw Exception( __FILE__, __LINE__, "read error"); + } + + return ret; +} + + +/*------------------------------------------------------------------------------ + * Close the audio source + *----------------------------------------------------------------------------*/ +void +SolarisDspSource :: close ( void ) throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + ::close( fileDescriptor); + fileDescriptor = 0; +} + +#endif // SUPPORT_SOLARIS_DSP + diff --git a/darkice/tags/darkice-1_3/src/SolarisDspSource.h b/darkice/tags/darkice-1_3/src/SolarisDspSource.h new file mode 100644 index 0000000..b795eff --- /dev/null +++ b/darkice/tags/darkice-1_3/src/SolarisDspSource.h @@ -0,0 +1,257 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : SolarisDspSource.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef SOLARIS_DSP_SOURCE_H +#define SOLARIS_DSP_SOURCE_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Reporter.h" +#include "AudioSource.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * An audio input based on Solaris /dev/audio devices + * + * @author $Author$ + * @version $Revision$ + */ +class SolarisDspSource : public AudioSource, public virtual Reporter +{ + private: + + /** + * The file name of the OSS DSP device (e.g. /dev/audio) + */ + char * fileName; + + /** + * The low-level file descriptor of the Solaris DSP device. + */ + int fileDescriptor; + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + SolarisDspSource ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Initialize the object + * + * @param name the file name of the Solaris DSP device. + * @exception Exception + */ + void + init ( const char * name ) throw ( Exception ); + + /** + * De-iitialize the object + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + public: + + /** + * Constructor. + * + * @param name the file name of the Solaris DSP device + * (e.g. /dev/audio or /dev/sound/0) + * @param sampleRate samples per second (e.g. 44100 for 44.1kHz). + * @param bitsPerSample bits per sample (e.g. 16 bits). + * @param channel number of channels of the audio source + * (e.g. 1 for mono, 2 for stereo, etc.). + * @exception Exception + */ + inline + SolarisDspSource ( const char * name, + int sampleRate = 44100, + int bitsPerSample = 16, + int channel = 2 ) + throw ( Exception ) + + : AudioSource( sampleRate, bitsPerSample, channel) + { + init( name); + } + + /** + * Copy Constructor. + * + * @param sds the object to copy. + * @exception Exception + */ + inline + SolarisDspSource ( const SolarisDspSource & sds ) + throw ( Exception ) + : AudioSource( sds ) + { + init( sds.fileName); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~SolarisDspSource ( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param ds the object to assign to this one. + * @return a reference to this object. + * @exception Exception + */ + inline virtual SolarisDspSource & + operator= ( const SolarisDspSource & ds ) throw ( Exception ) + { + if ( this != &ds ) { + strip(); + AudioSource::operator=( ds); + init( ds.fileName); + } + return *this; + } + + /** + * Tell if the data from this source comes in big or little endian. + * + * @return true + */ + virtual inline bool + isBigEndian ( void ) const throw () + { +#ifdef WORDS_BIGENDIAN + return true; +#else + return false; +#endif + } + + /** + * Open the SolarisDspSource. + * This does not put the Solaris DSP device into recording mode. + * To start getting samples, call either canRead() or read(). + * + * @return true if opening was successful, false otherwise + * @exception Exception + * + * @see #canRead + * @see #read + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the SolarisDspSource is open. + * + * @return true if the SolarisDspSource is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return fileDescriptor != 0; + } + + /** + * Check if the SolarisDspSource can be read from. + * Blocks until the specified time for data to be available. + * Puts the Solaris DSP device into recording mode. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the SolarisDspSource is ready to be read from, + * false otherwise. + * @exception Exception + */ + virtual bool + canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ); + + /** + * Read from the SolarisDspSource. + * Puts the Solaris DSP device into recording mode. + * + * @param buf the buffer to read into. + * @param len the number of bytes to read into buf + * @return the number of bytes read (may be less than len). + * @exception Exception + */ + virtual unsigned int + read ( void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Close the SolarisDspSource. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* SOLARIS_DSP_SOURCE_H */ + diff --git a/darkice/tags/darkice-1_3/src/Source.h b/darkice/tags/darkice-1_3/src/Source.h new file mode 100644 index 0000000..95db07d --- /dev/null +++ b/darkice/tags/darkice-1_3/src/Source.h @@ -0,0 +1,171 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : Source.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef SOURCE_H +#define SOURCE_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Referable.h" +#include "Exception.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A general data source + * + * @author $Author$ + * @version $Revision$ + */ +class Source : public virtual Referable +{ + private: + + protected: + + /** + * Default Constructor. + * + * @exception Exception + */ + inline + Source ( void ) throw ( Exception ) + { + } + + /** + * Copy Constructor. + * + * @param source the object to copy. + * @exception Exception + */ + inline + Source ( const Source & source ) throw ( Exception ) + { + } + + /** + * Assignment operator. + * + * @param source the object to assign to this one. + * @return a reference to this object. + * @exception Exception + */ + inline virtual Source & + operator= ( const Source & source ) throw ( Exception ) + { + return *this; + } + + + public: + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~Source ( void ) throw ( Exception ) + { + } + + /** + * Open the Source. + * + * @return true if opening was successful, false otherwise + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ) = 0; + + /** + * Check if the Source is open. + * + * @return true if the Source is open, false otherwise. + */ + virtual bool + isOpen ( void ) const throw () = 0; + + /** + * Check if the Source can be read from. + * Blocks until the specified time for data to be available. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the Source is ready to be read from, + * false otherwise. + * @exception Exception + */ + virtual bool + canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ) = 0; + + /** + * Read from the Source. + * + * @param buf the buffer to read into. + * @param len the number of bytes to read into buf + * @return the number of bytes read (may be less than len). + * @exception Exception + */ + virtual unsigned int + read ( void * buf, + unsigned int len ) throw ( Exception ) = 0; + + /** + * Close the Source. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ) = 0; +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* SOURCE_H */ + diff --git a/darkice/tags/darkice-1_3/src/TcpSocket.cpp b/darkice/tags/darkice-1_3/src/TcpSocket.cpp new file mode 100644 index 0000000..2b8e07c --- /dev/null +++ b/darkice/tags/darkice-1_3/src/TcpSocket.cpp @@ -0,0 +1,418 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : TcpSocket.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#else +#error need sys/types.h +#endif + +#ifdef HAVE_ERRNO_H +#include +#else +#error need errno.h +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#else +#error need sys/socket.h +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#else +#error need netinet/in.h +#endif + +#ifdef HAVE_NETDB_H +#include +#else +#error need netdb.h +#endif + +#ifdef HAVE_UNISTD_H +#include +#else +#error need unistd.h +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#else +#error need sys/time.h +#endif + +#ifdef HAVE_SIGNAL_H +#include +#else +#error need signal.h +#endif + + +#include "Util.h" +#include "Exception.h" +#include "TcpSocket.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +TcpSocket :: init ( const char * host, + unsigned short port ) throw ( Exception ) +{ + this->host = Util::strDup( host); + this->port = port; + this->sockfd = 0; +} + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +TcpSocket :: strip ( void) throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + delete[] host; +} + + +/*------------------------------------------------------------------------------ + * Copy Constructor + *----------------------------------------------------------------------------*/ +TcpSocket :: TcpSocket ( const TcpSocket & ss ) throw ( Exception ) + : Source( ss), Sink( ss ) +{ + int fd; + + init( ss.host, ss.port); + + if ( (fd = ss.sockfd ? dup( ss.sockfd) : 0) == -1 ) { + strip(); + throw Exception( __FILE__, __LINE__, "dup failure"); + } + + sockfd = fd; +} + + +/*------------------------------------------------------------------------------ + * Assignment operator + *----------------------------------------------------------------------------*/ +TcpSocket & +TcpSocket :: operator= ( const TcpSocket & ss ) throw ( Exception ) +{ + if ( this != &ss ) { + int fd; + + /* first strip */ + strip(); + + + /* then build up */ + Sink::operator=( ss ); + Source::operator=( ss ); + + init( ss.host, ss.port); + + if ( (fd = ss.sockfd ? dup( ss.sockfd) : 0) == -1 ) { + strip(); + throw Exception( __FILE__, __LINE__, "dup failure"); + } + + sockfd = fd; + } + + return *this; +} + + +/*------------------------------------------------------------------------------ + * Open the file + *----------------------------------------------------------------------------*/ +bool +TcpSocket :: open ( void ) throw ( Exception ) +{ + int optval; + socklen_t optlen; +#ifdef HAVE_ADDRINFO + struct addrinfo hints + struct addrinfo * ptr; + struct sockaddr_storage addr; + char portstr[6]; +#else + struct sockaddr_in addr; + struct hostent * pHostEntry; +#endif + + if ( isOpen() ) { + return false; + } + +#ifdef HAVE_ADDRINFO + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_ANY; + snprintf(portstr, sizeof(portstr), "%d", port); + + if (getaddrinfo(host , portstr, &hints, &ptr)) { + sockfd = 0; + throw Exception( __FILE__, __LINE__, "getaddrinfo error", errno); + } + memcpy ( addr, ptr->ai_addr, ptr->ai_addrlen); + freeaddrinfo(ptr); +#else + if ( !(pHostEntry = gethostbyname( host)) ) { + sockfd = 0; + throw Exception( __FILE__, __LINE__, "gethostbyname error", errno); + } + + memset( &addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = *((long*) pHostEntry->h_addr_list[0]); +#endif + + if ( (sockfd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) { + sockfd = 0; + throw Exception( __FILE__, __LINE__, "socket error", errno); + } + + // set TCP keep-alive + optval = 1; + optlen = sizeof(optval); + if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) == -1) { + reportEvent(5, "can't set TCP socket keep-alive mode", errno); + } + + // connect + if ( connect( sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1 ) { + ::close( sockfd); + sockfd = 0; + throw Exception( __FILE__, __LINE__, "connect error", errno); + } + + return true; +} + + +/*------------------------------------------------------------------------------ + * Check whether read() would return anything + *----------------------------------------------------------------------------*/ +bool +TcpSocket :: canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ) +{ + fd_set fdset; + struct timespec timespec; + sigset_t sigset; + int ret; + + if ( !isOpen() ) { + return false; + } + + FD_ZERO( &fdset); + FD_SET( sockfd, &fdset); + + timespec.tv_sec = sec; + timespec.tv_nsec = usec * 1000L; + + // mask out SIGUSR1, as we're expecting that signal for other reasons + sigemptyset(&sigset); + sigaddset(&sigset, SIGUSR1); + + ret = pselect( sockfd + 1, &fdset, NULL, NULL, ×pec, &sigset); + + if ( ret == -1 ) { + ::close( sockfd); + sockfd = 0; + throw Exception( __FILE__, __LINE__, "select error"); + } + + return ret > 0; +} + + +/*------------------------------------------------------------------------------ + * Read from the socket + *----------------------------------------------------------------------------*/ +unsigned int +TcpSocket :: read ( void * buf, + unsigned int len ) throw ( Exception ) +{ + int ret; + + if ( !isOpen() ) { + return 0; + } + + ret = recv( sockfd, buf, len, 0); + + if ( ret == -1 ) { + switch (errno) { + case ECONNRESET: + // re-open the socket if it has been reset by the peer + close(); + Util::sleep(1L, 0L); + open(); + break; + + default: + ::close( sockfd); + sockfd = 0; + throw Exception( __FILE__, __LINE__, "recv error", errno); + } + } + + return ret; +} + + +/*------------------------------------------------------------------------------ + * Check whether write() would send anything + *----------------------------------------------------------------------------*/ +bool +TcpSocket :: canWrite ( unsigned int sec, + unsigned int usec ) throw ( Exception ) +{ + fd_set fdset; + struct timespec timespec; + sigset_t sigset; + int ret; + + if ( !isOpen() ) { + return false; + } + + FD_ZERO( &fdset); + FD_SET( sockfd, &fdset); + + timespec.tv_sec = sec; + timespec.tv_nsec = usec * 1000L; + + // mask out SIGUSR1, as we're expecting that signal for other reasons + sigemptyset(&sigset); + sigaddset(&sigset, SIGUSR1); + + ret = pselect( sockfd + 1, NULL, &fdset, NULL, ×pec, &sigset); + + if ( ret == -1 ) { + ::close( sockfd); + sockfd = 0; + reportEvent(4,"TcpSocket :: canWrite, connection lost", errno); + } + + return ret > 0; +} + + +/*------------------------------------------------------------------------------ + * Write to the socket + *----------------------------------------------------------------------------*/ +unsigned int +TcpSocket :: write ( const void * buf, + unsigned int len ) throw ( Exception ) +{ + int ret; + + if ( !isOpen() ) { + return 0; + } + +#ifdef HAVE_MSG_NOSIGNAL + ret = send( sockfd, buf, len, MSG_NOSIGNAL); +#else + ret = send( sockfd, buf, len, 0); +#endif + + if ( ret == -1 ) { + if ( errno == EAGAIN ) { + ret = 0; + } else { + ::close( sockfd); + sockfd = 0; + reportEvent(4,"TcpSocket :: write, send error", errno); + throw Exception( __FILE__, __LINE__, "send error", errno); + } + } + + return ret; +} + + +/*------------------------------------------------------------------------------ + * Close the socket + *----------------------------------------------------------------------------*/ +void +TcpSocket :: close ( void ) throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + flush(); + ::close( sockfd); + sockfd = 0; +} + + diff --git a/darkice/tags/darkice-1_3/src/TcpSocket.h b/darkice/tags/darkice-1_3/src/TcpSocket.h new file mode 100644 index 0000000..4a43971 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/TcpSocket.h @@ -0,0 +1,292 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : TcpSocket.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef TCP_SOCKET_H +#define TCP_SOCKET_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Source.h" +#include "Sink.h" +#include "Reporter.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A TCP network socket + * + * @author $Author$ + * @version $Revision$ + */ +class TcpSocket : public Source, public Sink, public virtual Reporter +{ + private: + + /** + * Name of the host this socket connects to. + */ + char * host; + + /** + * Port to connect to. + */ + unsigned short port; + + /** + * Low-level socket descriptor. + */ + int sockfd; + + /** + * Initialize the object. + * + * @param host name of the host this socket connects to. + * @param port port to connect to. + * @exception Exception + */ + void + init ( const char * host, + unsigned short port ) throw ( Exception ); + + /** + * De-initialize the object. + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + TcpSocket ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + + public: + + /** + * Constructor. + * + * @param host name of the host this socket connects to. + * @param port port to connect to. + * @exception Exception + */ + inline + TcpSocket( const char * host, + unsigned short port ) throw ( Exception ) + { + init( host, port); + } + + /** + * Copy constructor. + * + * @param ss the TcpSocket to copy. + * @exception Exception + */ + TcpSocket( const TcpSocket & ss ) throw ( Exception ); + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~TcpSocket( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param ss the TcpSocket to assign this to. + * @return a reference to this TcpSocket. + * @exception Exception + */ + inline virtual TcpSocket & + operator= ( const TcpSocket & ss ) throw ( Exception ); + + /** + * Get the host this socket connects to. + * + * @return the host this socket connects to. + */ + inline const char * + getHost ( void ) const throw () + { + return host; + } + + /** + * Get the port this socket connects to. + * + * @return the port this socket connects to. + */ + inline unsigned int + getPort ( void ) const throw () + { + return port; + } + + /** + * Open the TcpSocket. + * + * @return true if opening was successfull, false otherwise. + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the TcpSocket is open. + * + * @return true if the TcpSocket is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return sockfd != 0; + } + + /** + * Check if the TcpScoket can be read from. + * Blocks until the specified time for data to be available. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the TcpSocket is ready to be read from, + * false otherwise. + * @exception Exception + */ + virtual bool + canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ); + + /** + * Read from the TcpSocket. + * + * @param buf the buffer to read into. + * @param len the number of bytes to read into buf + * @return the number of bytes read (may be less than len). + * @exception Exception + */ + virtual unsigned int + read ( void * buf, + unsigned int len ) throw ( Exception ); + + + /** + * Check if the TcpSocket is ready to accept data. + * Blocks until the specified time for data to be available. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the TcpSocket is ready to accept data, + * false otherwise. + * @exception Exception + */ + virtual bool + canWrite ( unsigned int sec, + unsigned int usec ) throw ( Exception ); + + /** + * Write data to the TcpSocket. + * + * @param buf the data to write. + * @param len number of bytes to write from buf. + * @return the number of bytes written (may be less than len). + * @exception Exception + */ + virtual unsigned int + write ( const void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Flush all data that was written to the TcpSocket to the underlying + * connection. + * + * @exception Exception + */ + inline virtual void + flush ( void ) throw ( Exception ) + { + } + + /** + * Cut what the sink has been doing so far, and start anew. + * This usually means separating the data sent to the sink up + * until now, and start saving a new chunk of data. + * + * For TcpSocket, this is a no-op. + */ + inline virtual void + cut ( void ) throw () + { + } + + /** + * Close the TcpSocket. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* TCP_SOCKET_H */ + diff --git a/darkice/tags/darkice-1_3/src/TwoLameLibEncoder.cpp b/darkice/tags/darkice-1_3/src/TwoLameLibEncoder.cpp new file mode 100644 index 0000000..a5ba5dc --- /dev/null +++ b/darkice/tags/darkice-1_3/src/TwoLameLibEncoder.cpp @@ -0,0 +1,301 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : TwoLameLibEncoder.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// compile the whole file only if TwoLame support configured in +#ifdef HAVE_TWOLAME_LIB + + + +#include "Exception.h" +#include "Util.h" +#include "TwoLameLibEncoder.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + + + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +TwoLameLibEncoder :: init ( void ) throw ( Exception ) +{ + this->twolame_opts = NULL; + + if ( getInBitsPerSample() != 16 ) { + throw Exception( __FILE__, __LINE__, + "specified bits per sample not supported", + getInBitsPerSample() ); + } + + if ( getInChannel() != 1 && getInChannel() != 2 ) { + throw Exception( __FILE__, __LINE__, + "unsupported number of input channels for the encoder", + getInChannel() ); + } + if ( getOutChannel() != 1 && getOutChannel() != 2 ) { + throw Exception( __FILE__, __LINE__, + "unsupported number of output channels for the encoder", + getOutChannel() ); + } + if ( getInChannel() < getOutChannel() ) { + throw Exception( __FILE__, __LINE__, + "output channels greater then input channels", + getOutChannel() ); + } +} + + +/*------------------------------------------------------------------------------ + * Open an encoding session + *----------------------------------------------------------------------------*/ +bool +TwoLameLibEncoder :: open ( void ) + throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + // open the underlying sink + if ( !getSink()->open() ) { + throw Exception( __FILE__, __LINE__, + "TwoLAME lib opening underlying sink error"); + } + + twolame_opts = ::twolame_init(); + + // ugly twolame returns -1 in a pointer on allocation errors + if ( !twolame_opts ) { + throw Exception( __FILE__, __LINE__, + "TwoLAME lib init error", + (long int) twolame_opts); + } + + if ( 0 > twolame_set_num_channels( twolame_opts, getInChannel()) ) { + throw Exception( __FILE__, __LINE__, + "TwoLAME lib setting channels error", + getInChannel() ); + } + + if ( 0 > twolame_set_mode( twolame_opts, + getOutChannel() == 1 ? TWOLAME_MONO : TWOLAME_JOINT_STEREO) ) { + throw Exception( __FILE__, __LINE__, + "TwoLAME lib setting mode error", + TWOLAME_JOINT_STEREO ); + } + + if ( 0 > twolame_set_in_samplerate( twolame_opts, getInSampleRate()) ) { + throw Exception( __FILE__, __LINE__, + "TwoLAME lib setting input sample rate error", + getInSampleRate() ); + } + + if ( 0 > twolame_set_out_samplerate( twolame_opts, getOutSampleRate()) ) { + throw Exception( __FILE__, __LINE__, + "TwoLAME lib setting output sample rate error", + getOutSampleRate() ); + } + + switch ( getOutBitrateMode() ) { + + case cbr: { + + if ( 0 > twolame_set_brate( twolame_opts, getOutBitrate()) ) { + throw Exception( __FILE__, __LINE__, + "TwoLAME lib setting output bit rate error", + getOutBitrate() ); + } + } break; + + default: { + throw Exception( __FILE__, __LINE__, + "Unsupported bitrate mode." ); + } + } + + + // let TwoLAME init its own params based on our settings + if ( 0 > twolame_init_params( twolame_opts) ) { + throw Exception( __FILE__, __LINE__, + "TwoLAME lib initializing params error" ); + } + + // Information about TwoLame's setup + if (getReportVerbosity() >= 3) { + twolame_print_config( twolame_opts); + } + + return true; +} + + +/*------------------------------------------------------------------------------ + * Write data to the encoder + *----------------------------------------------------------------------------*/ +unsigned int +TwoLameLibEncoder :: write ( const void * buf, + unsigned int len ) throw ( Exception ) +{ + if ( !isOpen() || len == 0 ) { + return 0; + } + + unsigned int bitsPerSample = getInBitsPerSample(); + unsigned int inChannels = getInChannel(); + + unsigned int sampleSize = (bitsPerSample / 8) * inChannels; + unsigned char * b = (unsigned char*) buf; + unsigned int processed = len - (len % sampleSize); + unsigned int nSamples = processed / sampleSize; + short int * leftBuffer = new short int[nSamples]; + short int * rightBuffer = new short int[nSamples]; + + if ( bitsPerSample == 8 ) { + Util::conv8( b, processed, leftBuffer, rightBuffer, inChannels); + } else if ( bitsPerSample == 16 ) { + Util::conv16( b, + processed, + leftBuffer, + rightBuffer, + inChannels, + isInBigEndian()); + } else { + delete[] leftBuffer; + delete[] rightBuffer; + throw Exception( __FILE__, __LINE__, + "unsupported number of bits per sample for the encoder", + bitsPerSample ); + } + + // data chunk size estimate according to TwoLAME documentation + // NOTE: mp2Size is calculated based on the number of input channels + // which may be bigger than need, as output channels can be less + unsigned int mp2Size = (unsigned int) (1.25 * nSamples + 7200); + unsigned char * mp2Buf = new unsigned char[mp2Size]; + int ret; + + ret = twolame_encode_buffer( twolame_opts, + leftBuffer, + inChannels == 2 ? rightBuffer : leftBuffer, + nSamples, + mp2Buf, + mp2Size ); + + delete[] leftBuffer; + delete[] rightBuffer; + + if ( ret < 0 ) { + reportEvent( 3, "TwoLAME encoding error", ret); + delete[] mp2Buf; + return 0; + } + + unsigned int written = getSink()->write( mp2Buf, ret); + delete[] mp2Buf; + // just let go data that could not be written + if ( written < (unsigned int) ret ) { + reportEvent( 2, + "couldn't write all from encoder to underlying sink", + ret - written); + } + + return processed; +} + + +/*------------------------------------------------------------------------------ + * Flush the data from the encoder + *----------------------------------------------------------------------------*/ +void +TwoLameLibEncoder :: flush ( void ) + throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + // data chunk size estimate according to TwoLAME documentation + unsigned int mp2Size = 7200; + unsigned char * mp2Buf = new unsigned char[mp2Size]; + int ret; + + ret = twolame_encode_flush( twolame_opts, mp2Buf, mp2Size ); + + unsigned int written = getSink()->write( mp2Buf, ret); + delete[] mp2Buf; + + // just let go data that could not be written + if ( written < (unsigned int) ret ) { + reportEvent( 2, + "couldn't write all from encoder to underlying sink", + ret - written); + } + + getSink()->flush(); +} + + +/*------------------------------------------------------------------------------ + * Close the encoding session + *----------------------------------------------------------------------------*/ +void +TwoLameLibEncoder :: close ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + flush(); + twolame_close( &twolame_opts ); + getSink()->close(); + } +} + + +#endif // HAVE_TWOLAME_LIB + diff --git a/darkice/tags/darkice-1_3/src/TwoLameLibEncoder.h b/darkice/tags/darkice-1_3/src/TwoLameLibEncoder.h new file mode 100644 index 0000000..949c7bc --- /dev/null +++ b/darkice/tags/darkice-1_3/src/TwoLameLibEncoder.h @@ -0,0 +1,367 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : TwoLameLibEncoder.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef TWOLAME_LIB_ENCODER_H +#define TWOLAME_LIB_ENCODER_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_TWOLAME_LIB +#include +#else +#error configure with twolame +#endif + + +#include "Ref.h" +#include "Exception.h" +#include "Reporter.h" +#include "AudioEncoder.h" +#include "Sink.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A class representing the TwoLame encoder linked as a shared object or as + * a static library. + * + * @author $Author$ + * @version $Revision$ + */ +class TwoLameLibEncoder : public AudioEncoder, public virtual Reporter +{ + private: + + /** + * TwoLame library global flags + */ + twolame_options * twolame_opts; + + /** + * Initialize the object. + * + * @param sink the sink to send mp2 output to + * @exception Exception + */ + void + init ( void ) throw ( Exception ); + + /** + * De-initialize the object. + * + * @exception Exception + */ + inline void + strip ( void ) throw ( Exception ) + { + } + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + TwoLameLibEncoder ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + + public: + + /** + * Constructor. + * + * @param sink the sink to send mp2 output to + * @param inSampleRate sample rate of the input. + * @param inBitsPerSample number of bits per sample of the input. + * @param inChannel number of channels of the input. + * @param inBigEndian shows if the input is big or little endian + * @param outBitrateMode the bit rate mode of the output. + * @param outBitrate bit rate of the output (kbits/sec). + * @param outSampleRate sample rate of the output. + * If 0, inSampleRate is used. + * @param outChannel number of channels of the output. + * If 0, inChannel is used. + * @exception Exception + */ + inline + TwoLameLibEncoder ( Sink * sink, + unsigned int inSampleRate, + unsigned int inBitsPerSample, + unsigned int inChannel, + bool inBigEndian, + BitrateMode outBitrateMode, + unsigned int outBitrate, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0 ) + throw ( Exception ) + + : AudioEncoder ( sink, + inSampleRate, + inBitsPerSample, + inChannel, + inBigEndian, + outBitrateMode, + outBitrate, + 0.0f, // outQuality + outSampleRate, + outChannel ) + { + init(); + } + + /** + * Constructor. + * + * @param sink the sink to send mp2 output to + * @param as get input sample rate, bits per sample and channels + * from this AudioSource. + * @param outBitrateMode the bit rate mode of the output. + * @param outBitrate bit rate of the output (kbits/sec). + * @param outSampleRate sample rate of the output. + * If 0, input sample rate is used. + * @param outChannel number of channels of the output. + * If 0, input channel is used. + * @exception Exception + */ + inline + TwoLameLibEncoder ( Sink * sink, + const AudioSource * as, + BitrateMode outBitrateMode, + unsigned int outBitrate, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0 ) + throw ( Exception ) + + : AudioEncoder ( sink, + as, + outBitrateMode, + outBitrate, + 0.0f, // outQuality + outSampleRate, + outChannel ) + { + init(); + } + + /** + * Copy constructor. + * + * @param encoder the TwoLameLibEncoder to copy. + */ + inline + TwoLameLibEncoder ( const TwoLameLibEncoder & encoder ) + throw ( Exception ) + : AudioEncoder( encoder ) + { + init(); + } + + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~TwoLameLibEncoder ( void ) throw ( Exception ) + { + if ( isOpen() ) { + close(); + } + strip(); + } + + /** + * Assignment operator. + * + * @param encoder the TwoLameLibEncoder to assign this to. + * @return a reference to this TwoLameLibEncoder. + * @exception Exception + */ + inline virtual TwoLameLibEncoder & + operator= ( const TwoLameLibEncoder & encoder ) throw ( Exception ) + { + if ( this != &encoder ) { + strip(); + AudioEncoder::operator=( encoder); + init(); + } + + return *this; + } + + /** + * Get the version string of the underlying lame library. + * + * @return the version string of the underlying lame library. + */ + inline const char * + getLameVersion( void ) + { + return get_twolame_version(); + } + + /** + * Check whether encoding is in progress. + * + * @return true if encoding is in progress, false otherwise. + */ + inline virtual bool + isRunning ( void ) const throw () + { + return isOpen(); + } + + /** + * Start encoding. This function returns as soon as possible, + * with encoding started in the background. + * + * @return true if encoding has started, false otherwise. + * @exception Exception + */ + inline virtual bool + start ( void ) throw ( Exception ) + { + return open(); + } + + /** + * Stop encoding. Stops the encoding running in the background. + * + * @exception Exception + */ + inline virtual void + stop ( void ) throw ( Exception ) + { + return close(); + } + + /** + * Open an encoding session. + * + * @return true if opening was successfull, false otherwise. + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the encoding session is open. + * + * @return true if the encoding session is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return twolame_opts != 0; + } + + /** + * Check if the encoder is ready to accept data. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the encoder is ready to accept data, + * false otherwise. + * @exception Exception + */ + inline virtual bool + canWrite ( unsigned int sec, + unsigned int usec ) throw ( Exception ) + { + if ( !isOpen() ) { + return false; + } + + return true; + } + + /** + * Write data to the encoder. + * Buf is expected to be a sequence of big-endian 16 bit values, + * with left and right channels interleaved. Len is the number of + * bytes, must be a multiple of 4. + * + * @param buf the data to write. + * @param len number of bytes to write from buf. + * @return the number of bytes written (may be less than len). + * @exception Exception + */ + virtual unsigned int + write ( const void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Flush all data that was written to the encoder to the underlying + * connection. + * + * @exception Exception + */ + virtual void + flush ( void ) throw ( Exception ); + + /** + * Close the encoding session. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + +#endif /* TWOLAME_LIB_ENCODER_H */ + diff --git a/darkice/tags/darkice-1_3/src/Util.cpp b/darkice/tags/darkice-1_3/src/Util.cpp new file mode 100644 index 0000000..b664137 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/Util.cpp @@ -0,0 +1,540 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : Util.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ERRNO_H +#include +#else +#error need errno.h +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + +#ifdef HAVE_STDLIB_H +#include +#else +#error need stdlib.h +#endif + +#ifdef HAVE_LIMITS_H +#include +#else +#error need limits.h +#endif + +#ifdef HAVE_MATH_H +#include +#else +#error need math.h +#endif + +#ifdef HAVE_TIME_H +#include +#else +#error need time.h +#endif + +#ifdef HAVE_UNISTD_H +#include +#else +#error need unistd.h +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#else +#error need sys/time.h +#endif + +#ifdef HAVE_SIGNAL_H +#include +#else +#error need signal.h +#endif + +#ifdef HAVE_ERRNO_H +#include +#endif + +#include "Util.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +char +Util :: base64Table[] = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', + 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', + 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' +}; + + +/*------------------------------------------------------------------------------ + * Calculate the length of a zero-terminated C string, + * w/o the zero-termination + *----------------------------------------------------------------------------*/ +unsigned int +Util :: strLen( const char * str ) throw ( Exception ) +{ + size_t len; + + if ( !str ) { + throw Exception( __FILE__, __LINE__, "no str"); + } + + len = strlen( str); + + return len; +} + + +/*------------------------------------------------------------------------------ + * Copy the contents of a string into another + *----------------------------------------------------------------------------*/ +void +Util :: strCpy ( char * dest, + const char * src ) throw ( Exception ) +{ + if ( !dest || !src ) { + throw Exception( __FILE__, __LINE__, "no src or dest"); + } + + strcpy( dest, src); +} + + +/*------------------------------------------------------------------------------ + * Concatenate the contents of a string onto another + *----------------------------------------------------------------------------*/ +void +Util :: strCat ( char * dest, + const char * src ) throw ( Exception ) +{ + if ( !dest || !src ) { + throw Exception( __FILE__, __LINE__, "no src or dest"); + } + + strcat( dest, src); +} + + +/*------------------------------------------------------------------------------ + * Duplicate a string by allocating space with new[] + * The returned string must be freed with delete[] + *----------------------------------------------------------------------------*/ +char * +Util :: strDup( const char * str ) throw ( Exception ) +{ + size_t len; + char * s; + + if ( !str ) { + throw Exception( __FILE__, __LINE__, "no str"); + } + + len = strlen( str) + 1; + s = new char[len]; + memcpy( s, str, len); + + return s; +} + + +/*------------------------------------------------------------------------------ + * Convert a string into base64 encoding. + *----------------------------------------------------------------------------*/ +char * +Util :: base64Encode( const char * str ) throw ( Exception ) +{ + if ( !str ) { + throw Exception( __FILE__, __LINE__, "no str"); + } + + const char * data = str; + size_t len = strlen( data); + char * out = new char[len * 4 / 3 + 4]; + char * result = out; + unsigned chunk; + + while ( len > 0 ) { + chunk = (len > 3) ? 3 : len; + *out++ = base64Table[(*data & 0xfc) >> 2]; + *out++ = base64Table[((*data & 0x03) << 4) | ((*(data+1) & 0xf0) >> 4)]; + switch ( chunk ) { + case 3: + *out++ = base64Table[((*(data+1) & 0x0f) << 2) | + ((*(data+2) & 0xc0) >> 6)]; + *out++ = base64Table[(*(data+2)) & 0x3f]; + break; + case 2: + *out++ = base64Table[((*(data+1) & 0x0f) << 2)]; + *out++ = '='; + break; + case 1: + *out++ = '='; + *out++ = '='; + break; + } + data += chunk; + len -= chunk; + } + *out = 0; + + return result; +} + + +/*------------------------------------------------------------------------------ + * Check whether two strings are equal + *----------------------------------------------------------------------------*/ +bool +Util :: strEq( const char * str1, + const char * str2, + unsigned int len ) throw ( Exception ) +{ + if ( !str1 || !str2 ) { + throw Exception( __FILE__, __LINE__, "no str1 or no str2"); + } + + return len == 0 ? !strcmp( str1, str2) : !strncmp( str1, str2, len); +} + + +/*------------------------------------------------------------------------------ + * Convert a string to a long integer + *----------------------------------------------------------------------------*/ +long int +Util :: strToL( const char *str) throw ( Exception ) +{ + long int val; + char *end; + + if ( NULL == str ) + throw Exception( __FILE__, __LINE__, "null pointer parameter, not string"); + + errno = 0; // set it, strtol() can change it + val = strtol( str, &end, 10); + + if (end == str) + throw Exception( __FILE__, __LINE__, "number conversion error, not a decimal string"); + + if ((LONG_MIN == val || LONG_MAX == val) && ERANGE == errno) + throw Exception( __FILE__, __LINE__, "number conversion error, out of range of type long"); + + return val; +} + + +/*------------------------------------------------------------------------------ + * Convert a string to a double + *----------------------------------------------------------------------------*/ +double +Util :: strToD( const char * str ) throw ( Exception ) +{ + double val; + char * s; + + if ( !str ) { + throw Exception( __FILE__, __LINE__, "no str"); + } + + val = strtod( str, &s); + if ( s == str || errno == ERANGE ) { + throw Exception( __FILE__, __LINE__, "number conversion error"); + } + + return val; +} + + +/*------------------------------------------------------------------------------ + * add current date to a file name, before the file extension (if any) + *----------------------------------------------------------------------------*/ +char * +Util :: fileAddDate ( const char * str, + const char * format ) throw ( Exception ) +{ + unsigned int size; + const char * last; + char * s; + char * strdate; + time_t now; + + if ( !str ) { + throw Exception( __FILE__, __LINE__, "no str"); + } + + strdate = new char[128]; + now = time(NULL); + strftime( strdate, 128, format, localtime (&now)); + + // search for the part before the extension of the file name + if ( !(last = strrchr( str, '.')) ) { + last = (char *) str + strlen( str); + } + + size = strlen( str) + strlen( strdate) + 1; + s = new char [size]; + + memcpy( s, str, strlen (str)-strlen(last)); + memcpy( s + strlen(str) - strlen(last), strdate, strlen (strdate)); + memcpy( s + strlen(str) - strlen(last) + strlen(strdate), + last, + strlen(last)); + s[size-1] = '\0'; + + delete[] strdate; + return s; +} + +/*------------------------------------------------------------------------------ + * Convert an unsigned char buffer holding 8 or 16 bit PCM values with + * channels interleaved to a short int buffer, still with channels interleaved + *----------------------------------------------------------------------------*/ +void +Util :: conv ( unsigned int bitsPerSample, + unsigned char * pcmBuffer, + unsigned int lenPcmBuffer, + short int * outBuffer, + bool isBigEndian ) throw ( Exception ) +{ + if ( bitsPerSample == 8 ) { + unsigned int i, j; + + for ( i = 0, j = 0; i < lenPcmBuffer; ) { + outBuffer[j] = pcmBuffer[i++]; + ++j; + } + } else if ( bitsPerSample == 16 ) { + + if ( isBigEndian ) { + unsigned int i, j; + + for ( i = 0, j = 0; i < lenPcmBuffer; ) { + short int value; + + value = pcmBuffer[i++] << 8; + value |= pcmBuffer[i++]; + outBuffer[j] = value; + ++j; + } + } else { + unsigned int i, j; + + for ( i = 0, j = 0; i < lenPcmBuffer; ) { + short int value; + + value = pcmBuffer[i++]; + value |= pcmBuffer[i++] << 8; + outBuffer[j] = value; + ++j; + } + } + } else { + throw Exception( __FILE__, __LINE__, + "this number of bits per sample not supported", + bitsPerSample); + } +} + + +/*------------------------------------------------------------------------------ + * Convert a short buffer holding PCM values with channels interleaved + * to one or more float buffers, one for each channel + *----------------------------------------------------------------------------*/ +void +Util :: conv ( short int * shortBuffer, + unsigned int lenShortBuffer, + float ** floatBuffers, + unsigned int channels ) throw ( Exception ) +{ + unsigned int i, j; + + for ( i = 0, j = 0; i < lenShortBuffer; ) { + for ( unsigned int c = 0; c < channels; ++c ) { + floatBuffers[c][j] = ((float) shortBuffer[i++]) / 32768.f; + } + ++j; + } +} + + +/*------------------------------------------------------------------------------ + * Convert an unsigned char buffer holding 8 bit PCM values with channels + * interleaved to two short int buffers (one for each channel) + *----------------------------------------------------------------------------*/ +void +Util :: conv8 ( unsigned char * pcmBuffer, + unsigned int lenPcmBuffer, + short int * leftBuffer, + short int * rightBuffer, + unsigned int channels ) throw ( Exception ) +{ + if ( channels == 1 ) { + unsigned int i, j; + + for ( i = 0, j = 0; i < lenPcmBuffer; ) { + unsigned short int value; + + value = pcmBuffer[i++]; + leftBuffer[j] = (short int) value; + ++j; + } + } else if ( channels == 2 ) { + unsigned int i, j; + + for ( i = 0, j = 0; i < lenPcmBuffer; ) { + unsigned short int value; + + value = pcmBuffer[i++]; + leftBuffer[j] = (short int) value; + value = pcmBuffer[i++]; + rightBuffer[j] = (short int) value; + ++j; + } + } else { + throw Exception( __FILE__, __LINE__, + "this number of channels not supported", channels); + } +} + + +/*------------------------------------------------------------------------------ + * Convert an unsigned char buffer holding 16 bit PCM values with channels + * interleaved to two short int buffers (one for each channel) + *----------------------------------------------------------------------------*/ +void +Util :: conv16 ( unsigned char * pcmBuffer, + unsigned int lenPcmBuffer, + short int * leftBuffer, + short int * rightBuffer, + unsigned int channels, + bool isBigEndian ) throw ( Exception ) +{ + if ( isBigEndian ) { + if ( channels == 1 ) { + unsigned int i, j; + + for ( i = 0, j = 0; i < lenPcmBuffer; ) { + unsigned short int value; + + value = pcmBuffer[i++] << 8; + value |= pcmBuffer[i++]; + leftBuffer[j] = (short int) value; + ++j; + } + } else { + unsigned int i, j; + + for ( i = 0, j = 0; i < lenPcmBuffer; ) { + unsigned short int value; + + value = pcmBuffer[i++] << 8; + value |= pcmBuffer[i++]; + leftBuffer[j] = (short int) value; + value = pcmBuffer[i++] << 8; + value |= pcmBuffer[i++]; + rightBuffer[j] = (short int) value; + ++j; + } + } + } else { + if ( channels == 1 ) { + unsigned int i, j; + + for ( i = 0, j = 0; i < lenPcmBuffer; ) { + unsigned short int value; + + value = pcmBuffer[i++]; + value |= pcmBuffer[i++] << 8; + leftBuffer[j] = (short int) value; + ++j; + } + } else { + unsigned int i, j; + + for ( i = 0, j = 0; i < lenPcmBuffer; ) { + unsigned short int value; + + value = pcmBuffer[i++]; + value |= pcmBuffer[i++] << 8; + leftBuffer[j] = (short int) value; + value = pcmBuffer[i++]; + value |= pcmBuffer[i++] << 8; + rightBuffer[j] = (short int) value; + ++j; + } + } + } +} + + +/*------------------------------------------------------------------------------ + * Make a thread sleep for a specified amount of time. + *----------------------------------------------------------------------------*/ +void +Util :: sleep ( long sec, + long nsec) +{ + struct timespec timespec; + sigset_t sigset; + + timespec.tv_sec = sec; + timespec.tv_nsec = nsec; + + // mask out SIGUSR1, as we're expecting that signal for other reasons + sigemptyset(&sigset); + sigaddset(&sigset, SIGUSR1); + + pselect( 0, NULL, NULL, NULL, ×pec, &sigset); +} diff --git a/darkice/tags/darkice-1_3/src/Util.h b/darkice/tags/darkice-1_3/src/Util.h new file mode 100644 index 0000000..5a51aa7 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/Util.h @@ -0,0 +1,330 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : Util.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef UTIL_H +#define UTIL_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#include "Exception.h" + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * Widely used utilities. + * This class can not be instantiated, but contains useful (?) static + * functions. + * + * Typical usage: + * + *
+ *  #include "Util.h"
+ *  
+ *  char  * str = Util::strDup( otherStr);
+ *  
+ * + * @author $Author$ + * @version $Revision$ + */ +class Util +{ + private: + + /** + * Helper table for base64 encoding. + */ + static char base64Table[]; + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + Util ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Copy constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + Util ( const Util & e ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Destructor. Always throws an Exception. + * + * @exception Exception + */ + inline + ~Util ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Assignment operator. Always throws an Exception. + * + * @param u the object to assign to this one. + * @exception Exception + */ + inline Util & + operator= ( const Util & u ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + + + public: + + /** + * Determine a C string's length. + * + * @param str a zero-terminated C string. + * @return length of str + * @exception Exception + */ + static unsigned int + strLen ( const char * str ) throw ( Exception ); + + /** + * Copy a C string into another. + * + * @param dest place for the copy. Storage size must be at least + * Util::strLen(src) + 1 long. + * @param src the string to copy. + * @exception Exception + */ + static void + strCpy ( char * dest, + const char * src ) throw ( Exception ); + + /** + * Concatenate a string to another's end. + * + * @param dest the string to concatenate to. + * Storage size of dest must be at least + * Util::strLen(dest) + Util::strLen(src) + 1 long. + * @param src the string to concatenate. + * @exception Exception + */ + static void + strCat ( char * dest, + const char * src ) throw ( Exception ); + + /** + * Duplicate a string by allocating space with new[]. + * The returned string must be freed with delete[]. + * + * @param str the string to duplicate. + * @exception Exception + */ + static char * + strDup ( const char * str ) throw ( Exception ); + + /** + * Determine whether two string are equal. + * + * @param str1 one of the strings. + * @param str2 the other string. + * @param len check the first most len characters. if 0, check + * the whole string + * @return true if the two strings are equal, false othersize. + * @exception Exception + */ + static bool + strEq ( const char * str1, + const char * str2, + unsigned int len = 0 ) throw ( Exception ); + + /** + * Convert a string to long. + * + * @param str the string to convert. + * @return the value of str as a long int + * @exception Exception + */ + static long int + strToL ( const char * str) throw ( Exception ); + + /** + * Convert a string to double. + * + * @param str the string to convert. + * @return the value of str as a double + * @exception Exception + */ + static double + strToD ( const char * str ) throw ( Exception ); + + /** + * Add current date to a file name, before the file extension (if any) + * + * @param str the string to convert (file name). + * @return the new string with the date appended before + * extension of the file name. the string has to be + * deleted with delete[] after it is not needed + * @exception Exception + */ + static char * + fileAddDate ( const char * str, + const char * format = "[%m-%d-%Y-%H-%M-%S]" ) + throw ( Exception ); + + /** + * Convert a string into base64 encoding. + * base64 is described in RFC 2045, section 6.8 + * The returned string must be freed with delete[]. + * + * @param str the string to convert. + * @return the supplied string in base64 encoding. + * @exception Exception + */ + static char * + base64Encode ( const char * str ) throw ( Exception ); + + /** + * Convert an unsigned char buffer holding 8 or 16 bit PCM values + * with channels interleaved to a short int buffer, still + * with channels interleaved. + * + * @param bitsPerSample the number of bits per sample in the input + * @param pcmBuffer the input buffer + * @param lenPcmBuffer the number of samples total in pcmBuffer + * (e.g. if 2 channel input, this is twice the + * number of sound samples) + * @param outBuffer the output buffer, must be big enough + * @param isBigEndian true if the input is big endian, false otherwise + */ + static void + conv ( unsigned int bitsPerSample, + unsigned char * pcmBuffer, + unsigned int lenPcmBuffer, + short int * outBuffer, + bool isBigEndian = true ) throw ( Exception ); + + + /** + * Convert a short buffer holding PCM values with channels interleaved + * to one or more float buffers, one for each channel + * + * @param shortBuffer the input buffer + * @param lenShortBuffer total length of the input buffer + * @param floatBuffers an array of float buffers, each + * (lenShortBuffer / channels) long + * @param channels number of channels to separate the input to + */ + static void + conv ( short int * shortBuffer, + unsigned int lenShortBuffer, + float ** floatBuffers, + unsigned int channels ) throw ( Exception ); + + /** + * Convert a char buffer holding 8 bit PCM values to a short buffer + * + * @param pcmBuffer buffer holding 8 bit PCM audio values, + * channels are interleaved + * @param lenPcmBuffer length of pcmBuffer + * @param leftBuffer put the left channel here (must be big enough) + * @param rightBuffer put the right channel here (not touched if mono, + * must be big enough) + * @param channels number of channels (1 = mono, 2 = stereo) + */ + static void + conv8 ( unsigned char * pcmBuffer, + unsigned int lenPcmBuffer, + short int * leftBuffer, + short int * rightBuffer, + unsigned int channels ) throw ( Exception ); + + /** + * Convert a char buffer holding 16 bit PCM values to a short buffer + * + * @param pcmBuffer buffer holding 16 bit PCM audio values, + * channels are interleaved + * @param lenPcmBuffer length of pcmBuffer + * @param leftBuffer put the left channel here (must be big enough) + * @param rightBuffer put the right channel here (not touched if mono, + * must be big enough) + * @param channels number of channels (1 = mono, 2 = stereo) + * @param isBigEndian true if input is big endian, false otherwise + */ + static void + conv16 ( unsigned char * pcmBuffer, + unsigned int lenPcmBuffer, + short int * leftBuffer, + short int * rightBuffer, + unsigned int channels, + bool isBigEndian ) throw ( Exception ); + + /** + * Make a thread sleep for specified amount of time. + * Only the thread which this is called in will sleep. + * The SIGUSR1 signal will be blocked during the sleep. + * + * @param sec the number of seconds to sleep. + * @param nsec the number of nano-seconds to sleep. + */ + static void + sleep( long sec, + long nsec); + +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* UTIL_H */ + diff --git a/darkice/tags/darkice-1_3/src/VorbisLibEncoder.cpp b/darkice/tags/darkice-1_3/src/VorbisLibEncoder.cpp new file mode 100644 index 0000000..3b6b851 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/VorbisLibEncoder.cpp @@ -0,0 +1,455 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : VorbisLibEncoder.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// compile only if configured for Ogg Vorbis +#ifdef HAVE_VORBIS_LIB + + +#include "Exception.h" +#include "Util.h" +#include "VorbisLibEncoder.h" +#define VORBIS_MIN_BITRATE 45 + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the encoder + *----------------------------------------------------------------------------*/ +void +VorbisLibEncoder :: init ( unsigned int outMaxBitrate ) + throw ( Exception ) +{ + this->outMaxBitrate = outMaxBitrate; + + if ( getInBitsPerSample() != 16 && getInBitsPerSample() != 8 ) { + throw Exception( __FILE__, __LINE__, + "specified bits per sample not supported", + getInBitsPerSample() ); + } + + if ( getInChannel() != 1 && getInChannel() != 2 ) { + throw Exception( __FILE__, __LINE__, + "unsupported number of channels for the encoder", + getInChannel() ); + } + + if ( getOutBitrateMode() == abr || getOutBitrateMode() == cbr ) { + if ( getOutBitrate() < VORBIS_MIN_BITRATE ) { + throw Exception( __FILE__, __LINE__, + "output bitrate is lower than libvorbis minimum", + getOutBitrate() ); + } + + } + + if ( getOutSampleRate() == getInSampleRate() ) { + resampleRatio = 1; + converter = 0; + } else { + resampleRatio = ( (double) getOutSampleRate() / + (double) getInSampleRate() ); + + // Determine if we can use linear interpolation. + // The inverse of the ratio must be a power of two for linear mode to + // be of sufficient quality. + + bool useLinear = true; + double inverse = 1 / resampleRatio; + int integer = (int) inverse; + + // Check that the inverse of the ratio is an integer + if( integer == inverse ) { + while( useLinear && integer ) { // Loop through the bits + // If the lowest order bit is not the only one set + if( integer & 1 && integer != 1 ) { + // Not a power of two; cannot use linear + useLinear = false; + } else { + // Shift all the bits over and try again + integer >>= 1; + } + } + } else { + useLinear = false; + } + + // If we get here and useLinear is still true, then we have + // a power of two. + + // open the aflibConverter in + // - high quality + // - linear or quadratic (non-linear) based on algorithm + // - not filter interpolation +#ifdef HAVE_SRC_LIB + int srcError = 0; + converter = src_new(useLinear == true ? SRC_LINEAR : SRC_SINC_FASTEST, + getInChannel(), &srcError); + if(srcError) + throw Exception (__FILE__, __LINE__, "libsamplerate error: ", src_strerror (srcError)); +#else + converter = new aflibConverter( true, useLinear, false); +#endif + } + + encoderOpen = false; +} + + +/*------------------------------------------------------------------------------ + * Open an encoding session + *----------------------------------------------------------------------------*/ +bool +VorbisLibEncoder :: open ( void ) + throw ( Exception ) +{ + int ret; + + if ( isOpen() ) { + close(); + } + + // open the underlying sink + if ( !getSink()->open() ) { + throw Exception( __FILE__, __LINE__, + "vorbis lib opening underlying sink error"); + } + + vorbis_info_init( &vorbisInfo); + + switch ( getOutBitrateMode() ) { + + case cbr: { + int maxBitrate = getOutMaxBitrate() * 1000; + if ( !maxBitrate ) { + maxBitrate = -1; + } + if ( (ret = vorbis_encode_init( &vorbisInfo, + getOutChannel(), + getOutSampleRate(), + maxBitrate, + getOutBitrate() * 1000, + -1)) ) { + throw Exception( __FILE__, __LINE__, + "vorbis encode init error", ret); + } + } break; + + case abr: + /* set non-managed VBR around the average bitrate */ + ret = vorbis_encode_setup_managed( &vorbisInfo, + getOutChannel(), + getOutSampleRate(), + -1, + getOutBitrate() * 1000, + -1 ) + || vorbis_encode_ctl( &vorbisInfo, OV_ECTL_RATEMANAGE_SET, NULL) + || vorbis_encode_setup_init( &vorbisInfo); + if ( ret ) { + throw Exception( __FILE__, __LINE__, + "vorbis encode init error", ret); + } + break; + + case vbr: + if ( (ret = vorbis_encode_init_vbr( &vorbisInfo, + getOutChannel(), + getOutSampleRate(), + getOutQuality() )) ) { + throw Exception( __FILE__, __LINE__, + "vorbis encode init error", ret); + } + break; + } + + if ( (ret = vorbis_analysis_init( &vorbisDspState, &vorbisInfo)) ) { + throw Exception( __FILE__, __LINE__, "vorbis analysis init error", ret); + } + + if ( (ret = vorbis_block_init( &vorbisDspState, &vorbisBlock)) ) { + throw Exception( __FILE__, __LINE__, "vorbis block init error", ret); + } + + if ( (ret = ogg_stream_init( &oggStreamState, 0)) ) { + throw Exception( __FILE__, __LINE__, "ogg stream init error", ret); + } + + // create an empty vorbis_comment structure + vorbis_comment_init( &vorbisComment); + /* FIXME: removed title metadata when the sink type was changed from + * CastSink to the more generic Sink. + * make sure to add metadata somehow + // Add comment to vorbis headers to show title in players + // stupid cast to (char*) because of stupid vorbis API + if ( getSink()->getName() ) { + vorbis_comment_add_tag(&vorbisComment, + "TITLE", + (char*) getSink()->getName()); + } + */ + + // create the vorbis stream headers and send them to the underlying sink + ogg_packet header; + ogg_packet commentHeader; + ogg_packet codeHeader; + + if ( (ret = vorbis_analysis_headerout( &vorbisDspState, + &vorbisComment, + &header, + &commentHeader, + &codeHeader )) ) { + throw Exception( __FILE__, __LINE__, "vorbis header init error", ret); + } + + ogg_stream_packetin( &oggStreamState, &header); + ogg_stream_packetin( &oggStreamState, &commentHeader); + ogg_stream_packetin( &oggStreamState, &codeHeader); + + ogg_page oggPage; + while ( ogg_stream_flush( &oggStreamState, &oggPage) ) { + getSink()->write( oggPage.header, oggPage.header_len); + getSink()->write( oggPage.body, oggPage.body_len); + } + + vorbis_comment_clear( &vorbisComment ); + + // initialize the resampling coverter if needed + if ( converter ) { +#ifdef HAVE_SRC_LIB + converterData.input_frames = 4096/((getInBitsPerSample() / 8) * getInChannel()); + converterData.data_in = new float[converterData.input_frames*getInChannel()]; + converterData.output_frames = (int) (converterData.input_frames * resampleRatio + 1); + converterData.data_out = new float[getInChannel() * converterData.output_frames]; + converterData.src_ratio = resampleRatio; + converterData.end_of_input = 0; +#else + converter->initialize( resampleRatio, getInChannel()); +#endif + } + + encoderOpen = true; + + return true; +} + + +/*------------------------------------------------------------------------------ + * Write data to the encoder + *----------------------------------------------------------------------------*/ +unsigned int +VorbisLibEncoder :: write ( const void * buf, + unsigned int len ) throw ( Exception ) +{ + if ( !isOpen() || len == 0 ) { + return 0; + } + + unsigned int channels = getInChannel(); + unsigned int bitsPerSample = getInBitsPerSample(); + unsigned int sampleSize = (bitsPerSample / 8) * channels; + + unsigned int i; + + if ( getInChannel() == 2 && getOutChannel() == 1 ) { + for ( i = 0; i < len/sampleSize; i++) { + if ( bitsPerSample == 8 ) { + char * buf8 = (char *) buf; + unsigned int ix = sampleSize * i; + unsigned int iix = ix; + buf8[i] = (buf8[ix] + buf8[++iix]) / 2; + } + if ( bitsPerSample == 16 ) { + short * buf16 = (short *) buf; + unsigned int ix = (bitsPerSample >> 3) * i; + unsigned int iix = ix; + buf16[i] = (buf16[ix] + buf16[++iix]) / 2; + } + } + len >>= 1; + channels = 1; + } + + sampleSize = (bitsPerSample / 8) * channels; + unsigned char * b = (unsigned char*) buf; + unsigned int processed = len - (len % sampleSize); + unsigned int nSamples = processed / sampleSize; + float ** vorbisBuffer; + + + // convert the byte-based raw input into a short buffer + // with channels still interleaved + unsigned int totalSamples = nSamples * channels; + short int * shortBuffer = new short int[totalSamples]; + + + Util::conv( bitsPerSample, b, processed, shortBuffer, isInBigEndian()); + + if ( converter ) { + // resample if needed + int inCount = nSamples; + int outCount = (int) (inCount * resampleRatio); + short int * resampledBuffer = new short int[(outCount+1)* channels]; + int converted; +#ifdef HAVE_SRC_LIB + converterData.input_frames = nSamples; + src_short_to_float_array (shortBuffer, converterData.data_in, totalSamples); + int srcError = src_process (converter, &converterData); + if (srcError) + throw Exception (__FILE__, __LINE__, "libsamplerate error: ", src_strerror (srcError)); + converted = converterData.output_frames_gen; + + src_float_to_short_array(converterData.data_out, resampledBuffer, converted*channels); + +#else + converted = converter->resample( inCount, + outCount, + shortBuffer, + resampledBuffer ); +#endif + + vorbisBuffer = vorbis_analysis_buffer( &vorbisDspState, + converted); + Util::conv( resampledBuffer, + converted * channels, + vorbisBuffer, + channels); + delete[] resampledBuffer; + + vorbis_analysis_wrote( &vorbisDspState, converted); + + } else { + + vorbisBuffer = vorbis_analysis_buffer( &vorbisDspState, nSamples); + Util::conv( shortBuffer, totalSamples, vorbisBuffer, channels); + vorbis_analysis_wrote( &vorbisDspState, nSamples); + } + + delete[] shortBuffer; + + vorbisBlocksOut(); + + return processed; +} + + +/*------------------------------------------------------------------------------ + * Flush the data from the encoder + *----------------------------------------------------------------------------*/ +void +VorbisLibEncoder :: flush ( void ) + throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + vorbis_analysis_wrote( &vorbisDspState, 0); + vorbisBlocksOut(); + getSink()->flush(); +} + + +/*------------------------------------------------------------------------------ + * Send pending Vorbis blocks to the underlying stream + *----------------------------------------------------------------------------*/ +void +VorbisLibEncoder :: vorbisBlocksOut ( void ) throw ( Exception ) +{ + while ( 1 == vorbis_analysis_blockout( &vorbisDspState, &vorbisBlock) ) { + ogg_packet oggPacket; + ogg_page oggPage; + + vorbis_analysis( &vorbisBlock, &oggPacket); + vorbis_bitrate_addblock( &vorbisBlock); + + while ( vorbis_bitrate_flushpacket( &vorbisDspState, &oggPacket) ) { + + ogg_stream_packetin( &oggStreamState, &oggPacket); + + while ( ogg_stream_pageout( &oggStreamState, &oggPage) ) { + int written = 0; + + written = getSink()->write(oggPage.header, oggPage.header_len); + written += getSink()->write( oggPage.body, oggPage.body_len); + + if ( written < oggPage.header_len + oggPage.body_len ) { + // just let go data that could not be written + reportEvent( 2, + "couldn't write full vorbis data to underlying sink", + oggPage.header_len + oggPage.body_len - written); + } + } + } + } +} + + +/*------------------------------------------------------------------------------ + * Close the encoding session + *----------------------------------------------------------------------------*/ +void +VorbisLibEncoder :: close ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + flush(); + + ogg_stream_clear( &oggStreamState); + vorbis_block_clear( &vorbisBlock); + vorbis_dsp_clear( &vorbisDspState); + vorbis_comment_clear( &vorbisComment); + vorbis_info_clear( &vorbisInfo); + + encoderOpen = false; + + getSink()->close(); + } +} + + +#endif // HAVE_VORBIS_LIB + diff --git a/darkice/tags/darkice-1_3/src/VorbisLibEncoder.h b/darkice/tags/darkice-1_3/src/VorbisLibEncoder.h new file mode 100644 index 0000000..114905f --- /dev/null +++ b/darkice/tags/darkice-1_3/src/VorbisLibEncoder.h @@ -0,0 +1,453 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : VorbisLibEncoder.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef VORBIS_LIB_ENCODER_H +#define VORBIS_LIB_ENCODER_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_VORBIS_LIB +#include +#else +#error configure for Ogg Vorbis +#endif + + +#include "Ref.h" +#include "Exception.h" +#include "Reporter.h" +#include "AudioEncoder.h" +#include "Sink.h" +#ifdef HAVE_SRC_LIB +#include +#else +#include "aflibConverter.h" +#endif + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A class representing the ogg vorbis encoder linked as a shared object or + * as a static library. + * + * @author $Author$ + * @version $Revision$ + */ +class VorbisLibEncoder : public AudioEncoder, public virtual Reporter +{ + private: + + /** + * Value indicating if the encoding process is going on + */ + bool encoderOpen; + + /** + * Ogg Vorbis library global info + */ + vorbis_info vorbisInfo; + + /** + * Ogg Vorbis library global DSP state + */ + vorbis_dsp_state vorbisDspState; + + /** + * Ogg Vorbis library global block + */ + vorbis_block vorbisBlock; + + /** + * Ogg Vorbis library global comment + */ + vorbis_comment vorbisComment; + + /** + * Ogg library global stream state + */ + ogg_stream_state oggStreamState; + + /** + * Maximum bitrate of the output in kbits/sec. If 0, don't care. + */ + unsigned int outMaxBitrate; + + /** + * Resample ratio + */ + double resampleRatio; + + /** + * sample rate converter object for possible resampling + */ +#ifdef HAVE_SRC_LIB + SRC_STATE * converter; + SRC_DATA converterData; +#else + aflibConverter * converter; +#endif + + /** + * Initialize the object. + * + * @param the maximum bit rate + * @exception Exception + */ + void + init ( unsigned int outMaxBitrate ) throw ( Exception ); + + /** + * De-initialize the object. + * + * @exception Exception + */ + inline void + strip ( void ) throw ( Exception ) + { + if ( converter ) { +#ifdef HAVE_SRC_LIB + delete [] converterData.data_in; + delete [] converterData.data_out; + src_delete (converter); +#else + delete converter; +#endif + } + } + + /** + * Send pending Vorbis blocks to the underlying stream + */ + void + vorbisBlocksOut( void ) throw ( Exception ); + + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + VorbisLibEncoder ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + + public: + + /** + * Constructor. + * + * @param sink the sink to send encoded output to + * @param inSampleRate sample rate of the input. + * @param inBitsPerSample number of bits per sample of the input. + * @param inChannel number of channels of the input. + * @param inBigEndian shows if the input is big or little endian + * @param outBitrateMode the bit rate mode of the output. + * @param outBitrate bit rate of the output (kbits/sec). + * @param outQuality the quality of the stream. + * @param outSampleRate sample rate of the output. + * If 0, inSampleRate is used. + * @param outMaxBitrate maximum output bitrate. + * 0 if not used. + * @param outChannel number of channels of the output. + * If 0, inChannel is used. + * @exception Exception + */ + inline + VorbisLibEncoder ( Sink * sink, + unsigned int inSampleRate, + unsigned int inBitsPerSample, + unsigned int inChannel, + bool inBigEndian, + BitrateMode outBitrateMode, + unsigned int outBitrate, + double outQuality, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0, + unsigned int outMaxBitrate = 0 ) + throw ( Exception ) + + : AudioEncoder ( sink, + inSampleRate, + inBitsPerSample, + inChannel, + inBigEndian, + outBitrateMode, + outBitrate, + outQuality, + outSampleRate, + outChannel ) + { + init( outMaxBitrate); + } + + /** + * Constructor. + * + * @param sink the sink to send encoded output to + * @param as get input sample rate, bits per sample and channels + * from this AudioSource. + * @param outBitrateMode the bit rate mode of the output. + * @param outBitrate bit rate of the output (kbits/sec). + * @param outQuality the quality of the stream. + * @param outSampleRate sample rate of the output. + * If 0, input sample rate is used. + * @param outMaxBitrate maximum output bitrate. + * 0 if not used. + * @param outChannel number of channels of the output. + * If 0, input channel is used. + * @exception Exception + */ + inline + VorbisLibEncoder ( Sink * sink, + const AudioSource * as, + BitrateMode outBitrateMode, + unsigned int outBitrate, + double outQuality, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0, + unsigned int outMaxBitrate = 0 ) + throw ( Exception ) + + : AudioEncoder ( sink, + as, + outBitrateMode, + outBitrate, + outQuality, + outSampleRate, + outChannel ) + { + init( outMaxBitrate); + } + + /** + * Copy constructor. + * + * @param encoder the VorbisLibEncoder to copy. + */ + inline + VorbisLibEncoder ( const VorbisLibEncoder & encoder ) + throw ( Exception ) + : AudioEncoder( encoder ) + { + if( encoder.isOpen() ) { + throw Exception(__FILE__, __LINE__, "don't copy open encoders"); + } + init( encoder.getOutMaxBitrate() ); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~VorbisLibEncoder ( void ) throw ( Exception ) + { + if ( isOpen() ) { + close(); + } + strip(); + } + + /** + * Assignment operator. + * + * @param encoder the VorbisLibEncoder to assign this to. + * @return a reference to this VorbisLibEncoder. + * @exception Exception + */ + inline virtual VorbisLibEncoder & + operator= ( const VorbisLibEncoder & encoder ) throw ( Exception ) + { + if( encoder.isOpen() ) { + throw Exception(__FILE__, __LINE__, "don't copy open encoders"); + } + + if ( this != &encoder ) { + strip(); + AudioEncoder::operator=( encoder); + init( encoder.getOutMaxBitrate() ); + } + + return *this; + } + + /** + * Get the maximum bit rate of the output in kbits/sec, + * for fixed / average bitrate encodings. + * + * @return the maximum bit rate of the output, or 0 if not set. + */ + inline unsigned int + getOutMaxBitrate ( void ) const throw () + { + return outMaxBitrate; + } + + /** + * Check whether encoding is in progress. + * + * @return true if encoding is in progress, false otherwise. + */ + inline virtual bool + isRunning ( void ) const throw () + { + return isOpen(); + } + + /** + * Start encoding. This function returns as soon as possible, + * with encoding started in the background. + * + * @return true if encoding has started, false otherwise. + * @exception Exception + */ + inline virtual bool + start ( void ) throw ( Exception ) + { + return open(); + } + + /** + * Stop encoding. Stops the encoding running in the background. + * + * @exception Exception + */ + inline virtual void + stop ( void ) throw ( Exception ) + { + return close(); + } + + /** + * Open an encoding session. + * + * @return true if opening was successfull, false otherwise. + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the encoding session is open. + * + * @return true if the encoding session is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return encoderOpen; + } + + /** + * Check if the encoder is ready to accept data. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the encoder is ready to accept data, + * false otherwise. + * @exception Exception + */ + inline virtual bool + canWrite ( unsigned int sec, + unsigned int usec ) throw ( Exception ) + { + if ( !isOpen() ) { + return false; + } + + if ( 1 == vorbis_analysis_blockout( &vorbisDspState, &vorbisBlock) ) { + return getSink()->canWrite(sec, usec); + } else { + return true; + } + } + + /** + * Write data to the encoder. + * Buf is expected to be a sequence of big-endian 16 bit values, + * with left and right channels interleaved. Len is the number of + * bytes, must be a multiple of 4. + * + * @param buf the data to write. + * @param len number of bytes to write from buf. + * @return the number of bytes written (may be less than len). + * @exception Exception + */ + virtual unsigned int + write ( const void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Flush all data that was written to the encoder to the underlying + * connection. + * + * @exception Exception + */ + virtual void + flush ( void ) throw ( Exception ); + + /** + * Close the encoding session. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* VORBIS_LIB_ENCODER_H */ diff --git a/darkice/tags/darkice-1_3/src/aacPlusEncoder.cpp b/darkice/tags/darkice-1_3/src/aacPlusEncoder.cpp new file mode 100644 index 0000000..b3c36cd --- /dev/null +++ b/darkice/tags/darkice-1_3/src/aacPlusEncoder.cpp @@ -0,0 +1,278 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2005 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : aacPlusEncoder.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// compile the whole file only if aacplus support configured in +#ifdef HAVE_AACPLUS_LIB + + + +#include "Exception.h" +#include "Util.h" +#include "aacPlusEncoder.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Open an encoding session + *----------------------------------------------------------------------------*/ +bool +aacPlusEncoder :: open ( void ) + throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + // open the underlying sink + if ( !sink->open() ) { + throw Exception( __FILE__, __LINE__, + "aacplus lib opening underlying sink error"); + } + + reportEvent(1, "Using aacplus codec"); + + encoderHandle = aacplusEncOpen(getOutSampleRate(), + getInChannel(), + &inputSamples, + &maxOutputBytes); + + aacplusEncConfiguration * aacplusConfig; + + aacplusConfig = aacplusEncGetCurrentConfiguration(encoderHandle); + + aacplusConfig->bitRate = getOutBitrate() * 1000; + aacplusConfig->bandWidth = lowpass; + aacplusConfig->outputFormat = 1; + aacplusConfig->inputFormat = AACPLUS_INPUT_16BIT; + aacplusConfig->nChannelsOut = getOutChannel(); + + if (!aacplusEncSetConfiguration(encoderHandle, aacplusConfig)) { + throw Exception(__FILE__, __LINE__, + "error configuring libaacplus library"); + } + + // initialize the resampling coverter if needed + if ( converter ) { +#ifdef HAVE_SRC_LIB + converterData.input_frames = 4096/((getInBitsPerSample() / 8) * getInChannel()); + converterData.data_in = new float[converterData.input_frames*getInChannel()]; + converterData.output_frames = (int) (converterData.input_frames * resampleRatio + 1); + if ((int) inputSamples > getInChannel() * converterData.output_frames) { + resampledOffset = new float[2 * inputSamples]; + } else { + resampledOffset = new float[2 * getInChannel() * converterData.input_frames]; + } + converterData.src_ratio = resampleRatio; + converterData.end_of_input = 0; +#else + converter->initialize( resampleRatio, getInChannel()); + //needed 2x(converted input samples) to handle offsets + int outCount = 2 * getInChannel() * (inputSamples + 1); + if (resampleRatio > 1) + outCount = (int) (outCount * resampleRatio); + resampledOffset = new short int[outCount]; +#endif + resampledOffsetSize = 0; + } + + aacplusOpen = true; + reportEvent(10, "nChannelsAAC", aacplusConfig->nChannelsOut); + reportEvent(10, "sampleRateAAC", aacplusConfig->sampleRate); + reportEvent(10, "inSamples", inputSamples); + return true; +} + + +/*------------------------------------------------------------------------------ + * Write data to the encoder + *----------------------------------------------------------------------------*/ +unsigned int +aacPlusEncoder :: write ( const void * buf, + unsigned int len ) throw ( Exception ) +{ + if ( !isOpen() || len == 0) { + return 0; + } + + unsigned int channels = getInChannel(); + unsigned int bitsPerSample = getInBitsPerSample(); + unsigned int sampleSize = (bitsPerSample / 8) * channels; + unsigned char * b = (unsigned char*) buf; + unsigned int processed = len - (len % sampleSize); + unsigned int nSamples = processed / sampleSize; + unsigned char * aacplusBuf = new unsigned char[maxOutputBytes]; + int samples = (int) nSamples * channels; + int processedSamples = 0; + + + if ( converter ) { + unsigned int converted; +#ifdef HAVE_SRC_LIB + src_short_to_float_array ((short *) b, converterData.data_in, samples); + converterData.input_frames = nSamples; + converterData.data_out = resampledOffset + (resampledOffsetSize * channels); + int srcError = src_process (converter, &converterData); + if (srcError) + throw Exception (__FILE__, __LINE__, "libsamplerate error: ", src_strerror (srcError)); + converted = converterData.output_frames_gen; +#else + int inCount = nSamples; + short int * shortBuffer = new short int[samples]; + int outCount = (int) (inCount * resampleRatio); + Util::conv( bitsPerSample, b, processed, shortBuffer, isInBigEndian()); + converted = converter->resample( inCount, + outCount+1, + shortBuffer, + &resampledOffset[resampledOffsetSize*channels]); + delete[] shortBuffer; +#endif + resampledOffsetSize += converted; + + // encode samples (if enough) + while(resampledOffsetSize - processedSamples >= inputSamples/channels) { +#ifdef HAVE_SRC_LIB + short *shortData = new short[inputSamples]; + src_float_to_short_array(resampledOffset + (processedSamples * channels), + shortData, inputSamples) ; + int outputBytes = aacplusEncEncode(encoderHandle, + (int32_t*) shortData, + inputSamples, + aacplusBuf, + maxOutputBytes); + delete [] shortData; +#else + int outputBytes = aacplusEncEncode(encoderHandle, + (int32_t*) &resampledOffset[processedSamples*channels], + inputSamples, + aacplusBuf, + maxOutputBytes); +#endif + unsigned int wrote = getSink()->write(aacplusBuf, outputBytes); + + if (wrote < outputBytes) { + reportEvent(3, "aacPlusEncoder :: write, couldn't write full data to underlying sink"); + } + + processedSamples+=inputSamples/channels; + } + + if (processedSamples && (int) resampledOffsetSize >= processedSamples) { + resampledOffsetSize -= processedSamples; + //move least part of resampled data to beginning + if(resampledOffsetSize) +#ifdef HAVE_SRC_LIB + resampledOffset = (float *) memmove(resampledOffset, &resampledOffset[processedSamples*channels], + resampledOffsetSize*channels*sizeof(float)); +#else + resampledOffset = (short *) memmove(resampledOffset, &resampledOffset[processedSamples*channels], + resampledOffsetSize*sampleSize); +#endif + } + } else { + while (processedSamples < samples) { + int inSamples = samples - processedSamples < (int) inputSamples + ? samples - processedSamples + : inputSamples; + + int outputBytes = aacplusEncEncode(encoderHandle, + (int32_t*) (b + processedSamples/sampleSize), + inSamples, + aacplusBuf, + maxOutputBytes); + + unsigned int wrote = getSink()->write(aacplusBuf, outputBytes); + + if (wrote < outputBytes) { + reportEvent(3, "aacPlusEncoder :: write, couldn't write full data to underlying sink"); + } + + processedSamples += inSamples; + } + } + + delete[] aacplusBuf; + +// return processedSamples; + return samples * sampleSize; +} + +/*------------------------------------------------------------------------------ + * Flush the data from the encoder + *----------------------------------------------------------------------------*/ +void +aacPlusEncoder :: flush ( void ) + throw ( Exception ) +{ + if ( !isOpen() ) { + return; + } + + sink->flush(); +} + + +/*------------------------------------------------------------------------------ + * Close the encoding session + *----------------------------------------------------------------------------*/ +void +aacPlusEncoder :: close ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + flush(); + + aacplusEncClose(encoderHandle); + aacplusOpen = false; + + sink->close(); + } +} + + +#endif // HAVE_AACPLUS_LIB diff --git a/darkice/tags/darkice-1_3/src/aacPlusEncoder.h b/darkice/tags/darkice-1_3/src/aacPlusEncoder.h new file mode 100644 index 0000000..ea7881f --- /dev/null +++ b/darkice/tags/darkice-1_3/src/aacPlusEncoder.h @@ -0,0 +1,520 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : aacPlusEncoder.h + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef AACP_ENCODER_H +#define AACP_ENCODER_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_AACPLUS_LIB +#include +#else +#error configure with aacplus +#endif + +#include +#include + +#include "Ref.h" +#include "Exception.h" +#include "Reporter.h" +#include "AudioEncoder.h" +#include "Sink.h" +#ifdef HAVE_SRC_LIB +#include +#else +#include "aflibConverter.h" +#endif + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * A class representing aacplus AAC+ encoder. + * + * @author $Author$ + * @version $Revision$ + */ + +class aacPlusEncoder : public AudioEncoder, public virtual Reporter +{ + private: + /** + * A flag to indicate if the encoding session is open. + */ + bool aacplusOpen; + + /** + * Resample ratio + */ + double resampleRatio; + + /** + * sample rate converter object for possible resampling + */ +#ifdef HAVE_SRC_LIB + SRC_STATE *converter; + SRC_DATA converterData; + float *resampledOffset; +#else + aflibConverter *converter; + short *resampledOffset; +#endif + unsigned int resampledOffsetSize; + + /** + * The Sink to dump aac+ data to + */ + Ref sink; + + /** + * The handle to the AAC+ encoder instance. + */ + aacplusEncHandle encoderHandle; + + /** + * The maximum number of input samples to supply to the encoder. + */ + unsigned long inputSamples; + + /** + * The maximum number of output bytes the encoder returns in one call. + */ + unsigned long maxOutputBytes; + + /** + * Lowpass filter. Sound frequency in Hz, from where up the + * input is cut. + */ + int lowpass; + + /** + * Initialize the object. + * + * @param sink the sink to send mp3 output to + * @exception Exception + */ + inline void + init ( Sink * sink, int lowpass) throw (Exception) + { + this->aacplusOpen = false; + this->sink = sink; + this->lowpass = lowpass; + + /* TODO: if we have float as input, we don't need conversion */ + if ( getInBitsPerSample() != 16 && getInBitsPerSample() != 32 ) { + throw Exception( __FILE__, __LINE__, + "specified bits per sample not supported", + getInBitsPerSample() ); + } + + if ( getInChannel() > 2 ) { + throw Exception( __FILE__, __LINE__, + "unsupported number of input channels for the encoder", + getInChannel() ); + } + if ( getOutChannel() > 2 ) { + throw Exception( __FILE__, __LINE__, + "unsupported number of output channels for the encoder", + getOutChannel() ); + } + + if ( getOutSampleRate() == getInSampleRate() ) { + resampleRatio = 1; + converter = 0; + } else if (getInBitsPerSample() == 16) { + resampleRatio = ( (double) getOutSampleRate() / + (double) getInSampleRate() ); + + // Determine if we can use linear interpolation. + // The inverse of the ratio must be a power of two for linear mode to + // be of sufficient quality. + + bool useLinear = true; + double inverse = 1 / resampleRatio; + int integer = (int) inverse; + + // Check that the inverse of the ratio is an integer + if( integer == inverse ) { + while( useLinear && integer ) { // Loop through the bits + // If the lowest order bit is not the only one set + if( integer & 1 && integer != 1 ) { + // Not a power of two; cannot use linear + useLinear = false; + } else { + // Shift all the bits over and try again + integer >>= 1; + } + } + } else { + useLinear = false; + } + + // If we get here and useLinear is still true, then we have + // a power of two. + + // open the aflibConverter in + // - high quality + // - linear or quadratic (non-linear) based on algorithm + // - not filter interpolation +#ifdef HAVE_SRC_LIB + int srcError = 0; + converter = src_new(useLinear == true ? SRC_LINEAR : SRC_SINC_FASTEST, + getInChannel(), &srcError); + if(srcError) + throw Exception (__FILE__, __LINE__, "libsamplerate error: ", src_strerror (srcError)); +#else + converter = new aflibConverter( true, useLinear, false); +#endif + } else { + throw Exception( __FILE__, __LINE__, + "specified bits per sample with samplerate conversion not supported", + getInBitsPerSample() ); + } + } + + /** + * De-initialize the object. + * + * @exception Exception + */ + inline void + strip ( void ) throw ( Exception ) + { + if ( converter ) { +#ifdef HAVE_SRC_LIB + delete [] converterData.data_in; + src_delete (converter); +#else + delete converter; +#endif + delete [] resampledOffset; + } + } + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + aacPlusEncoder ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + + public: + + /** + * Constructor. + * + * @param sink the sink to send mp3 output to + * @param inSampleRate sample rate of the input. + * @param inBitsPerSample number of bits per sample of the input. + * @param inChannel number of channels of the input. + * @param inBigEndian shows if the input is big or little endian + * @param outBitrateMode the bit rate mode of the output. + * @param outBitrate bit rate of the output (kbits/sec). + * @param outQuality the quality of the stream. + * @param outSampleRate sample rate of the output. + * If 0, inSampleRate is used. + * @param outChannel number of channels of the output. + * If 0, inChannel is used. + * @param lowpass frequency threshold for the lowpass filter. + * Input above this frequency is cut. + * If 0, aacplus's default values are used, + * which depends on the out sample rate. + * @exception Exception + */ + inline + aacPlusEncoder ( Sink * sink, + unsigned int inSampleRate, + unsigned int inBitsPerSample, + unsigned int inChannel, + bool inBigEndian, + BitrateMode outBitrateMode, + unsigned int outBitrate, + double outQuality, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0, + int lowpass = 0) + throw ( Exception ) + + : AudioEncoder ( sink, + inSampleRate, + inBitsPerSample, + inChannel, + inBigEndian, + outBitrateMode, + outBitrate, + outQuality, + outSampleRate, + outChannel ) + { + init( sink, lowpass); + } + + /** + * Constructor. + * + * @param sink the sink to send mp3 output to + * @param as get input sample rate, bits per sample and channels + * from this AudioSource. + * @param outBitrateMode the bit rate mode of the output. + * @param outBitrate bit rate of the output (kbits/sec). + * @param outQuality the quality of the stream. + * @param outSampleRate sample rate of the output. + * If 0, input sample rate is used. + * @param outChannel number of channels of the output. + * If 0, input channel is used. + * @param lowpass frequency threshold for the lowpass filter. + * Input above this frequency is cut. + * If 0, aacplus's default values are used, + * which depends on the out sample rate. + * @exception Exception + */ + inline + aacPlusEncoder ( Sink * sink, + const AudioSource * as, + BitrateMode outBitrateMode, + unsigned int outBitrate, + double outQuality, + unsigned int outSampleRate = 0, + unsigned int outChannel = 0, + int lowpass = 0) + throw ( Exception ) + + : AudioEncoder ( sink, + as, + outBitrateMode, + outBitrate, + outQuality, + outSampleRate, + outChannel ) + { + init( sink, lowpass ); + } + + /** + * Copy constructor. + * + * @param encoder the aacPlusEncoder to copy. + */ + inline + aacPlusEncoder ( const aacPlusEncoder & encoder ) + throw ( Exception ) + : AudioEncoder( encoder ) + { + init( encoder.sink.get(), encoder.lowpass); + } + + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~aacPlusEncoder ( void ) throw ( Exception ) + { + if ( isOpen() ) { + close(); + } + strip(); + } + + /** + * Assignment operator. + * + * @param encoder the aacPlusEncoder to assign this to. + * @return a reference to this aacPlusEncoder. + * @exception Exception + */ + inline virtual aacPlusEncoder & + operator= ( const aacPlusEncoder & encoder ) throw ( Exception ) + { + if ( this != &encoder ) { + strip(); + AudioEncoder::operator=( encoder); + init( encoder.sink.get(), encoder.lowpass); + } + + return *this; + } + + /** + * Get the version string of the underlying aacplus library. + * + * @return the version string of the underlying aacplus library. + */ + inline const char * + getAacPlusVersion( void ) + { + char * id; + //char * copyright; + + /* aacplusEncGetVersion(&id, ©right); */ + return id; + } + + /** + * Check whether encoding is in progress. + * + * @return true if encoding is in progress, false otherwise. + */ + inline virtual bool + isRunning ( void ) const throw () + { + return isOpen(); + } + + /** + * Start encoding. This function returns as soon as possible, + * with encoding started in the background. + * + * @return true if encoding has started, false otherwise. + * @exception Exception + */ + inline virtual bool + start ( void ) throw ( Exception ) + { + return open(); + } + + /** + * Stop encoding. Stops the encoding running in the background. + * + * @exception Exception + */ + inline virtual void + stop ( void ) throw ( Exception ) + { + return close(); + } + + /** + * Open an encoding session. + * + * @return true if opening was successfull, false otherwise. + * @exception Exception + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the encoding session is open. + * + * @return true if the encoding session is open, false otherwise. + */ + inline virtual bool + isOpen ( void ) const throw () + { + return aacplusOpen; + } + + /** + * Check if the encoder is ready to accept data. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the encoder is ready to accept data, + * false otherwise. + * @exception Exception + */ + inline virtual bool + canWrite ( unsigned int sec, + unsigned int usec ) throw ( Exception ) + { + if ( !isOpen() ) { + return false; + } + + return true; + } + + /** + * Write data to the encoder. + * Buf is expected to be a sequence of big-endian 16 bit values, + * with left and right channels interleaved. Len is the number of + * bytes, must be a multiple of 4. + * + * @param buf the data to write. + * @param len number of bytes to write from buf. + * @return the number of bytes written (may be less than len). + * @exception Exception + */ + virtual unsigned int + write ( const void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Flush all data that was written to the encoder to the underlying + * connection. + * + * @exception Exception + */ + virtual void + flush ( void ) throw ( Exception ); + + /** + * Close the encoding session. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); +}; + + + + +/* ================================================= external data structures */ + +/* ====================================================== function prototypes */ + + +#endif /* AACP_ENCODER_H */ + diff --git a/darkice/tags/darkice-1_3/src/aflibConverter.cc b/darkice/tags/darkice-1_3/src/aflibConverter.cc new file mode 100644 index 0000000..67a2cda --- /dev/null +++ b/darkice/tags/darkice-1_3/src/aflibConverter.cc @@ -0,0 +1,797 @@ +/* + * Copyright: (C) 2000 Julius O. Smith + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Julius O. Smith jos@ccrma.stanford.edu + * + */ +/* This code was modified by Bruce Forsberg (forsberg@tns.net) to make it + into a C++ class +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "aflibConverter.h" +#include "aflibConverterLargeFilter.h" +#include "aflibConverterSmallFilter.h" + +#include "aflibDebug.h" + +#if (!defined(TRUE) || !defined(FALSE)) +# define TRUE 1 +# define FALSE 0 +#endif + + +/* + * The configuration constants below govern + * the number of bits in the input sample and filter coefficients, the + * number of bits to the right of the binary-point for fixed-point math, etc. + */ + +/* Conversion constants */ +#define Nhc 8 +#define Na 7 +#define Np (Nhc+Na) +#define Npc (1< (inCount - (int)framecount)) + { + Nsamps = inCount - framecount; + } + + for (c = 0; c < _nChans; c++) + { + ptr = outPtr[c]; + ptr += Xoff; /* Start at designated sample number */ + + for (i = 0; i < Nsamps; i++) + *ptr++ = (short) inArray[c * inCount + i + framecount]; + } + + framecount += Nsamps; + + if ((int)framecount >= inCount) /* return index of last samp */ + return (((Nsamps - (framecount - inCount)) - 1) + Xoff); + else + return 0; +} + +int +aflibConverter::SrcLinear( + short X[], + short Y[], + double factor, + unsigned int *Time, + unsigned short& Nx, + unsigned short Nout) +{ + short iconst; + short *Xp, *Ystart; + int v,x1,x2; + + double dt; /* Step through input signal */ + unsigned int dtb; /* Fixed-point version of Dt */ +// unsigned int endTime; /* When Time reaches EndTime, return to user */ + unsigned int start_sample, end_sample; + + dt = 1.0/factor; /* Output sampling period */ + dtb = (unsigned int)(dt*(1<>Np; + Ystart = Y; +// endTime = *Time + (1<>Np]; /* Ptr to current input sample */ + x1 = *Xp++; + x2 = *Xp; + x1 *= ((1<>Np; + Nx = end_sample - start_sample; + return (Y - Ystart); /* Return number of output samples */ +} + + +int +aflibConverter::SrcUp( + short X[], + short Y[], + double factor, + unsigned int *Time, + unsigned short& Nx, + unsigned short Nout, + unsigned short Nwing, + unsigned short LpScl, + short Imp[], + short ImpD[], + bool Interp) +{ + short *Xp, *Ystart; + int v; + + double dt; /* Step through input signal */ + unsigned int dtb; /* Fixed-point version of Dt */ +// unsigned int endTime; /* When Time reaches EndTime, return to user */ + unsigned int start_sample, end_sample; + + dt = 1.0/factor; /* Output sampling period */ + dtb = (unsigned int)(dt*(1<>Np; + Ystart = Y; +// endTime = *Time + (1<>Np]; /* Ptr to current input sample */ + /* Perform left-wing inner product */ + v = FilterUp(Imp, ImpD, Nwing, Interp, Xp, (short)(*Time&Pmask),-1); + /* Perform right-wing inner product */ + v += FilterUp(Imp, ImpD, Nwing, Interp, Xp+1, + (short)((((*Time)^Pmask)+1)&Pmask), 1); + v >>= Nhg; /* Make guard bits */ + v *= LpScl; /* Normalize for unity filter gain */ + *Y++ = WordToHword(v,NLpScl); /* strip guard bits, deposit output */ + *Time += dtb; /* Move to next sample by time increment */ + } + end_sample = (*Time)>>Np; + Nx = end_sample - start_sample; + return (Y - Ystart); /* Return the number of output samples */ +} + + + +int +aflibConverter::SrcUD( + short X[], + short Y[], + double factor, + unsigned int *Time, + unsigned short& Nx, + unsigned short Nout, + unsigned short Nwing, + unsigned short LpScl, + short Imp[], + short ImpD[], + bool Interp) +{ + short *Xp, *Ystart; + int v; + + double dh; /* Step through filter impulse response */ + double dt; /* Step through input signal */ +// unsigned int endTime; /* When Time reaches EndTime, return to user */ + unsigned int dhb, dtb; /* Fixed-point versions of Dh,Dt */ + unsigned int start_sample, end_sample; + + dt = 1.0/factor; /* Output sampling period */ + dtb = (unsigned int)(dt*(1<>Np; + Ystart = Y; +// endTime = *Time + (1<>Np]; /* Ptr to current input sample */ + v = FilterUD(Imp, ImpD, Nwing, Interp, Xp, (short)(*Time&Pmask), + -1, dhb); /* Perform left-wing inner product */ + v += FilterUD(Imp, ImpD, Nwing, Interp, Xp+1, + (short)((((*Time)^Pmask)+1)&Pmask), 1, dhb); /* Perform right-wing inner product */ + v >>= Nhg; /* Make guard bits */ + v *= LpScl; /* Normalize for unity filter gain */ + *Y++ = WordToHword(v,NLpScl); /* strip guard bits, deposit output */ + *Time += dtb; /* Move to next sample by time increment */ + } + + end_sample = (*Time)>>Np; + Nx = end_sample - start_sample; + return (Y - Ystart); /* Return the number of output samples */ +} + + +int +aflibConverter::resampleFast( /* number of output samples returned */ + int& inCount, /* number of input samples to convert */ + int outCount, /* number of output samples to compute */ + short inArray[], /* input data */ + short outArray[]) /* output data */ +{ + unsigned int Time2; /* Current time/pos in input sample */ +#if 0 + unsigned short Ncreep; +#endif + unsigned short Xp, Xoff, Xread; + int OBUFFSIZE = (int)(((double)IBUFFSIZE)*_factor); + unsigned short Nout = 0, Nx, orig_Nx; + unsigned short maxOutput; + int total_inCount = 0; + int c, i, Ycount, last; + bool first_pass = TRUE; + + + Xoff = 10; + + Nx = IBUFFSIZE - 2*Xoff; /* # of samples to process each iteration */ + last = 0; /* Have not read last input sample yet */ + Ycount = 0; /* Current sample and length of output file */ + + Xp = Xoff; /* Current "now"-sample pointer for input */ + Xread = Xoff; /* Position in input array to read into */ + + if (_initial == TRUE) + _Time = (Xoff< (OBUFFSIZE - (2*Xoff*_factor)) ) + maxOutput = OBUFFSIZE - (unsigned short)(2*Xoff*_factor); + else + maxOutput = outCount-Ycount; + + for (c = 0; c < _nChans; c++) + { + orig_Nx = Nx; + Time2 = _Time; + /* Resample stuff in input buffer */ + Nout=SrcLinear(_II[c],_JJ[c],_factor,&Time2,orig_Nx,maxOutput); + } + Nx = orig_Nx; + _Time = Time2; + + _Time -= (Nx<>Np) - Xoff; /* Calc time accumulation in Time */ + if (Ncreep) { + Time -= (Ncreep<outCount) { + Nout -= (Ycount-outCount); + Ycount = outCount; + } + + if (Nout > OBUFFSIZE) /* Check to see if output buff overflowed */ + return err_ret("Output array overflow"); + + for (c = 0; c < _nChans; c++) + for (i = 0; i < Nout; i++) + outArray[c * outCount + i + Ycount - Nout] = _JJ[c][i]; + + total_inCount += Nx; + + } while (Ycount < outCount); /* Continue until done */ + + inCount = total_inCount; + + return(Ycount); /* Return # of samples in output file */ +} + + +int +aflibConverter::resampleWithFilter( /* number of output samples returned */ + int& inCount, /* number of input samples to convert */ + int outCount, /* number of output samples to compute */ + short inArray[], /* input data */ + short outArray[], /* output data */ + short Imp[], short ImpD[], + unsigned short LpScl, unsigned short Nmult, unsigned short Nwing) +{ + unsigned int Time2; /* Current time/pos in input sample */ +#if 0 + unsigned short Ncreep; +#endif + unsigned short Xp, Xoff, Xread; + int OBUFFSIZE = (int)(((double)IBUFFSIZE)*_factor); + unsigned short Nout = 0, Nx, orig_Nx; + unsigned short maxOutput; + int total_inCount = 0; + int c, i, Ycount, last; + bool first_pass = TRUE; + + + /* Account for increased filter gain when using factors less than 1 */ + if (_factor < 1) + LpScl = (unsigned short)(LpScl*_factor + 0.5); + + /* Calc reach of LP filter wing & give some creeping room */ + Xoff = (unsigned short)(((Nmult+1)/2.0) * MAX(1.0,1.0/_factor) + 10); + + if (IBUFFSIZE < 2*Xoff) /* Check input buffer size */ + return err_ret("IBUFFSIZE (or factor) is too small"); + + Nx = IBUFFSIZE - 2*Xoff; /* # of samples to process each iteration */ + + last = 0; /* Have not read last input sample yet */ + Ycount = 0; /* Current sample and length of output file */ + Xp = Xoff; /* Current "now"-sample pointer for input */ + Xread = Xoff; /* Position in input array to read into */ + + if (_initial == TRUE) + _Time = (Xoff< (OBUFFSIZE - (2*Xoff*_factor)) ) + maxOutput = OBUFFSIZE - (unsigned short)(2*Xoff*_factor); + else + maxOutput = outCount-Ycount; + + for (c = 0; c < _nChans; c++) + { + orig_Nx = Nx; + Time2 = _Time; + /* Resample stuff in input buffer */ + if (_factor >= 1) { /* SrcUp() is faster if we can use it */ + Nout=SrcUp(_II[c],_JJ[c],_factor, + &Time2,Nx,maxOutput,Nwing,LpScl,Imp,ImpD,interpFilt); + } + else { + Nout=SrcUD(_II[c],_JJ[c],_factor, + &Time2,Nx,maxOutput,Nwing,LpScl,Imp,ImpD,interpFilt); + } + } + _Time = Time2; + + _Time -= (Nx<>Np) - Xoff; /* Calc time accumulation in Time */ + if (Ncreep) { + Time -= (Ncreep< outCount) { + Nout -= (Ycount - outCount); + Ycount = outCount; + } + + if (Nout > OBUFFSIZE) /* Check to see if output buff overflowed */ + return err_ret("Output array overflow"); + + for (c = 0; c < _nChans; c++) + { + for (i = 0; i < Nout; i++) + { + outArray[c * outCount + i + Ycount - Nout] = _JJ[c][i]; + } + } + + int act_incount = (int)Nx; + + for (c = 0; c < _nChans; c++) + { + for (i=0; i>Na]; + End = &Imp[Nwing]; + + if (Interp) + { + Hdp = &ImpD[Ph>>Na]; + a = Ph & Amask; + } + + if (Inc == 1) /* If doing right wing... */ + { /* ...drop extra coeff, so when Ph is */ + End--; /* 0.5, we don't do too many mult's */ + if (Ph == 0) /* If the phase is zero... */ + { /* ...then we've already skipped the */ + Hp += Npc; /* first sample, so we must also */ + Hdp += Npc; /* skip ahead in Imp[] and ImpD[] */ + } + } + + if (Interp) + { + while (Hp < End) + { + t = *Hp; /* Get filter coeff */ + t += (((int)*Hdp)*a)>>Na; /* t is now interp'd filter coeff */ + Hdp += Npc; /* Filter coeff differences step */ + t *= *Xp; /* Mult coeff by input sample */ + if (t & (1<<(Nhxn-1))) /* Round, if needed */ + t += (1<<(Nhxn-1)); + t >>= Nhxn; /* Leave some guard bits, but come back some */ + v += t; /* The filter output */ + Hp += Npc; /* Filter coeff step */ + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + } + } + else + { + while (Hp < End) + { + t = *Hp; /* Get filter coeff */ + t *= *Xp; /* Mult coeff by input sample */ + if (t & (1<<(Nhxn-1))) /* Round, if needed */ + t += (1<<(Nhxn-1)); + t >>= Nhxn; /* Leave some guard bits, but come back some */ + v += t; /* The filter output */ + Hp += Npc; /* Filter coeff step */ + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + } + } + return(v); +} + + +int +aflibConverter::FilterUD( + short Imp[], + short ImpD[], + unsigned short Nwing, + bool Interp, + short *Xp, + short Ph, + short Inc, + unsigned short dhb) +{ + short a; + short *Hp, *Hdp, *End; + int v, t; + unsigned int Ho; + + v=0; + Ho = (Ph*(unsigned int)dhb)>>Np; + End = &Imp[Nwing]; + if (Inc == 1) /* If doing right wing... */ + { /* ...drop extra coeff, so when Ph is */ + End--; /* 0.5, we don't do too many mult's */ + if (Ph == 0) /* If the phase is zero... */ + Ho += dhb; /* ...then we've already skipped the */ + } /* first sample, so we must also */ + /* skip ahead in Imp[] and ImpD[] */ + + if (Interp) + { + while ((Hp = &Imp[Ho>>Na]) < End) + { + t = *Hp; /* Get IR sample */ + Hdp = &ImpD[Ho>>Na]; /* get interp (lower Na) bits from diff table*/ + a = Ho & Amask; /* a is logically between 0 and 1 */ + t += (((int)*Hdp)*a)>>Na; /* t is now interp'd filter coeff */ + t *= *Xp; /* Mult coeff by input sample */ + if (t & 1<<(Nhxn-1)) /* Round, if needed */ + t += 1<<(Nhxn-1); + t >>= Nhxn; /* Leave some guard bits, but come back some */ + v += t; /* The filter output */ + Ho += dhb; /* IR step */ + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + } + } + else + { + while ((Hp = &Imp[Ho>>Na]) < End) + { + t = *Hp; /* Get IR sample */ + t *= *Xp; /* Mult coeff by input sample */ + if (t & 1<<(Nhxn-1)) /* Round, if needed */ + t += 1<<(Nhxn-1); + t >>= Nhxn; /* Leave some guard bits, but come back some */ + v += t; /* The filter output */ + Ho += dhb; /* IR step */ + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + } + } + return(v); +} + diff --git a/darkice/tags/darkice-1_3/src/aflibConverter.h b/darkice/tags/darkice-1_3/src/aflibConverter.h new file mode 100644 index 0000000..816bee6 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/aflibConverter.h @@ -0,0 +1,236 @@ +/* + * Copyright: (C) 2000 Julius O. Smith + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Julius O. Smith jos@ccrma.stanford.edu + * + */ +/* This code was modified by Bruce Forsberg (forsberg@tns.net) to make it + into a C++ class +*/ + + +#ifndef _AFLIBCONVERTER_H_ +#define _AFLIBCONVERTER_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef MAX +#define MAX(x,y) ((x)>(y) ?(x):(y)) +#endif +#ifndef MIN +#define MIN(x,y) ((x)<(y) ?(x):(y)) +#endif + +#define MAX_HWORD (32767) +#define MIN_HWORD (-32768) + +#define IBUFFSIZE 4096 /* Input buffer size */ + +/*! \class aflibConverter + \brief Provides sample rate conversion. + + This class will perform audio resampling. With the constructor you can choose the + type of resampling to be done. Simple linear interpolation can be done by setting + linear_interpolation to be TRUE in the constructor. The other two flags are + ignored if this is set. If linear_interpolation is FALSE then some form of filtering + will be done. IF high_quality is FALSE then a small filter will be performed. + If high_quality is TRUE then a large filter (higher quality) will be performed. For + both the small and large filters another parameter can be specified, filter_interpolation. + With filter_interpolation set then the filter coefficients used for both the small and + large filtering will be interpolated as well. + + This class was designed to stream audio data. It also expects audio data as 16 bit values. + Each time a new stream is started some initialization needs to be done. Thus the function + initialize should be called to initialize everything. This initialize function will set + the conversion factor as well as a multiplecation factor for volume. The volume only + applies to the small and large filter. Since this filter uses a history of the audio data + it is possible for it to vary in amplitude. This allows users to scale the data. This + class will work on any number of channels. Once everything is specified then resample + should be called as many times as is necessary to process all the data. The value + inCount will be returned indicating how many inArray samples were actually used to + produce the output. This value can be used to indicate where the next block of + inArray data should start. The resample function is driven by the outCount value + specified. The inArray should contain at least: + outCount / factor + extra_samples. + extra_samples depends on the type of filtering done. As a rule of thumb 50 should be + adequate for any type of filter. +*/ + +class aflibData; + +class aflibConverter { + +public: + + // Available contructors and destructors + aflibConverter ( + bool high_quality, + bool linear_interpolation, + bool filter_interpolation); + + ~aflibConverter(); + + void + initialize( + double factor, /* factor = Sndout/Sndin */ + int channels, /* number of sound channels */ + double volume = 1.0); /* factor to multiply amplitude */ + + int + resample( /* number of output samples returned */ + int& inCount, /* number of input samples to convert */ + int outCount, /* number of output samples to compute */ + short inArray[], /* input array data (length inCount * nChans) */ + short outArray[]);/* output array data (length outCount * nChans) */ + + +private: + + aflibConverter(); + + aflibConverter(const aflibConverter& op); + + const aflibConverter& + operator=(const aflibConverter& op); + + int + err_ret(const char *s); + + void + deleteMemory(); + + int + readData( + int inCount, /* _total_ number of frames in input file */ + short inArray[], /* input data */ + short *outPtr[], /* array receiving chan samps */ + int dataArraySize, /* size of these arrays */ + int Xoff, /* read into input array starting at this index */ + bool init_count); + + + inline short + WordToHword(int v, int scl) + { + short out; + int llsb = (1<<(scl-1)); + v += llsb; /* round */ + v >>= scl; + if (v>MAX_HWORD) { + v = MAX_HWORD; + } else if (v < MIN_HWORD) { + v = MIN_HWORD; + } + out = (short) v; + return out; + }; + + int + SrcLinear( + short X[], + short Y[], + double factor, + unsigned int *Time, + unsigned short& Nx, + unsigned short Nout); + + int + SrcUp( + short X[], + short Y[], + double factor, + unsigned int *Time, + unsigned short& Nx, + unsigned short Nout, + unsigned short Nwing, + unsigned short LpScl, + short Imp[], + short ImpD[], + bool Interp); + + int + SrcUD( + short X[], + short Y[], + double factor, + unsigned int *Time, + unsigned short& Nx, + unsigned short Nout, + unsigned short Nwing, + unsigned short LpScl, + short Imp[], + short ImpD[], + bool Interp); + + int + FilterUp( + short Imp[], + short ImpD[], + unsigned short Nwing, + bool Interp, + short *Xp, + short Ph, + short Inc); + + int + FilterUD( + short Imp[], + short ImpD[], + unsigned short Nwing, + bool Interp, + short *Xp, + short Ph, + short Inc, + unsigned short dhb); + + int + resampleFast( /* number of output samples returned */ + int& inCount, /* number of input samples to convert */ + int outCount, /* number of output samples to compute */ + short inArray[], /* input array data (length inCount * nChans) */ + short outArray[]);/* output array data (length outCount * nChans) */ + + int + resampleWithFilter( /* number of output samples returned */ + int& inCount, /* number of input samples to convert */ + int outCount, /* number of output samples to compute */ + short inArray[], /* input array data (length inCount * nChans) */ + short outArray[], /* output array data (length outCount * nChans) */ + short Imp[], short ImpD[], + unsigned short LpScl, unsigned short Nmult, unsigned short Nwing); + + +static short SMALL_FILTER_IMP[]; +static short LARGE_FILTER_IMP[]; + +bool interpFilt; +bool largeFilter; +bool linearInterp; +short ** _II; +short ** _JJ; +unsigned int _Time; +double _factor; +int _nChans; +bool _initial; +double _vol; + +}; + + +#endif diff --git a/darkice/tags/darkice-1_3/src/aflibConverterLargeFilter.h b/darkice/tags/darkice-1_3/src/aflibConverterLargeFilter.h new file mode 100644 index 0000000..5d5b05b --- /dev/null +++ b/darkice/tags/darkice-1_3/src/aflibConverterLargeFilter.h @@ -0,0 +1,16432 @@ +/* + * Copyright: (C) 2000 Julius O. Smith + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Julius O. Smith jos@ccrma.stanford.edu + * + */ + +/* + +The default filter requires an +oversampling factor of around 20% to avoid aliasing. The expensive +filter is five times more computationally expensive and requires only +about a 5-10% oversampling factor. Both filters have comparable +stop-band attenuations (approximately 80 dB). The +expensive filter is not yet documented because its cut-off frequency +should be retuned slightly for optimal performance. Also, we plan to +compute truly optimized resampling filters sometime in the future. In +the meantime, the default filter is fast, well tuned, and works very +well for its level of computational expense. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + + +#define LARGE_FILTER_NMULT ((short)65) +#define LARGE_FILTER_SCALE 14746 /* Unity-gain scale factor */ +#define LARGE_FILTER_NWING 8192 /* Filter table length */ + +short aflibConverter::LARGE_FILTER_IMP[] /* Impulse response */ = { +32767, +32766, +32764, +32761, +32756, +32750, +32743, +32734, +32724, +32713, +32700, +32686, +32671, +32654, +32636, +32617, +32596, +32574, +32551, +32526, +32500, +32473, +32445, +32415, +32383, +32351, +32317, +32282, +32246, +32208, +32169, +32129, +32087, +32044, +32000, +31955, +31908, +31860, +31811, +31760, +31708, +31655, +31601, +31545, +31489, +31431, +31371, +31311, +31249, +31186, +31122, +31056, +30990, +30922, +30853, +30783, +30711, +30639, +30565, +30490, +30414, +30337, +30258, +30179, +30098, +30016, +29933, +29849, +29764, +29677, +29590, +29501, +29411, +29321, +29229, +29136, +29042, +28947, +28851, +28753, +28655, +28556, +28456, +28354, +28252, +28149, +28044, +27939, +27833, +27725, +27617, +27508, +27398, +27287, +27175, +27062, +26948, +26833, +26717, +26601, +26483, +26365, +26246, +26125, +26005, +25883, +25760, +25637, +25512, +25387, +25261, +25135, +25007, +24879, +24750, +24620, +24490, +24358, +24226, +24094, +23960, +23826, +23691, +23556, +23420, +23283, +23146, +23008, +22869, +22730, +22590, +22449, +22308, +22166, +22024, +21881, +21738, +21594, +21449, +21304, +21159, +21013, +20866, +20719, +20572, +20424, +20275, +20127, +19977, +19828, +19678, +19527, +19376, +19225, +19073, +18921, +18769, +18616, +18463, +18310, +18157, +18003, +17849, +17694, +17539, +17384, +17229, +17074, +16918, +16762, +16606, +16450, +16294, +16137, +15980, +15823, +15666, +15509, +15352, +15195, +15037, +14880, +14722, +14564, +14407, +14249, +14091, +13933, +13775, +13618, +13460, +13302, +13144, +12987, +12829, +12671, +12514, +12356, +12199, +12042, +11885, +11728, +11571, +11414, +11257, +11101, +10945, +10789, +10633, +10477, +10322, +10167, +10012, +9857, +9702, +9548, +9394, +9241, +9087, +8934, +8781, +8629, +8477, +8325, +8174, +8023, +7872, +7722, +7572, +7422, +7273, +7124, +6976, +6828, +6681, +6534, +6387, +6241, +6096, +5951, +5806, +5662, +5518, +5375, +5233, +5091, +4949, +4808, +4668, +4528, +4389, +4250, +4112, +3975, +3838, +3702, +3566, +3431, +3297, +3163, +3030, +2898, +2766, +2635, +2505, +2375, +2246, +2118, +1990, +1864, +1738, +1612, +1487, +1364, +1240, +1118, +996, +875, +755, +636, +517, +400, +283, +166, +51, +-63, +-176, +-289, +-401, +-513, +-623, +-733, +-841, +-949, +-1056, +-1162, +-1268, +-1372, +-1476, +-1578, +-1680, +-1781, +-1881, +-1980, +-2078, +-2176, +-2272, +-2367, +-2462, +-2556, +-2648, +-2740, +-2831, +-2921, +-3010, +-3098, +-3185, +-3271, +-3356, +-3441, +-3524, +-3606, +-3688, +-3768, +-3848, +-3926, +-4004, +-4080, +-4156, +-4231, +-4304, +-4377, +-4449, +-4519, +-4589, +-4658, +-4726, +-4792, +-4858, +-4923, +-4987, +-5050, +-5111, +-5172, +-5232, +-5291, +-5349, +-5406, +-5462, +-5517, +-5571, +-5624, +-5675, +-5726, +-5776, +-5825, +-5873, +-5920, +-5966, +-6011, +-6055, +-6098, +-6140, +-6181, +-6222, +-6261, +-6299, +-6336, +-6372, +-6407, +-6441, +-6475, +-6507, +-6538, +-6569, +-6598, +-6626, +-6654, +-6680, +-6706, +-6730, +-6754, +-6777, +-6798, +-6819, +-6839, +-6858, +-6876, +-6893, +-6909, +-6924, +-6938, +-6951, +-6964, +-6975, +-6986, +-6995, +-7004, +-7012, +-7019, +-7025, +-7030, +-7035, +-7038, +-7040, +-7042, +-7043, +-7043, +-7042, +-7040, +-7038, +-7034, +-7030, +-7025, +-7019, +-7012, +-7004, +-6996, +-6986, +-6976, +-6965, +-6954, +-6941, +-6928, +-6914, +-6899, +-6884, +-6867, +-6850, +-6832, +-6814, +-6794, +-6774, +-6753, +-6732, +-6709, +-6686, +-6663, +-6638, +-6613, +-6587, +-6561, +-6534, +-6506, +-6478, +-6448, +-6419, +-6388, +-6357, +-6325, +-6293, +-6260, +-6226, +-6192, +-6157, +-6122, +-6086, +-6049, +-6012, +-5975, +-5936, +-5897, +-5858, +-5818, +-5778, +-5737, +-5695, +-5653, +-5611, +-5568, +-5524, +-5480, +-5436, +-5391, +-5345, +-5300, +-5253, +-5207, +-5159, +-5112, +-5064, +-5015, +-4966, +-4917, +-4868, +-4818, +-4767, +-4716, +-4665, +-4614, +-4562, +-4510, +-4457, +-4404, +-4351, +-4298, +-4244, +-4190, +-4136, +-4081, +-4026, +-3971, +-3916, +-3860, +-3804, +-3748, +-3692, +-3635, +-3578, +-3521, +-3464, +-3406, +-3349, +-3291, +-3233, +-3175, +-3117, +-3058, +-3000, +-2941, +-2882, +-2823, +-2764, +-2705, +-2646, +-2587, +-2527, +-2468, +-2408, +-2349, +-2289, +-2229, +-2169, +-2110, +-2050, +-1990, +-1930, +-1870, +-1811, +-1751, +-1691, +-1631, +-1571, +-1512, +-1452, +-1392, +-1333, +-1273, +-1214, +-1154, +-1095, +-1036, +-977, +-918, +-859, +-800, +-741, +-683, +-624, +-566, +-508, +-450, +-392, +-335, +-277, +-220, +-163, +-106, +-49, +6, +63, +119, +175, +230, +286, +341, +396, +450, +505, +559, +613, +667, +720, +773, +826, +878, +931, +983, +1034, +1086, +1137, +1187, +1238, +1288, +1337, +1387, +1436, +1484, +1533, +1581, +1628, +1675, +1722, +1769, +1815, +1861, +1906, +1951, +1996, +2040, +2084, +2127, +2170, +2212, +2255, +2296, +2338, +2378, +2419, +2459, +2498, +2538, +2576, +2615, +2652, +2690, +2727, +2763, +2799, +2834, +2870, +2904, +2938, +2972, +3005, +3038, +3070, +3102, +3133, +3164, +3194, +3224, +3253, +3282, +3310, +3338, +3365, +3392, +3418, +3444, +3469, +3494, +3518, +3542, +3566, +3588, +3611, +3632, +3653, +3674, +3694, +3714, +3733, +3752, +3770, +3788, +3805, +3821, +3837, +3853, +3868, +3882, +3896, +3910, +3923, +3935, +3947, +3958, +3969, +3980, +3989, +3999, +4007, +4016, +4023, +4031, +4037, +4044, +4049, +4054, +4059, +4063, +4067, +4070, +4073, +4075, +4076, +4077, +4078, +4078, +4078, +4077, +4076, +4074, +4071, +4068, +4065, +4061, +4057, +4052, +4047, +4041, +4035, +4028, +4021, +4013, +4005, +3997, +3988, +3978, +3968, +3958, +3947, +3936, +3924, +3912, +3899, +3886, +3872, +3858, +3844, +3829, +3814, +3798, +3782, +3766, +3749, +3731, +3714, +3696, +3677, +3658, +3639, +3619, +3599, +3578, +3558, +3536, +3515, +3493, +3470, +3448, +3425, +3401, +3378, +3353, +3329, +3304, +3279, +3254, +3228, +3202, +3175, +3149, +3122, +3094, +3067, +3039, +3011, +2982, +2953, +2924, +2895, +2865, +2835, +2805, +2775, +2744, +2713, +2682, +2651, +2619, +2587, +2555, +2523, +2490, +2457, +2424, +2391, +2358, +2324, +2290, +2256, +2222, +2188, +2153, +2119, +2084, +2049, +2014, +1978, +1943, +1907, +1872, +1836, +1800, +1764, +1727, +1691, +1655, +1618, +1581, +1545, +1508, +1471, +1434, +1397, +1360, +1322, +1285, +1248, +1210, +1173, +1135, +1098, +1060, +1023, +985, +947, +910, +872, +834, +797, +759, +721, +684, +646, +608, +571, +533, +496, +458, +421, +383, +346, +308, +271, +234, +197, +160, +123, +86, +49, +12, +-23, +-60, +-96, +-133, +-169, +-205, +-241, +-277, +-313, +-348, +-384, +-419, +-455, +-490, +-525, +-559, +-594, +-628, +-663, +-697, +-731, +-765, +-798, +-832, +-865, +-898, +-931, +-963, +-996, +-1028, +-1060, +-1092, +-1124, +-1155, +-1186, +-1217, +-1248, +-1279, +-1309, +-1339, +-1369, +-1398, +-1428, +-1457, +-1486, +-1514, +-1542, +-1571, +-1598, +-1626, +-1653, +-1680, +-1707, +-1733, +-1760, +-1785, +-1811, +-1836, +-1862, +-1886, +-1911, +-1935, +-1959, +-1982, +-2006, +-2029, +-2051, +-2074, +-2096, +-2118, +-2139, +-2160, +-2181, +-2202, +-2222, +-2242, +-2261, +-2280, +-2299, +-2318, +-2336, +-2354, +-2372, +-2389, +-2406, +-2423, +-2439, +-2455, +-2470, +-2486, +-2500, +-2515, +-2529, +-2543, +-2557, +-2570, +-2583, +-2595, +-2607, +-2619, +-2631, +-2642, +-2652, +-2663, +-2673, +-2683, +-2692, +-2701, +-2710, +-2718, +-2726, +-2734, +-2741, +-2748, +-2754, +-2760, +-2766, +-2772, +-2777, +-2782, +-2786, +-2790, +-2794, +-2797, +-2800, +-2803, +-2805, +-2807, +-2809, +-2810, +-2811, +-2812, +-2812, +-2812, +-2812, +-2811, +-2810, +-2808, +-2807, +-2804, +-2802, +-2799, +-2796, +-2792, +-2789, +-2785, +-2780, +-2775, +-2770, +-2765, +-2759, +-2753, +-2746, +-2740, +-2732, +-2725, +-2717, +-2709, +-2701, +-2692, +-2683, +-2674, +-2664, +-2655, +-2644, +-2634, +-2623, +-2612, +-2601, +-2589, +-2577, +-2565, +-2552, +-2539, +-2526, +-2513, +-2499, +-2485, +-2471, +-2457, +-2442, +-2427, +-2412, +-2396, +-2380, +-2364, +-2348, +-2331, +-2315, +-2297, +-2280, +-2263, +-2245, +-2227, +-2209, +-2190, +-2171, +-2152, +-2133, +-2114, +-2094, +-2075, +-2055, +-2034, +-2014, +-1993, +-1972, +-1951, +-1930, +-1909, +-1887, +-1865, +-1843, +-1821, +-1799, +-1776, +-1754, +-1731, +-1708, +-1685, +-1662, +-1638, +-1614, +-1591, +-1567, +-1543, +-1519, +-1494, +-1470, +-1445, +-1421, +-1396, +-1371, +-1346, +-1321, +-1295, +-1270, +-1244, +-1219, +-1193, +-1167, +-1142, +-1116, +-1090, +-1064, +-1037, +-1011, +-985, +-958, +-932, +-905, +-879, +-852, +-826, +-799, +-772, +-745, +-719, +-692, +-665, +-638, +-611, +-584, +-557, +-530, +-503, +-476, +-449, +-422, +-395, +-368, +-341, +-314, +-287, +-260, +-234, +-207, +-180, +-153, +-126, +-100, +-73, +-46, +-20, +6, +32, +59, +85, +111, +138, +164, +190, +216, +242, +268, +294, +319, +345, +370, +396, +421, +446, +471, +496, +521, +546, +571, +595, +619, +644, +668, +692, +716, +739, +763, +787, +810, +833, +856, +879, +902, +924, +947, +969, +991, +1013, +1035, +1056, +1078, +1099, +1120, +1141, +1162, +1182, +1202, +1223, +1243, +1262, +1282, +1301, +1320, +1339, +1358, +1377, +1395, +1413, +1431, +1449, +1467, +1484, +1501, +1518, +1535, +1551, +1567, +1583, +1599, +1615, +1630, +1645, +1660, +1674, +1689, +1703, +1717, +1731, +1744, +1757, +1770, +1783, +1795, +1808, +1820, +1831, +1843, +1854, +1865, +1876, +1886, +1897, +1907, +1916, +1926, +1935, +1944, +1953, +1961, +1970, +1978, +1985, +1993, +2000, +2007, +2014, +2020, +2026, +2032, +2038, +2043, +2048, +2053, +2058, +2062, +2066, +2070, +2073, +2077, +2080, +2083, +2085, +2087, +2089, +2091, +2093, +2094, +2095, +2095, +2096, +2096, +2096, +2096, +2095, +2094, +2093, +2092, +2090, +2088, +2086, +2084, +2081, +2079, +2075, +2072, +2069, +2065, +2061, +2056, +2052, +2047, +2042, +2037, +2031, +2025, +2019, +2013, +2006, +2000, +1993, +1986, +1978, +1971, +1963, +1955, +1946, +1938, +1929, +1920, +1911, +1901, +1892, +1882, +1872, +1862, +1851, +1841, +1830, +1819, +1807, +1796, +1784, +1772, +1760, +1748, +1735, +1723, +1710, +1697, +1684, +1670, +1657, +1643, +1629, +1615, +1601, +1586, +1572, +1557, +1542, +1527, +1512, +1496, +1481, +1465, +1449, +1433, +1417, +1401, +1384, +1368, +1351, +1334, +1317, +1300, +1283, +1265, +1248, +1230, +1212, +1195, +1177, +1159, +1140, +1122, +1104, +1085, +1067, +1048, +1029, +1010, +991, +972, +953, +934, +915, +895, +876, +856, +837, +817, +797, +777, +758, +738, +718, +698, +678, +658, +637, +617, +597, +577, +556, +536, +516, +495, +475, +454, +434, +414, +393, +373, +352, +332, +311, +291, +270, +250, +229, +208, +188, +168, +147, +127, +106, +86, +65, +45, +25, +5, +-15, +-35, +-55, +-75, +-95, +-115, +-135, +-155, +-175, +-195, +-215, +-234, +-254, +-274, +-293, +-313, +-332, +-351, +-370, +-390, +-409, +-428, +-446, +-465, +-484, +-503, +-521, +-539, +-558, +-576, +-594, +-612, +-630, +-648, +-666, +-683, +-701, +-718, +-735, +-752, +-769, +-786, +-803, +-819, +-836, +-852, +-868, +-885, +-900, +-916, +-932, +-947, +-963, +-978, +-993, +-1008, +-1023, +-1038, +-1052, +-1066, +-1081, +-1095, +-1108, +-1122, +-1136, +-1149, +-1162, +-1175, +-1188, +-1201, +-1214, +-1226, +-1238, +-1250, +-1262, +-1274, +-1285, +-1297, +-1308, +-1319, +-1330, +-1340, +-1351, +-1361, +-1371, +-1381, +-1390, +-1400, +-1409, +-1418, +-1427, +-1436, +-1445, +-1453, +-1461, +-1469, +-1477, +-1485, +-1492, +-1499, +-1506, +-1513, +-1520, +-1526, +-1532, +-1538, +-1544, +-1550, +-1555, +-1560, +-1566, +-1570, +-1575, +-1579, +-1584, +-1588, +-1592, +-1595, +-1599, +-1602, +-1605, +-1608, +-1610, +-1613, +-1615, +-1617, +-1619, +-1620, +-1622, +-1623, +-1624, +-1625, +-1625, +-1626, +-1626, +-1626, +-1626, +-1625, +-1625, +-1624, +-1623, +-1622, +-1621, +-1619, +-1617, +-1615, +-1613, +-1611, +-1608, +-1605, +-1603, +-1599, +-1596, +-1593, +-1589, +-1585, +-1581, +-1577, +-1572, +-1568, +-1563, +-1558, +-1553, +-1547, +-1542, +-1536, +-1530, +-1524, +-1518, +-1511, +-1505, +-1498, +-1491, +-1484, +-1477, +-1469, +-1462, +-1454, +-1446, +-1438, +-1430, +-1421, +-1413, +-1404, +-1395, +-1386, +-1377, +-1367, +-1358, +-1348, +-1338, +-1328, +-1318, +-1308, +-1297, +-1287, +-1276, +-1265, +-1254, +-1243, +-1232, +-1221, +-1209, +-1198, +-1186, +-1174, +-1162, +-1150, +-1138, +-1125, +-1113, +-1100, +-1087, +-1075, +-1062, +-1049, +-1035, +-1022, +-1009, +-995, +-982, +-968, +-954, +-941, +-927, +-913, +-898, +-884, +-870, +-856, +-841, +-827, +-812, +-797, +-783, +-768, +-753, +-738, +-723, +-708, +-692, +-677, +-662, +-647, +-631, +-616, +-600, +-585, +-569, +-554, +-538, +-522, +-506, +-491, +-475, +-459, +-443, +-427, +-411, +-395, +-379, +-363, +-347, +-331, +-315, +-299, +-283, +-267, +-251, +-235, +-218, +-202, +-186, +-170, +-154, +-138, +-122, +-106, +-90, +-74, +-58, +-42, +-26, +-10, +5, +21, +37, +53, +69, +85, +100, +116, +132, +147, +163, +179, +194, +209, +225, +240, +256, +271, +286, +301, +316, +331, +346, +361, +376, +391, +405, +420, +434, +449, +463, +477, +492, +506, +520, +534, +548, +561, +575, +589, +602, +615, +629, +642, +655, +668, +681, +694, +706, +719, +731, +744, +756, +768, +780, +792, +804, +816, +827, +839, +850, +861, +872, +883, +894, +905, +915, +926, +936, +946, +956, +966, +976, +986, +995, +1005, +1014, +1023, +1032, +1041, +1049, +1058, +1066, +1075, +1083, +1091, +1099, +1106, +1114, +1121, +1128, +1135, +1142, +1149, +1156, +1162, +1169, +1175, +1181, +1187, +1192, +1198, +1203, +1208, +1214, +1218, +1223, +1228, +1232, +1237, +1241, +1245, +1249, +1252, +1256, +1259, +1262, +1265, +1268, +1271, +1273, +1276, +1278, +1280, +1282, +1284, +1285, +1287, +1288, +1289, +1290, +1291, +1292, +1292, +1292, +1293, +1293, +1292, +1292, +1292, +1291, +1290, +1289, +1288, +1287, +1285, +1284, +1282, +1280, +1278, +1276, +1274, +1271, +1269, +1266, +1263, +1260, +1257, +1253, +1250, +1246, +1242, +1238, +1234, +1230, +1225, +1221, +1216, +1211, +1206, +1201, +1196, +1190, +1185, +1179, +1173, +1167, +1161, +1155, +1149, +1142, +1136, +1129, +1122, +1115, +1108, +1101, +1094, +1086, +1078, +1071, +1063, +1055, +1047, +1039, +1030, +1022, +1013, +1005, +996, +987, +978, +969, +960, +951, +941, +932, +922, +913, +903, +893, +883, +873, +863, +853, +842, +832, +821, +811, +800, +789, +778, +768, +757, +746, +734, +723, +712, +701, +689, +678, +666, +654, +643, +631, +619, +607, +596, +584, +572, +559, +547, +535, +523, +511, +498, +486, +474, +461, +449, +436, +424, +411, +399, +386, +373, +361, +348, +335, +322, +310, +297, +284, +271, +258, +246, +233, +220, +207, +194, +181, +168, +156, +143, +130, +117, +104, +91, +78, +65, +53, +40, +27, +14, +1, +-10, +-23, +-36, +-48, +-61, +-74, +-86, +-99, +-111, +-124, +-136, +-149, +-161, +-174, +-186, +-198, +-211, +-223, +-235, +-247, +-259, +-271, +-283, +-295, +-307, +-319, +-330, +-342, +-354, +-365, +-377, +-388, +-399, +-411, +-422, +-433, +-444, +-455, +-466, +-477, +-488, +-499, +-509, +-520, +-530, +-541, +-551, +-561, +-571, +-581, +-591, +-601, +-611, +-621, +-631, +-640, +-650, +-659, +-668, +-677, +-686, +-695, +-704, +-713, +-722, +-730, +-739, +-747, +-755, +-763, +-771, +-779, +-787, +-795, +-803, +-810, +-817, +-825, +-832, +-839, +-846, +-853, +-859, +-866, +-873, +-879, +-885, +-891, +-897, +-903, +-909, +-915, +-920, +-926, +-931, +-936, +-941, +-946, +-951, +-955, +-960, +-964, +-969, +-973, +-977, +-981, +-985, +-988, +-992, +-995, +-999, +-1002, +-1005, +-1008, +-1011, +-1013, +-1016, +-1018, +-1020, +-1023, +-1025, +-1026, +-1028, +-1030, +-1031, +-1033, +-1034, +-1035, +-1036, +-1037, +-1038, +-1038, +-1039, +-1039, +-1039, +-1039, +-1039, +-1039, +-1039, +-1038, +-1038, +-1037, +-1036, +-1036, +-1034, +-1033, +-1032, +-1031, +-1029, +-1027, +-1026, +-1024, +-1022, +-1019, +-1017, +-1015, +-1012, +-1010, +-1007, +-1004, +-1001, +-998, +-995, +-991, +-988, +-984, +-980, +-977, +-973, +-969, +-965, +-960, +-956, +-951, +-947, +-942, +-937, +-932, +-927, +-922, +-917, +-912, +-906, +-901, +-895, +-889, +-883, +-877, +-871, +-865, +-859, +-853, +-846, +-840, +-833, +-826, +-819, +-812, +-805, +-798, +-791, +-784, +-777, +-769, +-762, +-754, +-746, +-739, +-731, +-723, +-715, +-707, +-699, +-691, +-682, +-674, +-665, +-657, +-648, +-640, +-631, +-622, +-614, +-605, +-596, +-587, +-578, +-569, +-559, +-550, +-541, +-532, +-522, +-513, +-503, +-494, +-484, +-474, +-465, +-455, +-445, +-436, +-426, +-416, +-406, +-396, +-386, +-376, +-366, +-356, +-346, +-336, +-325, +-315, +-305, +-295, +-285, +-274, +-264, +-254, +-243, +-233, +-223, +-212, +-202, +-192, +-181, +-171, +-161, +-150, +-140, +-129, +-119, +-108, +-98, +-88, +-77, +-67, +-57, +-46, +-36, +-25, +-15, +-5, +5, +15, +25, +35, +46, +56, +66, +76, +86, +97, +107, +117, +127, +137, +147, +157, +167, +177, +186, +196, +206, +216, +225, +235, +245, +254, +264, +273, +283, +292, +301, +311, +320, +329, +338, +347, +356, +365, +374, +383, +392, +400, +409, +418, +426, +435, +443, +451, +460, +468, +476, +484, +492, +500, +508, +515, +523, +531, +538, +546, +553, +560, +568, +575, +582, +589, +596, +602, +609, +616, +622, +629, +635, +642, +648, +654, +660, +666, +672, +678, +683, +689, +694, +700, +705, +710, +715, +720, +725, +730, +735, +739, +744, +748, +753, +757, +761, +765, +769, +773, +777, +780, +784, +787, +791, +794, +797, +800, +803, +806, +809, +811, +814, +816, +818, +821, +823, +825, +827, +828, +830, +832, +833, +835, +836, +837, +838, +839, +840, +841, +841, +842, +842, +843, +843, +843, +843, +843, +843, +843, +842, +842, +841, +840, +840, +839, +838, +837, +835, +834, +833, +831, +830, +828, +826, +824, +822, +820, +818, +816, +813, +811, +808, +806, +803, +800, +797, +794, +791, +788, +784, +781, +777, +774, +770, +766, +763, +759, +755, +750, +746, +742, +738, +733, +729, +724, +719, +714, +710, +705, +700, +694, +689, +684, +679, +673, +668, +662, +657, +651, +645, +639, +633, +627, +621, +615, +609, +603, +596, +590, +584, +577, +571, +564, +557, +551, +544, +537, +530, +523, +516, +509, +502, +495, +487, +480, +473, +465, +458, +450, +443, +435, +428, +420, +413, +405, +397, +389, +381, +374, +366, +358, +350, +342, +334, +326, +318, +310, +301, +293, +285, +277, +269, +260, +252, +244, +236, +227, +219, +211, +202, +194, +185, +177, +169, +160, +152, +143, +135, +126, +118, +110, +101, +93, +84, +76, +67, +59, +50, +42, +34, +25, +17, +8, +0, +-7, +-16, +-24, +-32, +-41, +-49, +-57, +-66, +-74, +-82, +-90, +-98, +-106, +-115, +-123, +-131, +-139, +-147, +-155, +-163, +-171, +-179, +-186, +-194, +-202, +-210, +-217, +-225, +-233, +-240, +-248, +-255, +-263, +-270, +-278, +-285, +-292, +-299, +-307, +-314, +-321, +-328, +-335, +-342, +-349, +-356, +-362, +-369, +-376, +-382, +-389, +-396, +-402, +-408, +-415, +-421, +-427, +-433, +-439, +-445, +-451, +-457, +-463, +-469, +-475, +-480, +-486, +-491, +-497, +-502, +-507, +-513, +-518, +-523, +-528, +-533, +-538, +-542, +-547, +-552, +-556, +-561, +-565, +-570, +-574, +-578, +-582, +-586, +-590, +-594, +-598, +-602, +-605, +-609, +-612, +-616, +-619, +-622, +-625, +-629, +-632, +-634, +-637, +-640, +-643, +-645, +-648, +-650, +-653, +-655, +-657, +-659, +-661, +-663, +-665, +-667, +-668, +-670, +-671, +-673, +-674, +-675, +-676, +-678, +-679, +-679, +-680, +-681, +-682, +-682, +-683, +-683, +-683, +-684, +-684, +-684, +-684, +-684, +-684, +-683, +-683, +-682, +-682, +-681, +-681, +-680, +-679, +-678, +-677, +-676, +-675, +-674, +-672, +-671, +-669, +-668, +-666, +-664, +-662, +-661, +-659, +-657, +-654, +-652, +-650, +-648, +-645, +-643, +-640, +-637, +-635, +-632, +-629, +-626, +-623, +-620, +-617, +-613, +-610, +-607, +-603, +-600, +-596, +-593, +-589, +-585, +-581, +-577, +-573, +-569, +-565, +-561, +-557, +-552, +-548, +-544, +-539, +-534, +-530, +-525, +-520, +-516, +-511, +-506, +-501, +-496, +-491, +-486, +-481, +-475, +-470, +-465, +-460, +-454, +-449, +-443, +-438, +-432, +-426, +-421, +-415, +-409, +-403, +-398, +-392, +-386, +-380, +-374, +-368, +-362, +-355, +-349, +-343, +-337, +-331, +-324, +-318, +-312, +-305, +-299, +-292, +-286, +-280, +-273, +-266, +-260, +-253, +-247, +-240, +-234, +-227, +-220, +-213, +-207, +-200, +-193, +-187, +-180, +-173, +-166, +-159, +-153, +-146, +-139, +-132, +-125, +-118, +-112, +-105, +-98, +-91, +-84, +-77, +-70, +-64, +-57, +-50, +-43, +-36, +-29, +-22, +-16, +-9, +-2, +4, +11, +17, +24, +31, +38, +44, +51, +58, +64, +71, +78, +84, +91, +98, +104, +111, +117, +124, +130, +137, +143, +149, +156, +162, +168, +175, +181, +187, +193, +199, +205, +212, +218, +224, +230, +236, +241, +247, +253, +259, +265, +270, +276, +282, +287, +293, +298, +304, +309, +314, +320, +325, +330, +335, +340, +345, +350, +355, +360, +365, +370, +375, +380, +384, +389, +393, +398, +402, +407, +411, +415, +419, +424, +428, +432, +436, +440, +443, +447, +451, +455, +458, +462, +465, +469, +472, +475, +479, +482, +485, +488, +491, +494, +497, +499, +502, +505, +507, +510, +512, +515, +517, +519, +522, +524, +526, +528, +530, +532, +533, +535, +537, +538, +540, +541, +543, +544, +545, +546, +548, +549, +550, +550, +551, +552, +553, +553, +554, +554, +555, +555, +555, +556, +556, +556, +556, +556, +556, +555, +555, +555, +554, +554, +553, +553, +552, +551, +551, +550, +549, +548, +547, +546, +545, +543, +542, +541, +539, +538, +536, +534, +533, +531, +529, +527, +525, +523, +521, +519, +517, +514, +512, +510, +507, +505, +502, +500, +497, +494, +492, +489, +486, +483, +480, +477, +474, +471, +467, +464, +461, +457, +454, +450, +447, +443, +440, +436, +432, +429, +425, +421, +417, +413, +409, +405, +401, +397, +393, +388, +384, +380, +375, +371, +367, +362, +358, +353, +349, +344, +339, +335, +330, +325, +321, +316, +311, +306, +301, +296, +291, +286, +281, +276, +271, +266, +261, +256, +251, +245, +240, +235, +230, +225, +219, +214, +209, +203, +198, +193, +187, +182, +176, +171, +165, +160, +154, +149, +144, +138, +132, +127, +121, +116, +110, +105, +99, +94, +88, +83, +77, +71, +66, +60, +55, +49, +44, +38, +33, +27, +21, +16, +10, +5, +0, +-5, +-11, +-16, +-22, +-27, +-33, +-38, +-43, +-49, +-54, +-60, +-65, +-70, +-76, +-81, +-86, +-92, +-97, +-102, +-107, +-113, +-118, +-123, +-128, +-133, +-138, +-143, +-148, +-153, +-158, +-163, +-168, +-173, +-178, +-183, +-188, +-192, +-197, +-202, +-207, +-211, +-216, +-221, +-225, +-230, +-234, +-239, +-243, +-247, +-252, +-256, +-260, +-265, +-269, +-273, +-277, +-281, +-285, +-289, +-293, +-297, +-301, +-305, +-308, +-312, +-316, +-319, +-323, +-327, +-330, +-334, +-337, +-340, +-344, +-347, +-350, +-353, +-357, +-360, +-363, +-366, +-369, +-372, +-374, +-377, +-380, +-383, +-385, +-388, +-390, +-393, +-395, +-398, +-400, +-402, +-405, +-407, +-409, +-411, +-413, +-415, +-417, +-419, +-420, +-422, +-424, +-425, +-427, +-429, +-430, +-431, +-433, +-434, +-435, +-436, +-438, +-439, +-440, +-441, +-442, +-442, +-443, +-444, +-445, +-445, +-446, +-446, +-447, +-447, +-448, +-448, +-448, +-448, +-449, +-449, +-449, +-449, +-449, +-448, +-448, +-448, +-448, +-447, +-447, +-446, +-446, +-445, +-445, +-444, +-443, +-442, +-442, +-441, +-440, +-439, +-438, +-437, +-435, +-434, +-433, +-432, +-430, +-429, +-427, +-426, +-424, +-423, +-421, +-419, +-418, +-416, +-414, +-412, +-410, +-408, +-406, +-404, +-402, +-400, +-397, +-395, +-393, +-390, +-388, +-385, +-383, +-380, +-378, +-375, +-373, +-370, +-367, +-364, +-361, +-359, +-356, +-353, +-350, +-347, +-344, +-340, +-337, +-334, +-331, +-328, +-324, +-321, +-318, +-314, +-311, +-307, +-304, +-300, +-297, +-293, +-290, +-286, +-282, +-279, +-275, +-271, +-267, +-263, +-260, +-256, +-252, +-248, +-244, +-240, +-236, +-232, +-228, +-224, +-220, +-216, +-212, +-207, +-203, +-199, +-195, +-191, +-186, +-182, +-178, +-174, +-169, +-165, +-161, +-156, +-152, +-148, +-143, +-139, +-134, +-130, +-126, +-121, +-117, +-112, +-108, +-103, +-99, +-95, +-90, +-86, +-81, +-77, +-72, +-68, +-63, +-59, +-54, +-50, +-45, +-41, +-36, +-32, +-27, +-23, +-18, +-14, +-9, +-5, +0, +3, +7, +12, +16, +21, +25, +29, +34, +38, +43, +47, +51, +56, +60, +64, +69, +73, +77, +81, +85, +90, +94, +98, +102, +106, +110, +115, +119, +123, +127, +131, +135, +139, +143, +146, +150, +154, +158, +162, +166, +169, +173, +177, +181, +184, +188, +192, +195, +199, +202, +206, +209, +212, +216, +219, +223, +226, +229, +232, +236, +239, +242, +245, +248, +251, +254, +257, +260, +263, +266, +268, +271, +274, +277, +279, +282, +284, +287, +289, +292, +294, +297, +299, +301, +304, +306, +308, +310, +312, +314, +316, +318, +320, +322, +324, +326, +328, +329, +331, +333, +334, +336, +337, +339, +340, +341, +343, +344, +345, +346, +348, +349, +350, +351, +352, +353, +354, +354, +355, +356, +357, +357, +358, +358, +359, +359, +360, +360, +361, +361, +361, +361, +362, +362, +362, +362, +362, +362, +362, +361, +361, +361, +361, +360, +360, +360, +359, +359, +358, +358, +357, +356, +356, +355, +354, +353, +352, +351, +350, +349, +348, +347, +346, +345, +344, +343, +341, +340, +339, +337, +336, +334, +333, +331, +330, +328, +326, +324, +323, +321, +319, +317, +315, +313, +311, +309, +307, +305, +303, +301, +299, +297, +294, +292, +290, +288, +285, +283, +280, +278, +275, +273, +270, +268, +265, +263, +260, +257, +254, +252, +249, +246, +243, +240, +238, +235, +232, +229, +226, +223, +220, +217, +214, +211, +208, +204, +201, +198, +195, +192, +188, +185, +182, +179, +175, +172, +169, +165, +162, +159, +155, +152, +149, +145, +142, +138, +135, +131, +128, +124, +121, +117, +114, +110, +107, +103, +100, +96, +93, +89, +85, +82, +78, +75, +71, +67, +64, +60, +57, +53, +49, +46, +42, +39, +35, +31, +28, +24, +21, +17, +14, +10, +6, +3, +0, +-3, +-7, +-10, +-14, +-18, +-21, +-25, +-28, +-32, +-35, +-39, +-42, +-45, +-49, +-52, +-56, +-59, +-63, +-66, +-69, +-73, +-76, +-79, +-83, +-86, +-89, +-93, +-96, +-99, +-102, +-105, +-109, +-112, +-115, +-118, +-121, +-124, +-127, +-130, +-133, +-136, +-139, +-142, +-145, +-148, +-151, +-154, +-157, +-160, +-162, +-165, +-168, +-171, +-173, +-176, +-179, +-181, +-184, +-186, +-189, +-191, +-194, +-196, +-199, +-201, +-204, +-206, +-208, +-211, +-213, +-215, +-217, +-219, +-221, +-224, +-226, +-228, +-230, +-232, +-234, +-236, +-237, +-239, +-241, +-243, +-245, +-246, +-248, +-250, +-251, +-253, +-254, +-256, +-257, +-259, +-260, +-262, +-263, +-264, +-266, +-267, +-268, +-269, +-270, +-271, +-273, +-274, +-275, +-275, +-276, +-277, +-278, +-279, +-280, +-281, +-281, +-282, +-283, +-283, +-284, +-284, +-285, +-285, +-286, +-286, +-286, +-287, +-287, +-287, +-287, +-288, +-288, +-288, +-288, +-288, +-288, +-288, +-288, +-288, +-288, +-287, +-287, +-287, +-287, +-286, +-286, +-286, +-285, +-285, +-284, +-284, +-283, +-283, +-282, +-281, +-281, +-280, +-279, +-278, +-277, +-277, +-276, +-275, +-274, +-273, +-272, +-271, +-270, +-269, +-267, +-266, +-265, +-264, +-262, +-261, +-260, +-258, +-257, +-256, +-254, +-253, +-251, +-250, +-248, +-247, +-245, +-243, +-242, +-240, +-238, +-236, +-235, +-233, +-231, +-229, +-227, +-225, +-223, +-221, +-219, +-217, +-215, +-213, +-211, +-209, +-207, +-205, +-203, +-201, +-198, +-196, +-194, +-192, +-189, +-187, +-185, +-182, +-180, +-178, +-175, +-173, +-170, +-168, +-165, +-163, +-160, +-158, +-155, +-153, +-150, +-148, +-145, +-142, +-140, +-137, +-135, +-132, +-129, +-127, +-124, +-121, +-118, +-116, +-113, +-110, +-108, +-105, +-102, +-99, +-96, +-94, +-91, +-88, +-85, +-82, +-80, +-77, +-74, +-71, +-68, +-65, +-63, +-60, +-57, +-54, +-51, +-48, +-45, +-42, +-40, +-37, +-34, +-31, +-28, +-25, +-22, +-20, +-17, +-14, +-11, +-8, +-5, +-2, +0, +2, +5, +8, +11, +13, +16, +19, +22, +25, +27, +30, +33, +36, +38, +41, +44, +47, +49, +52, +55, +57, +60, +63, +65, +68, +71, +73, +76, +78, +81, +83, +86, +88, +91, +93, +96, +98, +101, +103, +106, +108, +110, +113, +115, +117, +120, +122, +124, +127, +129, +131, +133, +135, +137, +140, +142, +144, +146, +148, +150, +152, +154, +156, +158, +160, +161, +163, +165, +167, +169, +171, +172, +174, +176, +177, +179, +181, +182, +184, +185, +187, +188, +190, +191, +193, +194, +195, +197, +198, +199, +201, +202, +203, +204, +205, +207, +208, +209, +210, +211, +212, +213, +214, +215, +216, +216, +217, +218, +219, +219, +220, +221, +222, +222, +223, +223, +224, +224, +225, +225, +226, +226, +227, +227, +227, +227, +228, +228, +228, +228, +228, +229, +229, +229, +229, +229, +229, +229, +229, +228, +228, +228, +228, +228, +228, +227, +227, +227, +226, +226, +225, +225, +225, +224, +224, +223, +222, +222, +221, +221, +220, +219, +218, +218, +217, +216, +215, +214, +214, +213, +212, +211, +210, +209, +208, +207, +206, +205, +203, +202, +201, +200, +199, +197, +196, +195, +194, +192, +191, +190, +188, +187, +185, +184, +182, +181, +179, +178, +176, +175, +173, +172, +170, +168, +167, +165, +163, +162, +160, +158, +156, +155, +153, +151, +149, +147, +146, +144, +142, +140, +138, +136, +134, +132, +130, +128, +126, +124, +122, +120, +118, +116, +114, +112, +110, +108, +106, +104, +102, +99, +97, +95, +93, +91, +89, +87, +84, +82, +80, +78, +76, +73, +71, +69, +67, +64, +62, +60, +58, +56, +53, +51, +49, +47, +44, +42, +40, +38, +35, +33, +31, +28, +26, +24, +22, +19, +17, +15, +13, +10, +8, +6, +4, +1, +0, +-2, +-4, +-6, +-9, +-11, +-13, +-15, +-17, +-20, +-22, +-24, +-26, +-28, +-30, +-33, +-35, +-37, +-39, +-41, +-43, +-45, +-47, +-49, +-52, +-54, +-56, +-58, +-60, +-62, +-64, +-66, +-68, +-70, +-72, +-74, +-76, +-77, +-79, +-81, +-83, +-85, +-87, +-89, +-90, +-92, +-94, +-96, +-98, +-99, +-101, +-103, +-105, +-106, +-108, +-110, +-111, +-113, +-114, +-116, +-118, +-119, +-121, +-122, +-124, +-125, +-127, +-128, +-130, +-131, +-132, +-134, +-135, +-136, +-138, +-139, +-140, +-142, +-143, +-144, +-145, +-146, +-148, +-149, +-150, +-151, +-152, +-153, +-154, +-155, +-156, +-157, +-158, +-159, +-160, +-161, +-162, +-162, +-163, +-164, +-165, +-166, +-166, +-167, +-168, +-168, +-169, +-170, +-170, +-171, +-171, +-172, +-172, +-173, +-173, +-174, +-174, +-175, +-175, +-175, +-176, +-176, +-176, +-177, +-177, +-177, +-177, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-177, +-177, +-177, +-177, +-177, +-176, +-176, +-176, +-175, +-175, +-175, +-174, +-174, +-173, +-173, +-172, +-172, +-171, +-171, +-170, +-170, +-169, +-168, +-168, +-167, +-166, +-166, +-165, +-164, +-163, +-163, +-162, +-161, +-160, +-159, +-158, +-158, +-157, +-156, +-155, +-154, +-153, +-152, +-151, +-150, +-149, +-148, +-147, +-145, +-144, +-143, +-142, +-141, +-140, +-139, +-137, +-136, +-135, +-134, +-132, +-131, +-130, +-128, +-127, +-126, +-124, +-123, +-122, +-120, +-119, +-118, +-116, +-115, +-113, +-112, +-110, +-109, +-107, +-106, +-104, +-103, +-101, +-100, +-98, +-97, +-95, +-94, +-92, +-90, +-89, +-87, +-86, +-84, +-82, +-81, +-79, +-77, +-76, +-74, +-72, +-71, +-69, +-67, +-66, +-64, +-62, +-60, +-59, +-57, +-55, +-54, +-52, +-50, +-48, +-47, +-45, +-43, +-41, +-40, +-38, +-36, +-34, +-33, +-31, +-29, +-27, +-25, +-24, +-22, +-20, +-18, +-17, +-15, +-13, +-11, +-10, +-8, +-6, +-4, +-3, +-1, +0, +2, +3, +5, +7, +8, +10, +12, +14, +15, +17, +19, +20, +22, +24, +25, +27, +29, +30, +32, +34, +35, +37, +39, +40, +42, +43, +45, +47, +48, +50, +51, +53, +54, +56, +57, +59, +60, +62, +63, +65, +66, +68, +69, +70, +72, +73, +75, +76, +77, +79, +80, +81, +83, +84, +85, +87, +88, +89, +90, +92, +93, +94, +95, +96, +97, +99, +100, +101, +102, +103, +104, +105, +106, +107, +108, +109, +110, +111, +112, +113, +114, +115, +116, +117, +117, +118, +119, +120, +121, +121, +122, +123, +124, +124, +125, +126, +126, +127, +128, +128, +129, +129, +130, +130, +131, +131, +132, +132, +133, +133, +134, +134, +135, +135, +135, +136, +136, +136, +136, +137, +137, +137, +137, +138, +138, +138, +138, +138, +138, +138, +138, +139, +139, +139, +139, +139, +139, +139, +138, +138, +138, +138, +138, +138, +138, +138, +137, +137, +137, +137, +136, +136, +136, +136, +135, +135, +134, +134, +134, +133, +133, +132, +132, +132, +131, +131, +130, +129, +129, +128, +128, +127, +127, +126, +125, +125, +124, +123, +123, +122, +121, +121, +120, +119, +118, +117, +117, +116, +115, +114, +113, +113, +112, +111, +110, +109, +108, +107, +106, +105, +104, +103, +102, +101, +100, +99, +98, +97, +96, +95, +94, +93, +92, +91, +90, +89, +87, +86, +85, +84, +83, +82, +81, +79, +78, +77, +76, +75, +73, +72, +71, +70, +68, +67, +66, +65, +63, +62, +61, +60, +58, +57, +56, +54, +53, +52, +50, +49, +48, +47, +45, +44, +43, +41, +40, +39, +37, +36, +34, +33, +32, +30, +29, +28, +26, +25, +24, +22, +21, +20, +18, +17, +16, +14, +13, +11, +10, +9, +7, +6, +5, +3, +2, +1, +0, +-1, +-2, +-4, +-5, +-6, +-8, +-9, +-10, +-11, +-13, +-14, +-15, +-17, +-18, +-19, +-20, +-22, +-23, +-24, +-26, +-27, +-28, +-29, +-30, +-32, +-33, +-34, +-35, +-37, +-38, +-39, +-40, +-41, +-42, +-44, +-45, +-46, +-47, +-48, +-49, +-50, +-51, +-53, +-54, +-55, +-56, +-57, +-58, +-59, +-60, +-61, +-62, +-63, +-64, +-65, +-66, +-67, +-68, +-69, +-70, +-71, +-71, +-72, +-73, +-74, +-75, +-76, +-77, +-77, +-78, +-79, +-80, +-81, +-81, +-82, +-83, +-84, +-84, +-85, +-86, +-87, +-87, +-88, +-89, +-89, +-90, +-90, +-91, +-92, +-92, +-93, +-93, +-94, +-94, +-95, +-95, +-96, +-96, +-97, +-97, +-98, +-98, +-99, +-99, +-99, +-100, +-100, +-100, +-101, +-101, +-101, +-102, +-102, +-102, +-102, +-103, +-103, +-103, +-103, +-103, +-104, +-104, +-104, +-104, +-104, +-104, +-104, +-105, +-105, +-105, +-105, +-105, +-105, +-105, +-105, +-105, +-105, +-105, +-105, +-104, +-104, +-104, +-104, +-104, +-104, +-104, +-104, +-103, +-103, +-103, +-103, +-103, +-102, +-102, +-102, +-102, +-101, +-101, +-101, +-100, +-100, +-100, +-99, +-99, +-99, +-98, +-98, +-97, +-97, +-97, +-96, +-96, +-95, +-95, +-94, +-94, +-93, +-93, +-92, +-92, +-91, +-90, +-90, +-89, +-89, +-88, +-87, +-87, +-86, +-86, +-85, +-84, +-84, +-83, +-82, +-81, +-81, +-80, +-79, +-79, +-78, +-77, +-76, +-76, +-75, +-74, +-73, +-72, +-72, +-71, +-70, +-69, +-68, +-67, +-67, +-66, +-65, +-64, +-63, +-62, +-61, +-61, +-60, +-59, +-58, +-57, +-56, +-55, +-54, +-53, +-52, +-51, +-50, +-49, +-48, +-48, +-47, +-46, +-45, +-44, +-43, +-42, +-41, +-40, +-39, +-38, +-37, +-36, +-35, +-34, +-33, +-32, +-31, +-30, +-29, +-28, +-27, +-26, +-25, +-24, +-23, +-21, +-20, +-19, +-18, +-17, +-16, +-15, +-14, +-13, +-12, +-11, +-10, +-9, +-8, +-7, +-6, +-5, +-4, +-3, +-2, +-1, +0, +0, +1, +2, +3, +4, +5, +6, +7, +8, +9, +10, +11, +12, +13, +14, +15, +16, +17, +18, +19, +20, +21, +22, +22, +23, +24, +25, +26, +27, +28, +29, +30, +31, +32, +32, +33, +34, +35, +36, +37, +38, +38, +39, +40, +41, +42, +42, +43, +44, +45, +46, +46, +47, +48, +49, +49, +50, +51, +52, +52, +53, +54, +54, +55, +56, +56, +57, +58, +58, +59, +59, +60, +61, +61, +62, +62, +63, +64, +64, +65, +65, +66, +66, +67, +67, +68, +68, +69, +69, +69, +70, +70, +71, +71, +72, +72, +72, +73, +73, +73, +74, +74, +74, +75, +75, +75, +76, +76, +76, +76, +77, +77, +77, +77, +77, +78, +78, +78, +78, +78, +78, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +79, +78, +78, +78, +78, +78, +78, +77, +77, +77, +77, +77, +76, +76, +76, +76, +75, +75, +75, +74, +74, +74, +74, +73, +73, +72, +72, +72, +71, +71, +71, +70, +70, +69, +69, +69, +68, +68, +67, +67, +66, +66, +65, +65, +64, +64, +63, +63, +62, +62, +61, +61, +60, +60, +59, +59, +58, +57, +57, +56, +56, +55, +55, +54, +53, +53, +52, +51, +51, +50, +50, +49, +48, +48, +47, +46, +46, +45, +44, +44, +43, +42, +41, +41, +40, +39, +39, +38, +37, +37, +36, +35, +34, +34, +33, +32, +31, +31, +30, +29, +28, +28, +27, +26, +25, +25, +24, +23, +22, +22, +21, +20, +19, +19, +18, +17, +16, +16, +15, +14, +13, +12, +12, +11, +10, +9, +9, +8, +7, +6, +6, +5, +4, +3, +3, +2, +1, +0, +0, +0, +-1, +-2, +-2, +-3, +-4, +-5, +-5, +-6, +-7, +-8, +-8, +-9, +-10, +-10, +-11, +-12, +-13, +-13, +-14, +-15, +-15, +-16, +-17, +-17, +-18, +-19, +-19, +-20, +-21, +-21, +-22, +-23, +-23, +-24, +-25, +-25, +-26, +-27, +-27, +-28, +-28, +-29, +-30, +-30, +-31, +-31, +-32, +-33, +-33, +-34, +-34, +-35, +-35, +-36, +-36, +-37, +-37, +-38, +-38, +-39, +-39, +-40, +-40, +-41, +-41, +-42, +-42, +-43, +-43, +-44, +-44, +-45, +-45, +-45, +-46, +-46, +-47, +-47, +-47, +-48, +-48, +-49, +-49, +-49, +-50, +-50, +-50, +-51, +-51, +-51, +-51, +-52, +-52, +-52, +-53, +-53, +-53, +-53, +-54, +-54, +-54, +-54, +-54, +-55, +-55, +-55, +-55, +-55, +-56, +-56, +-56, +-56, +-56, +-56, +-56, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-56, +-56, +-56, +-56, +-56, +-56, +-56, +-55, +-55, +-55, +-55, +-55, +-54, +-54, +-54, +-54, +-54, +-53, +-53, +-53, +-53, +-52, +-52, +-52, +-52, +-51, +-51, +-51, +-50, +-50, +-50, +-50, +-49, +-49, +-49, +-48, +-48, +-48, +-47, +-47, +-46, +-46, +-46, +-45, +-45, +-45, +-44, +-44, +-43, +-43, +-43, +-42, +-42, +-41, +-41, +-40, +-40, +-40, +-39, +-39, +-38, +-38, +-37, +-37, +-36, +-36, +-35, +-35, +-35, +-34, +-34, +-33, +-33, +-32, +-32, +-31, +-31, +-30, +-30, +-29, +-29, +-28, +-28, +-27, +-26, +-26, +-25, +-25, +-24, +-24, +-23, +-23, +-22, +-22, +-21, +-21, +-20, +-19, +-19, +-18, +-18, +-17, +-17, +-16, +-16, +-15, +-15, +-14, +-13, +-13, +-12, +-12, +-11, +-11, +-10, +-9, +-9, +-8, +-8, +-7, +-7, +-6, +-6, +-5, +-4, +-4, +-3, +-3, +-2, +-2, +-1, +-1, +0, +0, +0, +1, +1, +2, +2, +3, +3, +4, +4, +5, +5, +6, +7, +7, +8, +8, +9, +9, +10, +10, +11, +11, +12, +12, +13, +13, +14, +14, +15, +15, +16, +16, +17, +17, +18, +18, +18, +19, +19, +20, +20, +21, +21, +22, +22, +22, +23, +23, +24, +24, +25, +25, +25, +26, +26, +27, +27, +27, +28, +28, +28, +29, +29, +30, +30, +30, +31, +31, +31, +32, +32, +32, +33, +33, +33, +33, +34, +34, +34, +35, +35, +35, +35, +36, +36, +36, +36, +37, +37, +37, +37, +38, +38, +38, +38, +38, +39, +39, +39, +39, +39, +40, +40, +40, +40, +40, +40, +40, +41, +41, +41, +41, +41, +41, +41, +41, +41, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +41, +41, +41, +41, +41, +41, +41, +41, +41, +41, +40, +40, +40, +40, +40, +40, +40, +39, +39, +39, +39, +39, +38, +38, +38, +38, +38, +37, +37, +37, +37, +37, +36, +36, +36, +36, +35, +35, +35, +35, +34, +34, +34, +34, +33, +33, +33, +33, +32, +32, +32, +31, +31, +31, +30, +30, +30, +30, +29, +29, +29, +28, +28, +28, +27, +27, +27, +26, +26, +26, +25, +25, +25, +24, +24, +23, +23, +23, +22, +22, +22, +21, +21, +21, +20, +20, +19, +19, +19, +18, +18, +18, +17, +17, +16, +16, +16, +15, +15, +14, +14, +14, +13, +13, +12, +12, +12, +11, +11, +10, +10, +10, +9, +9, +8, +8, +8, +7, +7, +6, +6, +6, +5, +5, +4, +4, +4, +3, +3, +2, +2, +2, +1, +1, +1, +0, +0, +0, +0, +0, +-1, +-1, +-2, +-2, +-2, +-3, +-3, +-3, +-4, +-4, +-5, +-5, +-5, +-6, +-6, +-6, +-7, +-7, +-7, +-8, +-8, +-9, +-9, +-9, +-10, +-10, +-10, +-11, +-11, +-11, +-12, +-12, +-12, +-13, +-13, +-13, +-14, +-14, +-14, +-14, +-15, +-15, +-15, +-16, +-16, +-16, +-17, +-17, +-17, +-17, +-18, +-18, +-18, +-19, +-19, +-19, +-19, +-20, +-20, +-20, +-20, +-21, +-21, +-21, +-21, +-21, +-22, +-22, +-22, +-22, +-23, +-23, +-23, +-23, +-23, +-24, +-24, +-24, +-24, +-24, +-25, +-25, +-25, +-25, +-25, +-25, +-26, +-26, +-26, +-26, +-26, +-26, +-26, +-27, +-27, +-27, +-27, +-27, +-27, +-27, +-27, +-27, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-27, +-27, +-27, +-27, +-27, +-27, +-27, +-27, +-27, +-27, +-26, +-26, +-26, +-26, +-26, +-26, +-26, +-25, +-25, +-25, +-25, +-25, +-25, +-25, +-24, +-24, +-24, +-24, +-24, +-24, +-23, +-23, +-23, +-23, +-23, +-22, +-22, +-22, +-22, +-22, +-21, +-21, +-21, +-21, +-21, +-20, +-20, +-20, +-20, +-20, +-19, +-19, +-19, +-19, +-18, +-18, +-18, +-18, +-17, +-17, +-17, +-17, +-16, +-16, +-16, +-16, +-15, +-15, +-15, +-15, +-14, +-14, +-14, +-14, +-13, +-13, +-13, +-13, +-12, +-12, +-12, +-12, +-11, +-11, +-11, +-11, +-10, +-10, +-10, +-9, +-9, +-9, +-9, +-8, +-8, +-8, +-7, +-7, +-7, +-7, +-6, +-6, +-6, +-6, +-5, +-5, +-5, +-4, +-4, +-4, +-4, +-3, +-3, +-3, +-2, +-2, +-2, +-2, +-1, +-1, +-1, +-1, +0, +0, +0, +0, +0, +0, +0, +1, +1, +1, +1, +2, +2, +2, +2, +3, +3, +3, +3, +4, +4, +4, +5, +5, +5, +5, +6, +6, +6, +6, +6, +7, +7, +7, +7, +8, +8, +8, +8, +9, +9, +9, +9, +10, +10, +10, +10, +10, +11, +11, +11, +11, +11, +12, +12, +12, +12, +12, +13, +13, +13, +13, +13, +14, +14, +14, +14, +14, +14, +15, +15, +15, +15, +15, +15, +16, +16, +16, +16, +16, +16, +16, +17, +17, +17, +17, +17, +17, +17, +17, +18, +18, +18, +18, +18, +18, +18, +18, +18, +19, +19, +19, +19, +19, +19, +19, +19, +19, +19, +19, +19, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +19, +19, +19, +19, +19, +19, +19, +19, +19, +19, +19, +19, +19, +19, +18, +18, +18, +18, +18, +18, +18, +18, +18, +18, +17, +17, +17, +17, +17, +17, +17, +17, +16, +16, +16, +16, +16, +16, +16, +16, +15, +15, +15, +15, +15, +15, +15, +14, +14, +14, +14, +14, +14, +14, +13, +13, +13, +13, +13, +13, +12, +12, +12, +12, +12, +12, +11, +11, +11, +11, +11, +11, +10, +10, +10, +10, +10, +9, +9, +9, +9, +9, +9, +8, +8, +8, +8, +8, +7, +7, +7, +7, +7, +7, +6, +6, +6, +6, +6, +5, +5, +5, +5, +5, +4, +4, +4, +4, +4, +4, +3, +3, +3, +3, +3, +2, +2, +2, +2, +2, +2, +1, +1, +1, +1, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-3, +-3, +-3, +-3, +-3, +-4, +-4, +-4, +-4, +-4, +-4, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +3, +3, +3, +3, +3, +3, +3, +3, +3, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +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, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-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, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +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, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +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, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +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, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +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 short LARGE_FILTER_IMPD[] /* Impulse response differences */ = { +-1, +-2, +-3, +-5, +-6, +-7, +-9, +-10, +-11, +-13, +-14, +-15, +-17, +-18, +-19, +-21, +-22, +-23, +-25, +-26, +-27, +-28, +-30, +-32, +-32, +-34, +-35, +-36, +-38, +-39, +-40, +-42, +-43, +-44, +-45, +-47, +-48, +-49, +-51, +-52, +-53, +-54, +-56, +-56, +-58, +-60, +-60, +-62, +-63, +-64, +-66, +-66, +-68, +-69, +-70, +-72, +-72, +-74, +-75, +-76, +-77, +-79, +-79, +-81, +-82, +-83, +-84, +-85, +-87, +-87, +-89, +-90, +-90, +-92, +-93, +-94, +-95, +-96, +-98, +-98, +-99, +-100, +-102, +-102, +-103, +-105, +-105, +-106, +-108, +-108, +-109, +-110, +-111, +-112, +-113, +-114, +-115, +-116, +-116, +-118, +-118, +-119, +-121, +-120, +-122, +-123, +-123, +-125, +-125, +-126, +-126, +-128, +-128, +-129, +-130, +-130, +-132, +-132, +-132, +-134, +-134, +-135, +-135, +-136, +-137, +-137, +-138, +-139, +-139, +-140, +-141, +-141, +-142, +-142, +-143, +-143, +-144, +-145, +-145, +-145, +-146, +-147, +-147, +-147, +-148, +-149, +-148, +-150, +-149, +-150, +-151, +-151, +-151, +-152, +-152, +-152, +-153, +-153, +-153, +-153, +-154, +-154, +-155, +-155, +-155, +-155, +-155, +-156, +-156, +-156, +-156, +-156, +-157, +-157, +-157, +-157, +-157, +-157, +-157, +-158, +-157, +-158, +-158, +-157, +-158, +-158, +-158, +-158, +-157, +-158, +-158, +-158, +-157, +-158, +-158, +-157, +-158, +-157, +-157, +-157, +-157, +-157, +-157, +-157, +-156, +-156, +-156, +-156, +-156, +-155, +-155, +-155, +-155, +-155, +-154, +-154, +-153, +-154, +-153, +-153, +-152, +-152, +-152, +-151, +-151, +-151, +-150, +-150, +-150, +-149, +-149, +-148, +-148, +-147, +-147, +-147, +-146, +-145, +-145, +-145, +-144, +-144, +-143, +-142, +-142, +-142, +-141, +-140, +-140, +-139, +-139, +-138, +-137, +-137, +-136, +-136, +-135, +-134, +-134, +-133, +-132, +-132, +-131, +-130, +-130, +-129, +-128, +-128, +-126, +-126, +-126, +-125, +-123, +-124, +-122, +-122, +-121, +-120, +-119, +-119, +-117, +-117, +-117, +-115, +-114, +-113, +-113, +-112, +-112, +-110, +-110, +-108, +-108, +-107, +-106, +-106, +-104, +-104, +-102, +-102, +-101, +-100, +-99, +-98, +-98, +-96, +-95, +-95, +-94, +-92, +-92, +-91, +-90, +-89, +-88, +-87, +-86, +-85, +-85, +-83, +-82, +-82, +-80, +-80, +-78, +-78, +-76, +-76, +-75, +-73, +-73, +-72, +-70, +-70, +-69, +-68, +-66, +-66, +-65, +-64, +-63, +-61, +-61, +-60, +-59, +-58, +-57, +-56, +-55, +-54, +-53, +-51, +-51, +-50, +-49, +-48, +-47, +-46, +-45, +-44, +-43, +-42, +-41, +-41, +-39, +-38, +-37, +-36, +-35, +-34, +-34, +-32, +-31, +-31, +-29, +-28, +-28, +-26, +-26, +-24, +-24, +-23, +-21, +-21, +-20, +-19, +-18, +-17, +-16, +-15, +-14, +-13, +-13, +-11, +-11, +-9, +-9, +-8, +-7, +-6, +-5, +-5, +-3, +-2, +-2, +-1, +0, +1, +2, +2, +4, +4, +5, +6, +7, +8, +8, +10, +10, +11, +11, +13, +13, +14, +15, +15, +17, +17, +18, +18, +20, +20, +21, +21, +23, +23, +23, +25, +25, +26, +26, +27, +28, +28, +30, +29, +31, +31, +32, +32, +33, +34, +34, +35, +35, +36, +37, +37, +37, +39, +39, +39, +40, +40, +41, +42, +42, +42, +43, +44, +44, +44, +45, +46, +45, +47, +46, +48, +47, +48, +49, +49, +49, +49, +50, +51, +51, +51, +51, +52, +52, +53, +53, +53, +53, +54, +54, +54, +55, +55, +55, +55, +56, +56, +56, +56, +57, +57, +57, +57, +58, +57, +58, +58, +58, +58, +59, +58, +59, +59, +59, +59, +59, +59, +59, +60, +59, +60, +59, +60, +60, +60, +59, +60, +60, +60, +60, +59, +60, +60, +60, +60, +59, +60, +60, +59, +60, +59, +60, +59, +59, +59, +59, +59, +59, +59, +58, +59, +58, +58, +58, +58, +57, +58, +57, +57, +57, +57, +55, +57, +56, +56, +55, +56, +55, +55, +54, +55, +54, +54, +54, +53, +53, +53, +52, +53, +52, +51, +52, +51, +50, +51, +50, +49, +50, +49, +48, +49, +48, +47, +47, +47, +47, +46, +46, +45, +45, +45, +44, +44, +43, +43, +42, +43, +41, +42, +40, +41, +40, +39, +40, +38, +39, +37, +38, +37, +36, +36, +35, +36, +34, +34, +34, +33, +33, +32, +32, +31, +31, +30, +30, +29, +29, +28, +28, +27, +27, +26, +26, +25, +25, +24, +24, +24, +22, +23, +21, +21, +21, +20, +20, +19, +19, +18, +18, +17, +16, +16, +16, +15, +14, +14, +14, +13, +12, +12, +11, +11, +11, +9, +10, +8, +9, +7, +8, +6, +7, +5, +5, +5, +4, +4, +3, +3, +2, +1, +1, +1, +0, +0, +-1, +-1, +-2, +-3, +-3, +-3, +-4, +-4, +-5, +-5, +-6, +-6, +-7, +-7, +-8, +-8, +-8, +-9, +-10, +-10, +-10, +-11, +-11, +-12, +-12, +-13, +-13, +-14, +-14, +-14, +-15, +-15, +-16, +-16, +-16, +-17, +-18, +-17, +-18, +-19, +-19, +-19, +-20, +-20, +-21, +-20, +-22, +-21, +-22, +-23, +-22, +-23, +-24, +-23, +-25, +-24, +-25, +-25, +-25, +-26, +-26, +-27, +-26, +-27, +-28, +-27, +-28, +-28, +-29, +-29, +-29, +-29, +-30, +-30, +-30, +-30, +-31, +-31, +-31, +-31, +-32, +-32, +-32, +-32, +-33, +-33, +-33, +-33, +-33, +-34, +-34, +-34, +-34, +-34, +-35, +-34, +-35, +-35, +-35, +-36, +-35, +-36, +-35, +-36, +-36, +-36, +-37, +-36, +-36, +-37, +-37, +-36, +-37, +-37, +-37, +-37, +-37, +-38, +-37, +-37, +-38, +-37, +-38, +-37, +-38, +-37, +-38, +-38, +-37, +-38, +-38, +-37, +-38, +-38, +-37, +-38, +-38, +-37, +-38, +-37, +-38, +-37, +-38, +-37, +-38, +-37, +-37, +-37, +-37, +-37, +-37, +-37, +-37, +-35, +-37, +-36, +-37, +-36, +-36, +-36, +-36, +-36, +-35, +-36, +-35, +-36, +-35, +-35, +-34, +-35, +-34, +-35, +-34, +-34, +-34, +-33, +-34, +-33, +-33, +-33, +-32, +-33, +-32, +-32, +-32, +-32, +-31, +-31, +-31, +-31, +-31, +-30, +-30, +-30, +-29, +-30, +-29, +-29, +-28, +-28, +-29, +-27, +-28, +-27, +-27, +-27, +-26, +-27, +-25, +-26, +-25, +-26, +-24, +-25, +-24, +-24, +-23, +-24, +-23, +-22, +-23, +-22, +-22, +-21, +-21, +-21, +-21, +-20, +-20, +-19, +-19, +-19, +-19, +-18, +-18, +-18, +-17, +-17, +-17, +-16, +-16, +-15, +-16, +-14, +-15, +-14, +-14, +-14, +-13, +-13, +-12, +-12, +-12, +-12, +-11, +-10, +-11, +-10, +-10, +-9, +-9, +-9, +-8, +-8, +-8, +-7, +-7, +-6, +-6, +-6, +-6, +-5, +-5, +-4, +-4, +-4, +-3, +-3, +-3, +-2, +-2, +-2, +-1, +-1, +-1, +0, +0, +0, +1, +1, +2, +1, +3, +2, +3, +3, +4, +3, +4, +5, +5, +5, +5, +6, +6, +7, +6, +8, +7, +8, +8, +8, +9, +9, +9, +10, +9, +11, +10, +11, +11, +11, +12, +12, +12, +13, +13, +13, +13, +14, +14, +14, +14, +15, +15, +15, +16, +16, +16, +16, +17, +16, +18, +17, +17, +18, +18, +18, +19, +19, +19, +19, +19, +20, +19, +20, +21, +20, +21, +21, +21, +21, +21, +22, +22, +22, +22, +22, +23, +22, +23, +23, +23, +23, +24, +24, +23, +24, +24, +24, +25, +24, +25, +24, +25, +25, +25, +25, +26, +25, +26, +25, +26, +26, +25, +26, +26, +26, +27, +26, +26, +27, +26, +27, +26, +27, +26, +27, +27, +27, +26, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +26, +27, +27, +27, +27, +26, +27, +27, +26, +26, +26, +27, +26, +26, +27, +26, +26, +26, +26, +26, +26, +25, +26, +25, +26, +25, +25, +25, +25, +25, +25, +25, +24, +24, +25, +24, +24, +24, +23, +24, +24, +23, +23, +23, +23, +23, +22, +23, +22, +22, +22, +22, +21, +22, +21, +21, +21, +21, +20, +20, +21, +20, +19, +20, +19, +19, +19, +19, +19, +18, +18, +18, +18, +18, +17, +17, +17, +17, +16, +16, +16, +16, +16, +15, +15, +15, +14, +15, +14, +14, +14, +13, +13, +13, +13, +12, +13, +12, +11, +12, +11, +11, +11, +10, +11, +10, +9, +10, +9, +9, +9, +8, +9, +8, +7, +8, +7, +7, +7, +6, +6, +6, +6, +5, +5, +5, +5, +4, +4, +4, +3, +4, +3, +3, +2, +2, +2, +2, +2, +1, +1, +0, +1, +0, +0, +0, +-1, +-1, +-1, +-1, +-2, +-2, +-2, +-2, +-3, +-2, +-4, +-3, +-3, +-4, +-4, +-5, +-4, +-5, +-5, +-5, +-6, +-6, +-6, +-6, +-7, +-6, +-7, +-7, +-8, +-7, +-8, +-8, +-9, +-8, +-9, +-9, +-9, +-10, +-9, +-10, +-10, +-10, +-11, +-10, +-11, +-11, +-12, +-11, +-12, +-12, +-12, +-12, +-13, +-12, +-13, +-13, +-13, +-14, +-13, +-14, +-14, +-14, +-14, +-15, +-14, +-15, +-15, +-15, +-15, +-16, +-15, +-16, +-16, +-16, +-16, +-16, +-17, +-16, +-17, +-17, +-17, +-17, +-17, +-18, +-17, +-18, +-18, +-17, +-18, +-18, +-19, +-18, +-18, +-19, +-18, +-19, +-19, +-19, +-19, +-19, +-19, +-19, +-19, +-20, +-19, +-20, +-19, +-20, +-20, +-20, +-19, +-20, +-20, +-20, +-20, +-20, +-21, +-20, +-20, +-20, +-21, +-20, +-20, +-21, +-20, +-21, +-20, +-20, +-21, +-20, +-21, +-20, +-21, +-20, +-21, +-20, +-21, +-21, +-20, +-20, +-21, +-20, +-21, +-20, +-21, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-19, +-20, +-20, +-19, +-20, +-19, +-19, +-19, +-20, +-19, +-19, +-18, +-19, +-19, +-19, +-18, +-18, +-19, +-18, +-18, +-18, +-18, +-18, +-18, +-17, +-18, +-17, +-17, +-17, +-17, +-17, +-17, +-16, +-17, +-16, +-16, +-17, +-15, +-16, +-16, +-15, +-16, +-15, +-15, +-15, +-15, +-15, +-14, +-14, +-15, +-14, +-13, +-14, +-14, +-13, +-13, +-13, +-13, +-13, +-13, +-12, +-12, +-12, +-12, +-12, +-11, +-12, +-11, +-11, +-11, +-10, +-11, +-10, +-10, +-10, +-9, +-10, +-9, +-9, +-9, +-9, +-9, +-8, +-8, +-8, +-8, +-8, +-7, +-7, +-7, +-7, +-7, +-6, +-6, +-6, +-6, +-6, +-5, +-5, +-6, +-4, +-5, +-4, +-5, +-4, +-4, +-3, +-4, +-3, +-3, +-3, +-2, +-3, +-2, +-2, +-2, +-1, +-2, +-1, +-1, +-1, +0, +-1, +0, +0, +0, +1, +0, +1, +1, +1, +1, +2, +2, +2, +2, +2, +3, +3, +2, +4, +3, +3, +4, +4, +4, +4, +5, +4, +5, +5, +5, +6, +5, +6, +6, +6, +6, +7, +6, +7, +7, +7, +7, +8, +7, +8, +8, +8, +8, +9, +8, +9, +9, +9, +9, +10, +9, +10, +10, +10, +10, +10, +11, +10, +11, +11, +11, +11, +11, +11, +12, +11, +12, +12, +12, +12, +12, +13, +12, +13, +13, +12, +13, +13, +14, +13, +13, +14, +13, +14, +14, +13, +14, +14, +15, +14, +14, +14, +15, +14, +15, +15, +14, +15, +15, +15, +15, +15, +16, +15, +15, +15, +16, +15, +16, +15, +16, +15, +16, +16, +16, +15, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +17, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +15, +16, +16, +16, +16, +16, +15, +16, +16, +15, +16, +16, +15, +15, +16, +15, +16, +15, +15, +15, +15, +15, +15, +15, +15, +15, +14, +15, +14, +15, +14, +14, +15, +14, +14, +14, +14, +13, +14, +14, +13, +13, +14, +13, +13, +13, +13, +13, +12, +13, +12, +13, +12, +12, +12, +12, +12, +12, +11, +12, +11, +11, +11, +11, +11, +11, +10, +11, +10, +10, +10, +10, +10, +10, +9, +10, +9, +9, +9, +9, +8, +9, +8, +9, +8, +8, +8, +7, +8, +7, +7, +7, +7, +7, +7, +6, +7, +6, +6, +6, +5, +6, +5, +5, +6, +4, +5, +5, +4, +5, +4, +4, +4, +3, +4, +3, +3, +3, +3, +3, +2, +3, +2, +2, +2, +2, +1, +2, +1, +1, +1, +1, +1, +0, +0, +1, +0, +-1, +0, +0, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-3, +-3, +-3, +-3, +-4, +-3, +-4, +-4, +-4, +-4, +-4, +-5, +-4, +-5, +-5, +-5, +-5, +-5, +-6, +-5, +-6, +-6, +-6, +-6, +-6, +-6, +-7, +-6, +-7, +-7, +-7, +-7, +-7, +-7, +-8, +-8, +-7, +-8, +-8, +-8, +-8, +-9, +-8, +-9, +-8, +-9, +-9, +-9, +-9, +-9, +-9, +-10, +-9, +-10, +-9, +-10, +-10, +-10, +-10, +-10, +-10, +-11, +-10, +-11, +-10, +-11, +-11, +-11, +-10, +-11, +-11, +-12, +-11, +-11, +-11, +-12, +-11, +-12, +-12, +-11, +-12, +-12, +-12, +-11, +-12, +-12, +-13, +-12, +-12, +-12, +-12, +-13, +-12, +-12, +-13, +-12, +-13, +-12, +-13, +-12, +-13, +-13, +-12, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-11, +-13, +-13, +-12, +-13, +-13, +-12, +-13, +-12, +-13, +-12, +-13, +-12, +-13, +-12, +-12, +-13, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-11, +-12, +-12, +-11, +-12, +-11, +-11, +-12, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-10, +-11, +-10, +-11, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-9, +-10, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-8, +-9, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-7, +-7, +-8, +-7, +-7, +-7, +-7, +-6, +-7, +-7, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-5, +-6, +-5, +-5, +-5, +-5, +-5, +-4, +-5, +-4, +-5, +-4, +-4, +-4, +-4, +-3, +-4, +-3, +-4, +-3, +-3, +-3, +-3, +-2, +-3, +-2, +-2, +-3, +-2, +-1, +-2, +-2, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +0, +-1, +0, +0, +0, +0, +0, +0, +1, +0, +1, +1, +0, +2, +1, +1, +1, +2, +2, +1, +2, +2, +3, +2, +2, +3, +2, +3, +3, +3, +3, +3, +4, +3, +4, +4, +3, +4, +4, +4, +5, +4, +5, +4, +5, +5, +5, +5, +5, +5, +5, +6, +5, +6, +6, +6, +6, +6, +6, +6, +6, +7, +6, +7, +7, +7, +7, +7, +7, +7, +7, +7, +8, +7, +8, +8, +7, +8, +8, +8, +8, +8, +8, +9, +8, +9, +8, +9, +8, +9, +9, +8, +9, +9, +9, +9, +9, +10, +9, +9, +9, +10, +9, +10, +9, +10, +10, +9, +10, +10, +9, +10, +10, +10, +10, +10, +10, +10, +10, +10, +10, +11, +10, +10, +10, +10, +11, +10, +10, +11, +10, +10, +11, +10, +10, +11, +10, +10, +11, +10, +11, +10, +11, +10, +10, +11, +10, +10, +11, +10, +11, +10, +10, +10, +10, +10, +10, +11, +10, +10, +10, +10, +11, +10, +10, +10, +10, +10, +10, +10, +10, +9, +10, +10, +10, +9, +10, +10, +9, +10, +9, +10, +9, +9, +10, +9, +9, +9, +9, +9, +9, +9, +9, +9, +8, +9, +9, +8, +9, +8, +8, +9, +8, +8, +8, +8, +8, +8, +7, +8, +8, +7, +8, +7, +7, +8, +7, +7, +7, +7, +6, +7, +7, +6, +7, +6, +7, +6, +6, +6, +6, +6, +6, +5, +6, +5, +6, +5, +5, +5, +5, +5, +5, +5, +4, +5, +4, +5, +4, +4, +4, +4, +4, +4, +3, +4, +3, +4, +3, +3, +3, +3, +3, +3, +2, +3, +2, +2, +3, +2, +2, +2, +1, +2, +2, +1, +2, +1, +1, +1, +1, +1, +1, +0, +1, +0, +1, +0, +0, +0, +0, +0, +0, +-1, +0, +-1, +-1, +0, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-3, +-2, +-3, +-3, +-3, +-3, +-3, +-3, +-4, +-3, +-4, +-3, +-4, +-4, +-3, +-4, +-4, +-5, +-4, +-4, +-4, +-5, +-4, +-5, +-5, +-5, +-4, +-5, +-5, +-6, +-5, +-5, +-5, +-6, +-5, +-6, +-5, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-7, +-6, +-6, +-7, +-6, +-7, +-7, +-6, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-8, +-7, +-7, +-8, +-7, +-8, +-7, +-8, +-7, +-8, +-7, +-8, +-8, +-8, +-8, +-7, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-9, +-8, +-8, +-8, +-8, +-9, +-8, +-8, +-8, +-9, +-8, +-8, +-9, +-8, +-9, +-8, +-8, +-9, +-8, +-9, +-8, +-9, +-8, +-8, +-9, +-8, +-9, +-8, +-9, +-8, +-9, +-8, +-8, +-9, +-8, +-9, +-8, +-7, +-9, +-8, +-8, +-9, +-8, +-8, +-9, +-8, +-8, +-8, +-8, +-8, +-9, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-7, +-8, +-8, +-8, +-7, +-8, +-8, +-7, +-8, +-7, +-8, +-7, +-8, +-7, +-7, +-7, +-8, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-6, +-7, +-7, +-6, +-7, +-7, +-6, +-6, +-7, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-5, +-6, +-5, +-6, +-5, +-5, +-6, +-5, +-5, +-5, +-5, +-5, +-4, +-5, +-5, +-4, +-5, +-4, +-5, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-3, +-4, +-3, +-4, +-3, +-3, +-3, +-4, +-3, +-2, +-3, +-3, +-3, +-2, +-3, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-2, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +0, +-1, +-1, +-1, +0, +-1, +0, +0, +-1, +0, +0, +0, +0, +0, +1, +0, +1, +0, +1, +0, +1, +1, +1, +1, +1, +1, +1, +2, +1, +2, +1, +2, +2, +2, +1, +2, +2, +3, +2, +2, +2, +3, +2, +3, +3, +2, +3, +3, +3, +3, +3, +3, +4, +3, +3, +4, +3, +4, +3, +4, +4, +4, +4, +4, +4, +4, +4, +4, +5, +4, +4, +5, +5, +4, +5, +5, +4, +5, +5, +5, +5, +5, +5, +5, +6, +5, +5, +5, +6, +5, +6, +5, +6, +6, +5, +6, +6, +6, +5, +6, +6, +6, +6, +6, +6, +7, +6, +6, +6, +6, +7, +6, +6, +7, +6, +7, +6, +6, +7, +7, +6, +7, +6, +7, +6, +7, +7, +7, +6, +7, +7, +6, +7, +7, +7, +7, +6, +7, +7, +7, +7, +7, +6, +7, +7, +7, +7, +7, +7, +6, +7, +7, +7, +7, +7, +7, +6, +7, +7, +6, +7, +6, +7, +7, +7, +6, +7, +7, +6, +7, +7, +6, +7, +7, +6, +7, +6, +7, +6, +7, +6, +6, +7, +6, +6, +7, +6, +6, +6, +6, +6, +7, +6, +6, +6, +6, +5, +6, +6, +6, +6, +5, +6, +6, +5, +6, +5, +6, +5, +5, +6, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +4, +5, +4, +5, +4, +5, +4, +4, +4, +5, +4, +4, +4, +4, +3, +4, +4, +4, +3, +4, +3, +4, +3, +3, +4, +3, +3, +3, +3, +3, +3, +2, +3, +3, +2, +3, +2, +3, +2, +2, +3, +2, +2, +2, +2, +2, +1, +2, +2, +1, +2, +1, +2, +1, +1, +1, +2, +1, +1, +0, +1, +1, +1, +0, +1, +0, +1, +0, +0, +1, +0, +0, +0, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-2, +-2, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-3, +-2, +-3, +-2, +-3, +-3, +-2, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-4, +-3, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-4, +-3, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-5, +-4, +-4, +-5, +-4, +-4, +-5, +-4, +-5, +-4, +-5, +-5, +-4, +-5, +-5, +-4, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-6, +-5, +-5, +-5, +-5, +-6, +-5, +-5, +-6, +-5, +-5, +-6, +-5, +-6, +-5, +-6, +-5, +-6, +-5, +-5, +-6, +-6, +-5, +-6, +-5, +-6, +-5, +-6, +-5, +-6, +-5, +-6, +-6, +-5, +-6, +-5, +-6, +-5, +-6, +-5, +-6, +-6, +-5, +-6, +-5, +-5, +-5, +-6, +-5, +-6, +-5, +-6, +-5, +-5, +-6, +-5, +-6, +-5, +-5, +-6, +-5, +-5, +-6, +-5, +-5, +-5, +-6, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-4, +-5, +-5, +-5, +-4, +-5, +-5, +-4, +-5, +-4, +-5, +-4, +-4, +-5, +-4, +-4, +-5, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-3, +-4, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-3, +-4, +-3, +-3, +-3, +-3, +-3, +-2, +-3, +-3, +-3, +-2, +-3, +-2, +-3, +-2, +-3, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-2, +-2, +-1, +-2, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +1, +0, +0, +0, +1, +0, +1, +0, +1, +0, +1, +1, +1, +0, +1, +1, +1, +1, +1, +2, +1, +1, +1, +2, +1, +2, +1, +2, +1, +2, +2, +1, +2, +2, +2, +2, +2, +2, +2, +2, +2, +3, +2, +2, +3, +2, +3, +2, +3, +2, +3, +2, +3, +3, +3, +3, +2, +3, +3, +3, +3, +3, +4, +3, +3, +3, +3, +4, +3, +3, +4, +3, +4, +3, +4, +3, +4, +3, +4, +4, +3, +4, +4, +4, +4, +3, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +5, +4, +4, +4, +4, +5, +4, +4, +4, +5, +4, +4, +5, +4, +4, +5, +4, +5, +4, +4, +5, +4, +5, +4, +5, +4, +4, +5, +4, +5, +4, +5, +4, +5, +4, +5, +4, +5, +4, +5, +4, +5, +4, +5, +4, +5, +4, +5, +3, +4, +5, +4, +5, +4, +4, +5, +4, +5, +4, +4, +5, +4, +4, +5, +4, +4, +4, +4, +5, +4, +4, +4, +4, +4, +5, +4, +4, +4, +4, +4, +4, +4, +3, +4, +4, +4, +4, +4, +3, +4, +4, +4, +3, +4, +4, +3, +4, +3, +4, +3, +3, +4, +3, +4, +3, +3, +3, +4, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +2, +3, +3, +3, +2, +3, +2, +3, +2, +3, +2, +3, +2, +2, +3, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +1, +2, +2, +1, +2, +1, +2, +1, +1, +2, +1, +1, +1, +2, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-2, +-2, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-3, +-2, +-3, +-2, +-3, +-2, +-3, +-2, +-3, +-2, +-3, +-3, +-3, +-2, +-3, +-3, +-3, +-3, +-2, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-4, +-3, +-3, +-3, +-3, +-4, +-3, +-3, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-4, +-3, +-3, +-3, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-3, +-3, +-4, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-2, +-3, +-3, +-3, +-2, +-3, +-3, +-2, +-3, +-2, +-3, +-2, +-3, +-2, +-3, +-2, +-3, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-2, +-2, +-2, +-2, +-1, +-2, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +0, +-1, +-1, +-1, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +1, +1, +2, +1, +1, +1, +2, +1, +1, +2, +1, +1, +2, +1, +2, +1, +2, +1, +2, +2, +1, +2, +2, +2, +1, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +3, +2, +2, +2, +3, +2, +2, +3, +2, +2, +3, +2, +3, +2, +3, +2, +3, +2, +3, +2, +3, +2, +3, +3, +2, +3, +2, +3, +3, +2, +3, +3, +3, +2, +3, +3, +2, +3, +3, +3, +3, +2, +3, +3, +3, +3, +2, +3, +3, +3, +3, +3, +2, +3, +3, +3, +3, +3, +3, +3, +2, +3, +3, +3, +3, +3, +3, +2, +3, +3, +3, +3, +3, +3, +2, +2, +3, +3, +3, +2, +3, +3, +3, +3, +2, +3, +3, +3, +2, +3, +3, +3, +2, +3, +3, +2, +3, +3, +2, +3, +3, +2, +3, +2, +3, +2, +3, +2, +3, +2, +3, +2, +3, +2, +3, +2, +2, +3, +2, +2, +3, +2, +2, +3, +2, +2, +2, +2, +2, +3, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +1, +2, +2, +2, +2, +2, +1, +2, +2, +1, +2, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +1, +2, +1, +1, +2, +1, +1, +1, +1, +2, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +0, +1, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-2, +-1, +-2, +-2, +-1, +-2, +-2, +-2, +-1, +-2, +-2, +-2, +-2, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-3, +-2, +-2, +-3, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-3, +-1, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-2, +-2, +-2, +-2, +-1, +-2, +-2, +-2, +-1, +-2, +-2, +-1, +-2, +-1, +-2, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +1, +0, +1, +1, +1, +0, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +2, +1, +1, +1, +1, +1, +1, +2, +1, +1, +1, +2, +1, +1, +2, +1, +1, +2, +1, +1, +2, +1, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +2, +1, +2, +1, +2, +2, +1, +2, +2, +1, +2, +2, +1, +2, +2, +1, +2, +2, +2, +1, +2, +2, +1, +2, +2, +2, +1, +2, +2, +2, +1, +2, +2, +2, +1, +2, +2, +2, +2, +1, +2, +2, +2, +1, +2, +2, +2, +1, +2, +2, +2, +1, +2, +1, +2, +1, +2, +2, +1, +2, +2, +2, +1, +2, +2, +1, +2, +2, +1, +2, +2, +1, +2, +2, +1, +2, +2, +1, +2, +1, +2, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +1, +2, +1, +2, +1, +1, +2, +1, +1, +2, +1, +1, +2, +1, +1, +1, +2, +1, +1, +1, +1, +1, +2, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +0, +1, +1, +1, +0, +1, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +1, +0, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +1, +0, +1, +1, +1, +0, +1, +1, +0, +1, +1, +1, +0, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +2, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +0, +1, +1, +1, +1, +0, +1, +1, +1, +0, +1, +1, +1, +0, +1, +1, +0, +1, +1, +0, +1, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +0, +1, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +1, +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, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +0, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +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, +1, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +1, +0, +1, +0, +0, +1, +0, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +0, +1, +0, +0, +1, +0, +1, +0, +0, +1, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +1, +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, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +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, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +1, +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, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +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, +-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, +1, +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, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +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, +1, +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, +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, +-1, +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, +-1, +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, +-1, +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, +-1, +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, +-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, +-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, +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, +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, +1, +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, +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, +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, +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, +-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, +-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, +-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, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +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, +-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}; diff --git a/darkice/tags/darkice-1_3/src/aflibConverterSmallFilter.h b/darkice/tags/darkice-1_3/src/aflibConverterSmallFilter.h new file mode 100644 index 0000000..d7d6b71 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/aflibConverterSmallFilter.h @@ -0,0 +1,4643 @@ +/* + * Copyright: (C) 2000 Julius O. Smith + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Julius O. Smith jos@ccrma.stanford.edu + * + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define SMALL_FILTER_NMULT ((short)13) +#define SMALL_FILTER_SCALE 13128 /* Unity-gain scale factor */ +#define SMALL_FILTER_NWING 1536 /* Filter table length */ + +short aflibConverter::SMALL_FILTER_IMP[] /* Impulse response */ = { +32767, +32766, +32764, +32760, +32755, +32749, +32741, +32731, +32721, +32708, +32695, +32679, +32663, +32645, +32625, +32604, +32582, +32558, +32533, +32506, +32478, +32448, +32417, +32385, +32351, +32316, +32279, +32241, +32202, +32161, +32119, +32075, +32030, +31984, +31936, +31887, +31836, +31784, +31731, +31676, +31620, +31563, +31504, +31444, +31383, +31320, +31256, +31191, +31124, +31056, +30987, +30916, +30845, +30771, +30697, +30621, +30544, +30466, +30387, +30306, +30224, +30141, +30057, +29971, +29884, +29796, +29707, +29617, +29525, +29433, +29339, +29244, +29148, +29050, +28952, +28852, +28752, +28650, +28547, +28443, +28338, +28232, +28125, +28017, +27908, +27797, +27686, +27574, +27461, +27346, +27231, +27115, +26998, +26879, +26760, +26640, +26519, +26398, +26275, +26151, +26027, +25901, +25775, +25648, +25520, +25391, +25262, +25131, +25000, +24868, +24735, +24602, +24467, +24332, +24197, +24060, +23923, +23785, +23647, +23507, +23368, +23227, +23086, +22944, +22802, +22659, +22515, +22371, +22226, +22081, +21935, +21789, +21642, +21494, +21346, +21198, +21049, +20900, +20750, +20600, +20449, +20298, +20146, +19995, +19842, +19690, +19537, +19383, +19230, +19076, +18922, +18767, +18612, +18457, +18302, +18146, +17990, +17834, +17678, +17521, +17365, +17208, +17051, +16894, +16737, +16579, +16422, +16264, +16106, +15949, +15791, +15633, +15475, +15317, +15159, +15001, +14843, +14685, +14527, +14369, +14212, +14054, +13896, +13739, +13581, +13424, +13266, +13109, +12952, +12795, +12639, +12482, +12326, +12170, +12014, +11858, +11703, +11548, +11393, +11238, +11084, +10929, +10776, +10622, +10469, +10316, +10164, +10011, +9860, +9708, +9557, +9407, +9256, +9106, +8957, +8808, +8659, +8511, +8364, +8216, +8070, +7924, +7778, +7633, +7488, +7344, +7200, +7057, +6914, +6773, +6631, +6490, +6350, +6210, +6071, +5933, +5795, +5658, +5521, +5385, +5250, +5115, +4981, +4848, +4716, +4584, +4452, +4322, +4192, +4063, +3935, +3807, +3680, +3554, +3429, +3304, +3180, +3057, +2935, +2813, +2692, +2572, +2453, +2335, +2217, +2101, +1985, +1870, +1755, +1642, +1529, +1418, +1307, +1197, +1088, +979, +872, +765, +660, +555, +451, +348, +246, +145, +44, +-54, +-153, +-250, +-347, +-443, +-537, +-631, +-724, +-816, +-908, +-998, +-1087, +-1175, +-1263, +-1349, +-1435, +-1519, +-1603, +-1685, +-1767, +-1848, +-1928, +-2006, +-2084, +-2161, +-2237, +-2312, +-2386, +-2459, +-2531, +-2603, +-2673, +-2742, +-2810, +-2878, +-2944, +-3009, +-3074, +-3137, +-3200, +-3261, +-3322, +-3381, +-3440, +-3498, +-3554, +-3610, +-3665, +-3719, +-3772, +-3824, +-3875, +-3925, +-3974, +-4022, +-4069, +-4116, +-4161, +-4205, +-4249, +-4291, +-4333, +-4374, +-4413, +-4452, +-4490, +-4527, +-4563, +-4599, +-4633, +-4666, +-4699, +-4730, +-4761, +-4791, +-4820, +-4848, +-4875, +-4901, +-4926, +-4951, +-4974, +-4997, +-5019, +-5040, +-5060, +-5080, +-5098, +-5116, +-5133, +-5149, +-5164, +-5178, +-5192, +-5205, +-5217, +-5228, +-5238, +-5248, +-5257, +-5265, +-5272, +-5278, +-5284, +-5289, +-5293, +-5297, +-5299, +-5301, +-5303, +-5303, +-5303, +-5302, +-5300, +-5298, +-5295, +-5291, +-5287, +-5282, +-5276, +-5270, +-5263, +-5255, +-5246, +-5237, +-5228, +-5217, +-5206, +-5195, +-5183, +-5170, +-5157, +-5143, +-5128, +-5113, +-5097, +-5081, +-5064, +-5047, +-5029, +-5010, +-4991, +-4972, +-4952, +-4931, +-4910, +-4889, +-4867, +-4844, +-4821, +-4797, +-4774, +-4749, +-4724, +-4699, +-4673, +-4647, +-4620, +-4593, +-4566, +-4538, +-4510, +-4481, +-4452, +-4422, +-4393, +-4363, +-4332, +-4301, +-4270, +-4238, +-4206, +-4174, +-4142, +-4109, +-4076, +-4042, +-4009, +-3975, +-3940, +-3906, +-3871, +-3836, +-3801, +-3765, +-3729, +-3693, +-3657, +-3620, +-3584, +-3547, +-3510, +-3472, +-3435, +-3397, +-3360, +-3322, +-3283, +-3245, +-3207, +-3168, +-3129, +-3091, +-3052, +-3013, +-2973, +-2934, +-2895, +-2855, +-2816, +-2776, +-2736, +-2697, +-2657, +-2617, +-2577, +-2537, +-2497, +-2457, +-2417, +-2377, +-2337, +-2297, +-2256, +-2216, +-2176, +-2136, +-2096, +-2056, +-2016, +-1976, +-1936, +-1896, +-1856, +-1817, +-1777, +-1737, +-1698, +-1658, +-1619, +-1579, +-1540, +-1501, +-1462, +-1423, +-1384, +-1345, +-1306, +-1268, +-1230, +-1191, +-1153, +-1115, +-1077, +-1040, +-1002, +-965, +-927, +-890, +-854, +-817, +-780, +-744, +-708, +-672, +-636, +-600, +-565, +-530, +-494, +-460, +-425, +-391, +-356, +-322, +-289, +-255, +-222, +-189, +-156, +-123, +-91, +-59, +-27, +4, +35, +66, +97, +127, +158, +188, +218, +247, +277, +306, +334, +363, +391, +419, +447, +474, +501, +528, +554, +581, +606, +632, +657, +683, +707, +732, +756, +780, +803, +827, +850, +872, +895, +917, +939, +960, +981, +1002, +1023, +1043, +1063, +1082, +1102, +1121, +1139, +1158, +1176, +1194, +1211, +1228, +1245, +1262, +1278, +1294, +1309, +1325, +1340, +1354, +1369, +1383, +1397, +1410, +1423, +1436, +1448, +1461, +1473, +1484, +1496, +1507, +1517, +1528, +1538, +1548, +1557, +1566, +1575, +1584, +1592, +1600, +1608, +1616, +1623, +1630, +1636, +1643, +1649, +1654, +1660, +1665, +1670, +1675, +1679, +1683, +1687, +1690, +1694, +1697, +1700, +1702, +1704, +1706, +1708, +1709, +1711, +1712, +1712, +1713, +1713, +1713, +1713, +1712, +1711, +1710, +1709, +1708, +1706, +1704, +1702, +1700, +1697, +1694, +1691, +1688, +1685, +1681, +1677, +1673, +1669, +1664, +1660, +1655, +1650, +1644, +1639, +1633, +1627, +1621, +1615, +1609, +1602, +1596, +1589, +1582, +1575, +1567, +1560, +1552, +1544, +1536, +1528, +1520, +1511, +1503, +1494, +1485, +1476, +1467, +1458, +1448, +1439, +1429, +1419, +1409, +1399, +1389, +1379, +1368, +1358, +1347, +1337, +1326, +1315, +1304, +1293, +1282, +1271, +1260, +1248, +1237, +1225, +1213, +1202, +1190, +1178, +1166, +1154, +1142, +1130, +1118, +1106, +1094, +1081, +1069, +1057, +1044, +1032, +1019, +1007, +994, +981, +969, +956, +943, +931, +918, +905, +892, +879, +867, +854, +841, +828, +815, +802, +790, +777, +764, +751, +738, +725, +713, +700, +687, +674, +662, +649, +636, +623, +611, +598, +585, +573, +560, +548, +535, +523, +510, +498, +486, +473, +461, +449, +437, +425, +413, +401, +389, +377, +365, +353, +341, +330, +318, +307, +295, +284, +272, +261, +250, +239, +228, +217, +206, +195, +184, +173, +163, +152, +141, +131, +121, +110, +100, +90, +80, +70, +60, +51, +41, +31, +22, +12, +3, +-5, +-14, +-23, +-32, +-41, +-50, +-59, +-67, +-76, +-84, +-93, +-101, +-109, +-117, +-125, +-133, +-140, +-148, +-156, +-163, +-170, +-178, +-185, +-192, +-199, +-206, +-212, +-219, +-226, +-232, +-239, +-245, +-251, +-257, +-263, +-269, +-275, +-280, +-286, +-291, +-297, +-302, +-307, +-312, +-317, +-322, +-327, +-332, +-336, +-341, +-345, +-349, +-354, +-358, +-362, +-366, +-369, +-373, +-377, +-380, +-384, +-387, +-390, +-394, +-397, +-400, +-402, +-405, +-408, +-411, +-413, +-416, +-418, +-420, +-422, +-424, +-426, +-428, +-430, +-432, +-433, +-435, +-436, +-438, +-439, +-440, +-442, +-443, +-444, +-445, +-445, +-446, +-447, +-447, +-448, +-448, +-449, +-449, +-449, +-449, +-449, +-449, +-449, +-449, +-449, +-449, +-449, +-448, +-448, +-447, +-447, +-446, +-445, +-444, +-443, +-443, +-442, +-441, +-440, +-438, +-437, +-436, +-435, +-433, +-432, +-430, +-429, +-427, +-426, +-424, +-422, +-420, +-419, +-417, +-415, +-413, +-411, +-409, +-407, +-405, +-403, +-400, +-398, +-396, +-393, +-391, +-389, +-386, +-384, +-381, +-379, +-376, +-374, +-371, +-368, +-366, +-363, +-360, +-357, +-355, +-352, +-349, +-346, +-343, +-340, +-337, +-334, +-331, +-328, +-325, +-322, +-319, +-316, +-313, +-310, +-307, +-304, +-301, +-298, +-294, +-291, +-288, +-285, +-282, +-278, +-275, +-272, +-269, +-265, +-262, +-259, +-256, +-252, +-249, +-246, +-243, +-239, +-236, +-233, +-230, +-226, +-223, +-220, +-217, +-213, +-210, +-207, +-204, +-200, +-197, +-194, +-191, +-187, +-184, +-181, +-178, +-175, +-172, +-168, +-165, +-162, +-159, +-156, +-153, +-150, +-147, +-143, +-140, +-137, +-134, +-131, +-128, +-125, +-122, +-120, +-117, +-114, +-111, +-108, +-105, +-102, +-99, +-97, +-94, +-91, +-88, +-86, +-83, +-80, +-78, +-75, +-72, +-70, +-67, +-65, +-62, +-59, +-57, +-55, +-52, +-50, +-47, +-45, +-43, +-40, +-38, +-36, +-33, +-31, +-29, +-27, +-25, +-22, +-20, +-18, +-16, +-14, +-12, +-10, +-8, +-6, +-4, +-2, +0, +0, +2, +4, +6, +8, +9, +11, +13, +14, +16, +17, +19, +21, +22, +24, +25, +27, +28, +29, +31, +32, +33, +35, +36, +37, +38, +40, +41, +42, +43, +44, +45, +46, +47, +48, +49, +50, +51, +52, +53, +54, +55, +56, +56, +57, +58, +59, +59, +60, +61, +62, +62, +63, +63, +64, +64, +65, +66, +66, +66, +67, +67, +68, +68, +69, +69, +69, +70, +70, +70, +70, +71, +71, +71, +71, +71, +72, +72, +72, +72, +72, +72, +72, +72, +72, +72, +72, +72, +72, +72, +72, +72, +72, +72, +72, +72, +72, +72, +72, +71, +71, +71, +71, +71, +70, +70, +70, +70, +69, +69, +69, +69, +68, +68, +68, +67, +67, +67, +66, +66, +66, +65, +65, +64, +64, +64, +63, +63, +62, +62, +62, +61, +61, +60, +60, +59, +59, +58, +58, +58, +57, +57, +56, +56, +55, +55, +54, +54, +53, +53, +52, +52, +51, +51, +50, +50, +49, +48, +48, +47, +47, +46, +46, +45, +45, +44, +44, +43, +43, +42, +42, +41, +41, +40, +39, +39, +38, +38, +37, +37, +36, +36, +35, +35, +34, +34, +33, +33, +32, +32, +31, +31, +30, +30, +29, +29, +28, +28, +27, +27, +26, +26, +25, +25, +24, +24, +23, +23, +23, +22, +22, +21, +21, +20, +20, +20, +19, +19, +18, +18, +17, +17, +17, +16, +16, +15, +15, +15, +14, +14, +14, +13, +13, +12, +12, +12, +11, +11, +11, +10, +10, +10, +9, +9, +9, +9, +8, +8, +8, +7, +7, +7, +7, +6, +6, +6, +6, +5, +5, +5, +5, +4, +4, +4, +4, +3, +3, +3, +3, +3, +2, +2, +2, +2, +2, +1, +1, +1, +1, +1, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1 +}; + +static short SMALL_FILTER_IMPD[] = { +-1, +-2, +-4, +-5, +-6, +-8, +-10, +-10, +-13, +-13, +-16, +-16, +-18, +-20, +-21, +-22, +-24, +-25, +-27, +-28, +-30, +-31, +-32, +-34, +-35, +-37, +-38, +-39, +-41, +-42, +-44, +-45, +-46, +-48, +-49, +-51, +-52, +-53, +-55, +-56, +-57, +-59, +-60, +-61, +-63, +-64, +-65, +-67, +-68, +-69, +-71, +-71, +-74, +-74, +-76, +-77, +-78, +-79, +-81, +-82, +-83, +-84, +-86, +-87, +-88, +-89, +-90, +-92, +-92, +-94, +-95, +-96, +-98, +-98, +-100, +-100, +-102, +-103, +-104, +-105, +-106, +-107, +-108, +-109, +-111, +-111, +-112, +-113, +-115, +-115, +-116, +-117, +-119, +-119, +-120, +-121, +-121, +-123, +-124, +-124, +-126, +-126, +-127, +-128, +-129, +-129, +-131, +-131, +-132, +-133, +-133, +-135, +-135, +-135, +-137, +-137, +-138, +-138, +-140, +-139, +-141, +-141, +-142, +-142, +-143, +-144, +-144, +-145, +-145, +-146, +-146, +-147, +-148, +-148, +-148, +-149, +-149, +-150, +-150, +-151, +-151, +-152, +-151, +-153, +-152, +-153, +-154, +-153, +-154, +-154, +-155, +-155, +-155, +-155, +-156, +-156, +-156, +-156, +-157, +-156, +-157, +-157, +-157, +-157, +-158, +-157, +-158, +-158, +-157, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-157, +-158, +-158, +-157, +-158, +-157, +-158, +-157, +-157, +-157, +-156, +-157, +-156, +-156, +-156, +-156, +-155, +-155, +-155, +-155, +-154, +-155, +-153, +-154, +-153, +-153, +-152, +-153, +-151, +-152, +-151, +-150, +-151, +-150, +-149, +-149, +-149, +-148, +-147, +-148, +-146, +-146, +-146, +-145, +-145, +-144, +-144, +-143, +-143, +-141, +-142, +-141, +-140, +-140, +-139, +-138, +-138, +-137, +-137, +-136, +-135, +-135, +-134, +-133, +-132, +-132, +-132, +-130, +-130, +-129, +-128, +-128, +-127, +-126, +-125, +-125, +-124, +-123, +-122, +-122, +-121, +-120, +-119, +-118, +-118, +-116, +-116, +-115, +-115, +-113, +-113, +-111, +-111, +-110, +-109, +-109, +-107, +-107, +-105, +-105, +-104, +-103, +-102, +-101, +-101, +-98, +-99, +-97, +-97, +-96, +-94, +-94, +-93, +-92, +-92, +-90, +-89, +-88, +-88, +-86, +-86, +-84, +-84, +-82, +-82, +-81, +-80, +-78, +-78, +-77, +-76, +-75, +-74, +-73, +-72, +-72, +-70, +-69, +-68, +-68, +-66, +-65, +-65, +-63, +-63, +-61, +-61, +-59, +-59, +-58, +-56, +-56, +-55, +-54, +-53, +-52, +-51, +-50, +-49, +-48, +-47, +-47, +-45, +-44, +-44, +-42, +-42, +-41, +-39, +-39, +-38, +-37, +-36, +-36, +-34, +-33, +-33, +-31, +-31, +-30, +-29, +-28, +-27, +-26, +-25, +-25, +-23, +-23, +-22, +-21, +-20, +-20, +-18, +-18, +-17, +-16, +-15, +-14, +-14, +-13, +-12, +-11, +-10, +-10, +-9, +-8, +-7, +-6, +-6, +-5, +-4, +-4, +-2, +-2, +-2, +0, +0, +1, +2, +2, +3, +4, +4, +5, +6, +6, +7, +8, +9, +9, +9, +11, +11, +11, +12, +13, +13, +14, +15, +15, +16, +16, +17, +17, +18, +19, +19, +19, +20, +21, +21, +21, +22, +23, +23, +24, +23, +25, +25, +25, +26, +26, +27, +27, +27, +28, +28, +29, +29, +30, +29, +30, +31, +31, +31, +32, +32, +32, +32, +33, +33, +34, +33, +34, +35, +34, +35, +35, +35, +36, +36, +36, +36, +37, +36, +37, +37, +38, +37, +38, +37, +38, +39, +38, +38, +39, +39, +38, +39, +39, +40, +39, +39, +40, +39, +40, +40, +39, +40, +40, +40, +40, +40, +40, +40, +40, +40, +40, +41, +40, +40, +40, +40, +40, +40, +40, +40, +40, +40, +39, +40, +40, +39, +40, +39, +40, +39, +39, +39, +39, +39, +39, +39, +38, +38, +39, +38, +38, +38, +37, +38, +37, +38, +37, +36, +37, +37, +36, +36, +36, +36, +36, +35, +35, +36, +34, +35, +34, +35, +34, +33, +34, +33, +33, +33, +33, +32, +32, +32, +31, +31, +31, +31, +30, +31, +30, +30, +29, +30, +29, +28, +29, +28, +28, +28, +27, +27, +27, +26, +27, +25, +26, +25, +26, +24, +25, +24, +24, +23, +24, +23, +22, +23, +22, +22, +21, +21, +21, +21, +20, +20, +19, +20, +19, +18, +19, +18, +18, +17, +17, +17, +17, +16, +16, +15, +16, +15, +14, +15, +14, +14, +13, +13, +13, +12, +13, +12, +11, +12, +11, +10, +11, +10, +10, +9, +9, +9, +9, +8, +8, +8, +8, +7, +7, +6, +7, +6, +5, +6, +5, +5, +5, +4, +4, +4, +3, +4, +3, +3, +2, +2, +2, +2, +1, +2, +1, +0, +1, +0, +0, +0, +-1, +-1, +-1, +-1, +-1, +-2, +-2, +-2, +-2, +-3, +-3, +-3, +-3, +-3, +-4, +-4, +-4, +-4, +-5, +-4, +-5, +-5, +-6, +-5, +-6, +-6, +-6, +-6, +-6, +-7, +-6, +-7, +-7, +-7, +-8, +-7, +-8, +-8, +-8, +-8, +-8, +-9, +-8, +-9, +-9, +-9, +-9, +-9, +-10, +-9, +-10, +-10, +-10, +-10, +-10, +-10, +-11, +-10, +-11, +-10, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-12, +-11, +-12, +-12, +-11, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-13, +-12, +-12, +-13, +-12, +-13, +-12, +-13, +-13, +-12, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-12, +-13, +-13, +-12, +-13, +-12, +-13, +-12, +-13, +-12, +-12, +-13, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-11, +-12, +-11, +-12, +-11, +-12, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-10, +-11, +-11, +-10, +-10, +-11, +-10, +-10, +-10, +-10, +-10, +-9, +-10, +-10, +-9, +-10, +-9, +-8, +-9, +-9, +-9, +-9, +-9, +-9, +-8, +-9, +-8, +-9, +-8, +-8, +-8, +-8, +-8, +-7, +-8, +-8, +-7, +-7, +-8, +-7, +-7, +-7, +-7, +-6, +-7, +-7, +-6, +-7, +-6, +-6, +-6, +-6, +-6, +-6, +-5, +-6, +-5, +-6, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-4, +-5, +-4, +-4, +-5, +-4, +-4, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-2, +-3, +-3, +-3, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-2, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +1, +0, +1, +1, +1, +1, +0, +1, +1, +1, +2, +1, +1, +1, +2, +1, +2, +1, +2, +1, +2, +2, +2, +1, +2, +2, +2, +2, +2, +2, +2, +2, +3, +2, +2, +3, +2, +2, +3, +2, +3, +2, +3, +2, +3, +3, +2, +3, +3, +3, +2, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +4, +3, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +3, +3, +4, +3, +3, +3, +3, +3, +3, +3, +4, +3, +3, +3, +3, +3, +3, +3, +2, +3, +3, +3, +3, +3, +3, +3, +2, +3, +3, +3, +2, +3, +3, +2, +3, +3, +2, +3, +2, +3, +3, +2, +2, +3, +2, +3, +2, +2, +3, +2, +2, +3, +2, +2, +2, +2, +3, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +0, +2, +2, +2, +2, +1, +2, +2, +1, +2, +1, +2, +2, +1, +2, +1, +2, +1, +1, +2, +1, +1, +2, +1, +1, +1, +2, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +0, +1, +1, +1, +0, +1, +0, +1, +0, +1, +1, +0, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +0, +0, +1, +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, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +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, +-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, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +-1, +-2, +-4, +-5, +-6, +-8, +-10, +-10, +-13, +-13, +-16, +-16, +-18, +-20, +-21, +-22, +-24, +-25, +-27, +-28, +-30, +-31, +-32, +-34, +-35, +-37, +-38, +-39, +-41, +-42, +-44, +-45, +-46, +-48, +-49, +-51, +-52, +-53, +-55, +-56, +-57, +-59, +-60, +-61, +-63, +-64, +-65, +-67, +-68, +-69, +-71, +-71, +-74, +-74, +-76, +-77, +-78, +-79, +-81, +-82, +-83, +-84, +-86, +-87, +-88, +-89, +-90, +-92, +-92, +-94, +-95, +-96, +-98, +-98, +-100, +-100, +-102, +-103, +-104, +-105, +-106, +-107, +-108, +-109, +-111, +-111, +-112, +-113, +-115, +-115, +-116, +-117, +-119, +-119, +-120, +-121, +-121, +-123, +-124, +-124, +-126, +-126, +-127, +-128, +-129, +-129, +-131, +-131, +-132, +-133, +-133, +-135, +-135, +-135, +-137, +-137, +-138, +-138, +-140, +-139, +-141, +-141, +-142, +-142, +-143, +-144, +-144, +-145, +-145, +-146, +-146, +-147, +-148, +-148, +-148, +-149, +-149, +-150, +-150, +-151, +-151, +-152, +-151, +-153, +-152, +-153, +-154, +-153, +-154, +-154, +-155, +-155, +-155, +-155, +-156, +-156, +-156, +-156, +-157, +-156, +-157, +-157, +-157, +-157, +-158, +-157, +-158, +-158, +-157, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-157, +-158, +-158, +-157, +-158, +-157, +-158, +-157, +-157, +-157, +-156, +-157, +-156, +-156, +-156, +-156, +-155, +-155, +-155, +-155, +-154, +-155, +-153, +-154, +-153, +-153, +-152, +-153, +-151, +-152, +-151, +-150, +-151, +-150, +-149, +-149, +-149, +-148, +-147, +-148, +-146, +-146, +-146, +-145, +-145, +-144, +-144, +-143, +-143, +-141, +-142, +-141, +-140, +-140, +-139, +-138, +-138, +-137, +-137, +-136, +-135, +-135, +-134, +-133, +-132, +-132, +-132, +-130, +-130, +-129, +-128, +-128, +-127, +-126, +-125, +-125, +-124, +-123, +-122, +-122, +-121, +-120, +-119, +-118, +-118, +-116, +-116, +-115, +-115, +-113, +-113, +-111, +-111, +-110, +-109, +-109, +-107, +-107, +-105, +-105, +-104, +-103, +-102, +-101, +-101, +-98, +-99, +-97, +-97, +-96, +-94, +-94, +-93, +-92, +-92, +-90, +-89, +-88, +-88, +-86, +-86, +-84, +-84, +-82, +-82, +-81, +-80, +-78, +-78, +-77, +-76, +-75, +-74, +-73, +-72, +-72, +-70, +-69, +-68, +-68, +-66, +-65, +-65, +-63, +-63, +-61, +-61, +-59, +-59, +-58, +-56, +-56, +-55, +-54, +-53, +-52, +-51, +-50, +-49, +-48, +-47, +-47, +-45, +-44, +-44, +-42, +-42, +-41, +-39, +-39, +-38, +-37, +-36, +-36, +-34, +-33, +-33, +-31, +-31, +-30, +-29, +-28, +-27, +-26, +-25, +-25, +-23, +-23, +-22, +-21, +-20, +-20, +-18, +-18, +-17, +-16, +-15, +-14, +-14, +-13, +-12, +-11, +-10, +-10, +-9, +-8, +-7, +-6, +-6, +-5, +-4, +-4, +-2, +-2, +-2, +0, +0, +1, +2, +2, +3, +4, +4, +5, +6, +6, +7, +8, +9, +9, +9, +11, +11, +11, +12, +13, +13, +14, +15, +15, +16, +16, +17, +17, +18, +19, +19, +19, +20, +21, +21, +21, +22, +23, +23, +24, +23, +25, +25, +25, +26, +26, +27, +27, +27, +28, +28, +29, +29, +30, +29, +30, +31, +31, +31, +32, +32, +32, +32, +33, +33, +34, +33, +34, +35, +34, +35, +35, +35, +36, +36, +36, +36, +37, +36, +37, +37, +38, +37, +38, +37, +38, +39, +38, +38, +39, +39, +38, +39, +39, +40, +39, +39, +40, +39, +40, +40, +39, +40, +40, +40, +40, +40, +40, +40, +40, +40, +40, +41, +40, +40, +40, +40, +40, +40, +40, +40, +40, +40, +39, +40, +40, +39, +40, +39, +40, +39, +39, +39, +39, +39, +39, +39, +38, +38, +39, +38, +38, +38, +37, +38, +37, +38, +37, +36, +37, +37, +36, +36, +36, +36, +36, +35, +35, +36, +34, +35, +34, +35, +34, +33, +34, +33, +33, +33, +33, +32, +32, +32, +31, +31, +31, +31, +30, +31, +30, +30, +29, +30, +29, +28, +29, +28, +28, +28, +27, +27, +27, +26, +27, +25, +26, +25, +26, +24, +25, +24, +24, +23, +24, +23, +22, +23, +22, +22, +21, +21, +21, +21, +20, +20, +19, +20, +19, +18, +19, +18, +18, +17, +17, +17, +17, +16, +16, +15, +16, +15, +14, +15, +14, +14, +13, +13, +13, +12, +13, +12, +11, +12, +11, +10, +11, +10, +10, +9, +9, +9, +9, +8, +8, +8, +8, +7, +7, +6, +7, +6, +5, +6, +5, +5, +5, +4, +4, +4, +3, +4, +3, +3, +2, +2, +2, +2, +1, +2, +1, +0, +1, +0, +0, +0, +-1, +-1, +-1, +-1, +-1, +-2, +-2, +-2, +-2, +-3, +-3, +-3, +-3, +-3, +-4, +-4, +-4, +-4, +-5, +-4, +-5, +-5, +-6, +-5, +-6, +-6, +-6, +-6, +-6, +-7, +-6, +-7, +-7, +-7, +-8, +-7, +-8, +-8, +-8, +-8, +-8, +-9, +-8, +-9, +-9, +-9, +-9, +-9, +-10, +-9, +-10, +-10, +-10, +-10, +-10, +-10, +-11, +-10, +-11, +-10, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-12, +-11, +-12, +-12, +-11, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-13, +-12, +-12, +-13, +-12, +-13, +-12, +-13, +-13, +-12, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-12, +-13, +-13, +-12, +-13, +-12, +-13, +-12, +-13, +-12, +-12, +-13, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-11, +-12, +-11, +-12, +-11, +-12, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-10, +-11, +-11, +-10, +-10, +-11, +-10, +-10, +-10, +-10, +-10, +-9, +-10, +-10, +-9, +-10, +-9, +-8, +-9, +-9, +-9, +-9, +-9, +-9, +-8, +-9, +-8, +-9, +-8, +-8, +-8, +-8, +-8, +-7, +-8, +-8, +-7, +-7, +-8, +-7, +-7, +-7, +-7, +-6, +-7, +-7, +-6, +-7, +-6, +-6, +-6, +-6, +-6, +-6, +-5, +-6, +-5, +-6, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-4, +-5, +-4, +-4, +-5, +-4, +-4, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-2, +-3, +-3, +-3, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-2, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +1, +0, +1, +1, +1, +1, +0, +1, +1, +1, +2, +1, +1, +1, +2, +1, +2, +1, +2, +1, +2, +2, +2, +1, +2, +2, +2, +2, +2, +2, +2, +2, +3, +2, +2, +3, +2, +2, +3, +2, +3, +2, +3, +2, +3, +3, +2, +3, +3, +3, +2, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +4, +3, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +3, +3, +4, +3, +3, +3, +3, +3, +3, +3, +4, +3, +3, +3, +3, +3, +3, +3, +2, +3, +3, +3, +3, +3, +3, +3, +2, +3, +3, +3, +2, +3, +3, +2, +3, +3, +2, +3, +2, +3, +3, +2, +2, +3, +2, +3, +2, +2, +3, +2, +2, +3, +2, +2, +2, +2, +3, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +0, +2, +2, +2, +2, +1, +2, +2, +1, +2, +1, +2, +2, +1, +2, +1, +2, +1, +1, +2, +1, +1, +2, +1, +1, +1, +2, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +0, +1, +1, +1, +0, +1, +0, +1, +0, +1, +1, +0, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +0, +0, +1, +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, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +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, +-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, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1 +}; diff --git a/darkice/tags/darkice-1_3/src/aflibDebug.cc b/darkice/tags/darkice-1_3/src/aflibDebug.cc new file mode 100644 index 0000000..9546c73 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/aflibDebug.cc @@ -0,0 +1,229 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "aflibDebug.h" +#include +#include +#include +#include + +static int aflib_debug_level = ::aflibDebug::lInfo; +static bool aflib_debug_abort = false; +static const char *aflib_debug_prefix = ""; +static char *messageAppName = 0; + + +/* +static char* status_strs[] = +{ + "Success", + "Error Open", + "Unsupported", + "AFLIB_ERROR_INITIALIZATION_FAILURE", + "AFLIB_NOT_FOUND", + "AFLIB_END_OF_FILE", + "AFLIB_NO_DATA", + 0 +}; + + +static char* data_size_strs[] = +{ + "UNDEFINED", + "8 bit signed", + "8 bit unsigned", + "16 bit signed", + "16 bit unsigned", + "32 bit signed", + "32 bit unsigned", + 0 +}; + +static char* data_endian_strs[] = +{ + "UNDEFINED", + "ENDIAN_LITTLE", + "ENDIAN_BIG", + 0 +}; +*/ + +/* + * Call the graphical application to display a message, if + * defined. Otherwise, send to standard error. Debug messages are + * always sent to standard error because they tend to be very verbose. + * Note that the external application is run in the background to + * avoid blocking the sound server. + */ +void output_message(::aflibDebug::Level level, const char *msg) { + char buff[1024]; + + /* default to text output if no message app is defined or if it is a debug message. */ + if (messageAppName == 0 || !strcmp(messageAppName, "") || (level == ::aflibDebug::lDebug)) + { + fprintf(stderr, "%s\n", msg); + return; + } + + switch (level) { + case ::aflibDebug::lFatal: + sprintf(buff, "%s -e \"aflib fatal error:\n\n%s\" &", messageAppName, msg); + break; + case ::aflibDebug::lWarning: + sprintf(buff, "%s -w \"aflib warning message:\n\n%s\" &", messageAppName, msg); + break; + case ::aflibDebug::lInfo: + sprintf(buff, "%s -i \"aflib informational message:\n\n%s\" &", messageAppName, msg); + break; + default: + break; // avoid compile warning + } + int r = system(buff); + if (r<0) fprintf(stderr, "aflibDebug, system() failed\n"); +} + +/* + * Display a message using output_message. If the message is the same + * as the previous one, just increment a count but don't display + * it. This prevents flooding the user with duplicate warnings. If the + * message is not the same as the previous one, then we report the + * previously repeated message (if any) and reset the last message and + * count. + */ +void display_message(::aflibDebug::Level level, const char *msg) { + static char lastMsg[1024]; + static ::aflibDebug::Level lastLevel; + static int msgCount = 0; + + if (!strncmp(msg, lastMsg, 1024)) + { + msgCount++; + } else { + if (msgCount > 0) + { + char buff[1024]; + sprintf(buff, "%s\n(The previous message was repeated %d times.)", lastMsg, msgCount); + output_message(lastLevel, buff); + } + + strncpy(lastMsg, msg, 1024); + lastLevel = level; + msgCount = 0; + output_message(level, msg); + } + +} + +static class DebugInitFromEnv { + + public: + DebugInitFromEnv() { + const char *env = getenv("AFLIB_DEBUG"); + if(env) + { + if(strcmp(env,"debug") == 0) + aflib_debug_level = ::aflibDebug::lDebug; + else if(strcmp(env,"info") == 0) + aflib_debug_level = ::aflibDebug::lInfo; + else if(strcmp(env,"warning") == 0) + aflib_debug_level = ::aflibDebug::lWarning; + else if(strcmp(env,"quiet") == 0) + aflib_debug_level = ::aflibDebug::lFatal; + else + { + fprintf(stderr, + "AFLIB_DEBUG must be one of debug,info,warning,quiet\n"); + } + } + + env = getenv("AFLIB_DEBUG_ABORT"); + if(env) + aflib_debug_abort = true; + } +} + +debugInitFromEnv; + + +void aflibDebug::init(const char *prefix, Level level) +{ + aflib_debug_level = level; + aflib_debug_prefix = prefix; +} + +void aflibDebug::fatal(const char *fmt, ...) +{ + char buff[1024]; + va_list ap; + va_start(ap, fmt); + vsprintf(buff, fmt, ap); + va_end(ap); + display_message(::aflibDebug::lFatal, buff); + + if(aflib_debug_abort) abort(); + exit(1); +} + +void aflibDebug::warning(const char *fmt, ...) +{ + if(lWarning >= aflib_debug_level) + { + char buff[1024]; + va_list ap; + va_start(ap, fmt); + vsprintf(buff, fmt, ap); + va_end(ap); + display_message(::aflibDebug::lWarning, buff); + } +} + +void aflibDebug::info(const char *fmt, ...) +{ + if(lInfo >= aflib_debug_level) + { + char buff[1024]; + va_list ap; + va_start(ap, fmt); + vsprintf(buff, fmt, ap); + va_end(ap); + display_message(::aflibDebug::lInfo, buff); + } +} + +void aflibDebug::debug(const char *fmt, ...) +{ + if(lDebug >= aflib_debug_level) + { + char buff[1024]; + va_list ap; + va_start(ap, fmt); + vsprintf(buff, fmt, ap); + va_end(ap); + display_message(::aflibDebug::lDebug, buff); + } +} + +void aflibDebug::messageApp(const char *appName) +{ + messageAppName = (char*) realloc(messageAppName, strlen(appName)+1); + strcpy(messageAppName, appName); +} diff --git a/darkice/tags/darkice-1_3/src/aflibDebug.h b/darkice/tags/darkice-1_3/src/aflibDebug.h new file mode 100644 index 0000000..ea7dd99 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/aflibDebug.h @@ -0,0 +1,118 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + + Some inspiration taken from glib. + Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + Modified by the GLib Team and others 1997-1999. + + */ + +#ifndef _AFLIBDEBUG_H_ +#define _AFLIBDEBUG_H_ + +/* + * BC - Status (2000-09-30): Debug. + * + * Collection class, no instance, no members. Thus binary compatible (will + * be kept). + */ + +#define aflib_fatal ::aflibDebug::fatal +#define aflib_warning ::aflibDebug::warning +#define aflib_info ::aflibDebug::info +#define aflib_debug ::aflibDebug::debug + +/* source compatibility with older sources */ +#define aflibdebug ::aflibDebug::debug +#define setaflibdebug(x) aflib_warning("setaflibdebug is obsolete") + +#ifdef __GNUC__ + +#define aflib_return_if_fail(expr) \ + if (!(expr)) \ + { \ + aflib_warning ("file %s: line %d (%s): assertion failed: (%s)", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \ + return; \ + } + +#define aflib_return_val_if_fail(expr,val) \ + if (!(expr)) \ + { \ + aflib_warning ("file %s: line %d (%s): assertion failed: (%s)", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \ + return (val); \ + } + +#define aflib_assert(expr) \ + if (!(expr)) \ + aflib_fatal ("file %s: line %d (%s): assertion failed: (%s)", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \ + +#else + +#define aflib_return_if_fail(expr) \ + if (!(expr)) \ + { \ + aflib_warning ("file %s: line %d: assertion failed: (%s)", \ + __FILE__, __LINE__, #expr); \ + return; \ + } + +#define aflib_return_val_if_fail(expr,val) \ + if (!(expr)) \ + { \ + aflib_warning ("file %s: line %d: assertion failed: (%s)", \ + __FILE__, __LINE__, #expr); \ + return (val); \ + } + +#define aflib_assert(expr) \ + if (!(expr)) \ + aflib_fatal ("file %s: line %d: assertion failed: (%s)", \ + __FILE__, __LINE__, #expr); \ + +#endif + +class aflibDebug { + public: + enum Level { lFatal = 3, lWarning = 2, lInfo = 1, lDebug = 0 }; + + /** + * Initializes at which is the minimum level to react to. If you + * call this, call this before creating the Arts::Dispatcher object. + */ + static void init(const char *prefix, Level level); + + static void fatal(const char *fmt,...); // print on stderr & abort + static void warning(const char *fmt,...); // print on stderr + static void info(const char *fmt,...); // print on stdout + static void debug(const char *fmt,...); // print on stdout + + /** + * This method sets the name of an external application to + * display messages graphically. + */ + static void messageApp(const char *appName); + + }; + +#endif diff --git a/darkice/tags/darkice-1_3/src/main.cpp b/darkice/tags/darkice-1_3/src/main.cpp new file mode 100644 index 0000000..b079926 --- /dev/null +++ b/darkice/tags/darkice-1_3/src/main.cpp @@ -0,0 +1,201 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved. + + Tyrell DarkIce + + File : main.cpp + Version : $Revision$ + Author : $Author$ + Location : $HeadURL$ + + Abstract : + + Program entry point + + Copyright notice: + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STDLIB_H +#include +#else +#error needs stdlib.h +#endif + +#ifdef HAVE_SIGNAL_H +#include +#else +#error needs signal.h +#endif + +#include +#include + +#include "Ref.h" +#include "Exception.h" +#include "Util.h" +#include "DarkIce.h" + + +/* =================================================== local data structures */ + +/*------------------------------------------------------------------------------ + * The DarkIce object we're running + *----------------------------------------------------------------------------*/ +static Ref darkice; + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + +/*------------------------------------------------------------------------------ + * Default config file name + *----------------------------------------------------------------------------*/ +static const char *DEFAULT_CONFIG_FILE = "/etc/darkice.cfg"; + + +/* =============================================== local function prototypes */ + +/*------------------------------------------------------------------------------ + * Show program usage + *----------------------------------------------------------------------------*/ +static void +showUsage ( std::ostream & os ); + +/*------------------------------------------------------------------------------ + * Handler for the SIGUSR1 signal + *----------------------------------------------------------------------------*/ +static void +sigusr1Handler(int value); + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Program entry point + *----------------------------------------------------------------------------*/ +int +main ( + int argc, + char * argv[] ) +{ + int res = -1; + + std::cout << "DarkIce " << VERSION + << " live audio streamer, http://code.google.com/p/darkice/" + << std::endl + << "Copyright (c) 2000-2007, Tyrell Hungary, http://tyrell.hu/" + << std::endl + << "Copyright (c) 2008-2013, Akos Maroy and Rafael Diniz" + << std::endl + << "This is free software, and you are welcome to redistribute it " + << std::endl + << "under the terms of The GNU General Public License version 3 or" + << std::endl + << "any later version." + << std::endl << std::endl; + + try { + const char * configFileName = DEFAULT_CONFIG_FILE; + unsigned int verbosity = 1; + int i; + const char opts[] = "hc:v:"; + + while ( (i = getopt( argc, argv, opts)) != -1 ) { + switch ( i ) { + case 'c': + configFileName = optarg; + break; + + case 'v': + verbosity = Util::strToL( optarg); + break; + + default: + case ':': + case '?': + case 'h': + showUsage( std::cout); + return 1; + } + } + + std::cout << "Using config file: " << configFileName << std::endl; + + std::ifstream configFile( configFileName); + Reporter::setReportVerbosity( verbosity ); + Reporter::setReportOutputStream( std::cout ); + Config config( configFile); + + darkice = new DarkIce( config); + + signal(SIGUSR1, sigusr1Handler); + + res = darkice->run(); + + } catch ( Exception & e ) { + std::cout << "DarkIce: " << e << std::endl << std::flush; + } + + return res; +} + + +/*------------------------------------------------------------------------------ + * Show program usage + *----------------------------------------------------------------------------*/ +static void +showUsage ( std::ostream & os ) +{ + os + << "usage: darkice [-v n] -c config.file" + << std::endl + << std::endl + << "options:" + << std::endl + << " -c config.file use configuration file config.file" + << std::endl + << " if not specified, /etc/darkice.cfg is used" + << std::endl + << " -v n verbosity level (0 = silent, 10 = loud)" + << std::endl + << " -h print this message and exit" + << std::endl + << std::endl; +} + + +/*------------------------------------------------------------------------------ + * Handle the SIGUSR1 signal here + *----------------------------------------------------------------------------*/ +static void +sigusr1Handler(int value) +{ + darkice->cut(); +} + diff --git a/darkice/tags/darkice-1_3/stamp-h.in b/darkice/tags/darkice-1_3/stamp-h.in new file mode 100644 index 0000000..9788f70 --- /dev/null +++ b/darkice/tags/darkice-1_3/stamp-h.in @@ -0,0 +1 @@ +timestamp