muroard-0.1.14/0000755000175000017500000000000012210617635011373 5ustar phiphimuroard-0.1.14/AUTHORS0000644000175000017500000000011511342672627012447 0ustar phiphi--- Main Developer: * Philipp 'ph3-der-loewe' Schafft muroard-0.1.14/COPYING.gplv30000644000175000017500000010451311342666134013467 0ustar phiphi 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 . muroard-0.1.14/ChangeLog0000644000175000017500000001006012210617414013135 0ustar phiphiv. 0.1.14 - Sun Sep 01 2013 13:03 CEST * Applied patch from Debian adding status command to init script. * Check arguments passed to the argv[] parser (Closes: DEB#716570) * Applied 03-init-source-functions from Debian to debian-like init script. * Code Cleanup. * Updated code and documentation on -sD. v. 0.1.13 - Mon Jun 10 2013 26:47 CEST * Added tinyalsa driver. * Updated copyright statements. v. 0.1.12 - Mon Dec 10 2012 13:04 CET * Updated win32 port. * Avoid warnings generated by libvorbisfile header. * Fixed resource leak in case adding a source failed. v. 0.1.11 - Mon Sep 17 2012 22:11 CEST * Updated SONAME infos in ckport database. v. 0.1.10 - Sun May 13 2012 27:54 CEST * Updates to documentation and comments. * Added muroard_mainloop_iteration() to support a non-blocking mainloop. * Changed SONAME (required by muroard_mainloop_iteration()). * Make complet global state visible via the single variable of muroard_g_state. This allows running multiple instances within a single process. * Fixed win32 port. * Corrected namespace conflict (struct muroard_audio_info). * Support sending a dummy client name. v. 0.1.9 - Tue Nov 08 2011 17:07 CET * Added codec filter vor ogg_vorbis. * Build library with backend (driver) as well. * Changed SONAME (required by codec filter ogg_vorbis). * Added support for a source stream. v. 0.1.8 - Sat Sep 17 2011 18:00 CEST * Started to merge stuff from the YIFF port. * Support DECnet (and updated Debian init script) (Closes: #167) * Added support for networks with MTU smaller than cycle buffer size. (I/O re-reads and re-writes) * Added version display (--version) (Closes: #170) v. 0.1.7 - Sun Jul 10 2011 17:46 CEST * Fixed a missing mkdir in Makefile * Fixed memory locking bug preventing startup on eeemsi's system. * Fixed problems with TCP sockets again. This now also fixes it for eeemsi. v. 0.1.6 - Sat Jul 09 2011 12:16 CEST * Fixed super long delay in WMM driver. * Small updates of manpage. * Added support for GETTIMEOFDAY command (Closes: #163) * Added support for standby and autostandby (Closes: #41) * Addec codec filters: au, riff_wave (Closes: #44) * Added support for stream positions (Closes: #164) * Added ckports database. v. 0.1.5 - Fri Jun 17 2011 17:21 CET * Moved common driver settings into feature.h * Added support for non-malloc systems * Added support to lock memory at startup * Updated everything so we no longer use MUROAR_ namespace as well * Do some work to get build progess smoother on win32 * Added WMM driver (Closes: #40) * Support setting driver using configure script v. 0.1.4 - Thu feb 24 2011 28:59 CET * Added support for SERVER_INFO/ITST_VERSION (Closes: #124) * Added volume support (Closes: #22) * Renamed all macros to include muroard_-prefix * Updated Debian init script (Closes: DEB#613772) v. 0.1.3 - Tue Jan 18 2011 21:46 CET * Fixed Debian init script to ensure muroard is shutted down when it finished (Closes: DEB#608812) * Updated debian init script (Closes: #60) * Build most parts as library. (Closes: #120, #118) v. 0.1.2 - Thu Dec 02 2010 16:29 CET * fixes very small memory leak in libao driver. * Added support for CAPS/Standards command (Closes: #11) * Reject OINFO commands with dir parameter set (Closes: #88) * Ported to support clang. v. 0.1.1 - Fri Sep 24 2010 28:31 CEST * fixed libao driver for libao4 v. 0.1.0 - Mon Jul 05 2010 22:34 CEST * added support for background streams v. 0.1beta3 - Tue Apr 20 2010 21:45 CEST * small copyright fixes * updated debian init script v. 0.1beta2 - Sun Apr 04 2010 10:34 CEST * mostly fixed PAUSE bug * added support to daemonize * added support to set file modus on socket * support for upmix/downmix/upscale/downscale/byte swap * small fixes for random failtures * added drivers: esd, sndio v. 0.1beta1 - Mon Mar 22 2010 24:07 CET * added init script (debian) * updated debian/* * fixed bug in oss driver * support for termination state * support more general driver interface * added µRoar driver v. 0.1beta0 - Wed Mar 03 2010 24:26 CET * start of project / inital release muroard-0.1.14/Makefile0000644000175000017500000001000512050302616013017 0ustar phiphiinclude Makefile.conf LIBNAME=libmuroard SOVERSION = 3 PREFIX_CKPORT=$(PREFIX_LIB)/ckport/db/ SLIB_BASE=$(LIBNAME)$(SHARED_SUFFIX) SLIB=$(SLIB_BASE).$(SOVERSION) ALIB=$(LIBNAME).a LIBNAME_BKEND=$(LIBNAME)-backend SLIB_BKEND_BASE=$(LIBNAME_BKEND)$(SHARED_SUFFIX) SLIB_BKEND=$(SLIB_BKEND_BASE).$(SOVERSION) ALIB_BKEND=$(LIBNAME_BKEND).a BIN=muroard MANPAGE=$(BIN).1 CKPORTDB=$(LIBNAME).ckport TARGETS=$(ALIB) $(ALIB_BKEND) $(BIN) ifeq ($(BUILD_SHARED),true) TARGETS += $(SLIB) $(SLIB_BKEND) endif HEADER=muroard.h clients.h deps.h driver.h dsp.h features.h memmgr.h network.h para.h proto.h streams.h waveform.h callbacks.h cf.h state.h OBJS_CF=cf_au.o cf_riff_wave.o cf_ogg_vorbis.o OBJS=muroard.o para.o network.o waveform.o proto.o dsp.o clients.o streams.o memmgr.o $(OBJS_CF) OBJS_DRIVER=driver.o OBJS_MAIN=main.o DEFINES += -DPACKAGE_VERSION="\"$(VERSION)\"" -DDEVICE_VENDOR_ID=$(DEV_VENDOR) -DDEVICE_VENDOR_NAME="\"$(DEV_VENDOR_NAME)\"" -DDEVICE_VENDOR_STRING="\"$(DEV_VENDOR_STRING)\"" -DDISTRIBUTION_VERSION_STRING="\"$(DISTRIBUTION_VERSION_STRING)\"" $(TARGET_MICROCONTROLLER) $(DRIVER_def) $(def_dnet_daemon) $(def_vorbisfile) CFLAGS += -Wall $(Wextra) $(fPIC) -g -O2 $(INCPATH) $(DEFINES) LDFLAGS += -Wall $(Wextra) -g -O2 $(LDPATH) CONTLIBS = $(lib_vorbisfile) NETLIBS = $(lib_wsock32) $(lib_ws2_32) $(lib_dnet_daemon) LIBS += $(CONTLIBS) $(NETLIBS) $(DRIVER_LIBS) all: ${TARGETS} clean: rm -f ${TARGETS} *.o distclean: clean rm -f Makefile.conf config.log new: clean all prep-install-dirs: mkdir -p '$(DESTDIR)$(PREFIX_LIB)' mkdir -p '$(DESTDIR)$(PREFIX_INC)'/muroard mkdir -p '$(DESTDIR)$(PREFIX_BIN)' mkdir -p '$(DESTDIR)$(PREFIX_MAN)/man1' mkdir -p '$(DESTDIR)$(PREFIX_CKPORT)' install: all prep-install-dirs ifeq ($(BUILD_SHARED),true) cp $(cp_v) $(SLIB) '$(DESTDIR)$(PREFIX_LIB)' cp $(cp_v) $(SLIB_BKEND) '$(DESTDIR)$(PREFIX_LIB)' endif cp $(cp_v) $(ALIB) '$(DESTDIR)$(PREFIX_LIB)' cp $(cp_v) $(ALIB_BKEND) '$(DESTDIR)$(PREFIX_LIB)' cp $(cp_v) $(HEADER) '$(DESTDIR)$(PREFIX_INC)/muroard/' cp $(cp_v) $(BIN) '$(DESTDIR)$(PREFIX_BIN)' cp $(cp_v) $(MANPAGE) '$(DESTDIR)$(PREFIX_MAN)/man1/' cp $(cp_v) $(CKPORTDB) '$(DESTDIR)$(PREFIX_CKPORT)' ifeq ($(BUILD_SHARED),true) ln -fs $(SLIB) '$(DESTDIR)$(PREFIX_LIB)'/$(SLIB_BASE) ln -fs $(SLIB_BKEND) '$(DESTDIR)$(PREFIX_LIB)'/$(SLIB_BKEND_BASE) endif semi-install: all prep-install-dirs ifeq ($(BUILD_SHARED),true) ln -fs `pwd`/$(SLIB) '$(DESTDIR)$(PREFIX_LIB)' ln -fs `pwd`/$(SLIB_BKEND) '$(DESTDIR)$(PREFIX_LIB)' endif ln -fs `pwd`/$(ALIB) '$(DESTDIR)$(PREFIX_LIB)' ln -fs `pwd`/$(ALIB_BKEND) '$(DESTDIR)$(PREFIX_LIB)' set -e; for i in $(HEADER); do ln -fs `pwd`/$$i '$(DESTDIR)$(PREFIX_INC)/muroard/'; done ln -fs `pwd`/$(BIN) '$(DESTDIR)$(PREFIX_BIN)' ln -fs `pwd`/$(MANPAGE) '$(DESTDIR)$(PREFIX_MAN)/man1/' ln -fs `pwd`/$(CKPORTDB) '$(DESTDIR)$(PREFIX_CKPORT)' ifeq ($(BUILD_SHARED),true) ln -fs $(SLIB) '$(DESTDIR)$(PREFIX_LIB)'/$(SLIB_BASE) ln -fs $(SLIB_BKEND) '$(DESTDIR)$(PREFIX_LIB)'/$(SLIB_BKEND_BASE) endif uninstall: rm -f '$(DESTDIR)$(PREFIX_LIB)'/$(SLIB) rm -f '$(DESTDIR)$(PREFIX_LIB)'/$(ALIB) rm -f '$(DESTDIR)$(PREFIX_LIB)'/$(SLIB_BKEND) rm -f '$(DESTDIR)$(PREFIX_LIB)'/$(ALIB_BKEND) rm -fr '$(DESTDIR)$(PREFIX_INC)/muroard/' rm -f '$(DESTDIR)$(PREFIX_LIB)'/$(SLIB_BASE) rm -f '$(DESTDIR)$(PREFIX_LIB)'/$(SLIB_BKEND_BASE) rm -f '$(DESTDIR)$(PREFIX_BIN)'/$(BIN) rm -f '$(DESTDIR)$(PREFIX_MAN)'/man1/$(MANPAGE) rm -f '$(DESTDIR)$(PREFIX_CKPORT)'/$(CKPORTDB) muroard: $(OBJS) $(OBJS_DRIVER) $(OBJS_MAIN) ${CC} ${LDFLAGS} -o muroard $(OBJS) $(OBJS_DRIVER) $(OBJS_MAIN) ${LIBS} $(SLIB): ${OBJS} ${CC} ${LDFLAGS} $(SHARED) -Wl,-soname,$(SLIB) -o $(SLIB) ${OBJS} ${LIBS} $(ALIB): ${OBJS} ${AR} cru $(ALIB) ${OBJS} ${RANLIB} $(ALIB) $(SLIB_BKEND): ${OBJS_DRIVER} ${CC} ${LDFLAGS} $(SHARED) -Wl,-soname,$(SLIB_BKEND) -o $(SLIB_BKEND) ${OBJS_DRIVER} $(DRIVER_LIBS) $(ALIB_BKEND): ${OBJS_DRIVER} ${AR} cru $(ALIB_BKEND) ${OBJS_DRIVER} ${RANLIB} $(ALIB_BKEND) driver.o: driver.c driver_*.c muroard-0.1.14/README0000644000175000017500000000451112210617414012247 0ustar phiphi µRoarD ---------- --- What is µRoarD?: µRoarD is a minimalist RoarAudio sound server which is limited in a lot of why but optimized for being fast and small. --- Build: -- Build requirements: A POSIX system and installed libmuroar(-dev). libmuroar (µRoar) is only needed to build. It is no runtime dependency expect the case you use the µRoar driver. -- How to configure: In order to configure µRoarD just edit the features.h header file. Depending on your Operating System you may need to adjust the setting MUROAR_FEATURE_DRIVER. It defaults to the OSS driver. It works on most system but not all. Some Systems out there miss OSS support. You can try a different driver then. The libao driver comes with a lot OS backends but is not easy to compile on your one on most of the systems not including OSS support. You may also need to update the Makefile in case you build a driver requiring a dynamic library. In addition please not that some OS also need a library for OSS. Please refer to your Operating System documentation and the documentation of the backend you try to build a driver for. If you change your network settings you may also need to just MUROAR_DEFAULT_LISTEN_TYPE as you else may get invalid defaults. -- How to build: $ ./configure $ make --- Tested platforms: OPERATING SYSTEM ARCH COMPILER TESTED M/STATUS COMMENT AND VERSION VERSION --------------------------------------------------------------------------------------------------- Debian Etch ix86 gcc 4.1.2 last s/OK Debian Etch x86_64 gcc 4.1.2 0.1.13 s/OK Debian Lenny ix86 gcc * ? s/OK Debian Wheezy x86_64 gcc 4.7.2 0.1.14 s/OK Debian Sid ix86 gcc 4.6.1 0.1.10 M/OK Debian Sid ix86 clang 2.7 0.1.3 s/OK OpenBSD 4.4 ix86 gcc 3.3.5 0.1.9 s/OK Win32 ix86 mingw* 0.1.7 s/OK Debian * * * M/OK This package is part of Debian > Lenny Tested Version: Current: Current as listed on Homepage last: Last released version (This system is on release checklist) *b*: Beta Status: Maintenance/testing Status: Maintenance: s = your are on your own, sources. m = package in work, beta package M = maintained S = maintained source package B = maintained binary package muroard-0.1.14/TODO0000644000175000017500000000033711714514373012071 0ustar phiphiMore Tickets on BTS at: https://bts.keep-cool.org/ Things we need to do: * (#39) support connect stream Things we should do: * update manpage, make it better * (#42) support meta data Things it would be nice to have: muroard-0.1.14/callbacks.h0000644000175000017500000000176712126652352013477 0ustar phiphi//callbacks.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _MUROARD_CALLBACKS_H_ #define _MUROARD_CALLBACKS_H_ #endif //ll muroard-0.1.14/cf.h0000644000175000017500000000303012126652352012131 0ustar phiphi//cf.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _MUROARD_CF_H_ #define _MUROARD_CF_H_ #ifdef MUROARD_FEATURE_CODECFILTER #ifdef MUROARD_FEATURE_CODECFILTER_AU ssize_t muroard_cf_au_read(int id, struct muroard_stream * stream, void * buf, size_t len); #endif #ifdef MUROARD_FEATURE_CODECFILTER_RIFF_WAVE ssize_t muroard_cf_riff_wave_read(int id, struct muroard_stream * stream, void * buf, size_t len); #endif #ifdef MUROARD_FEATURE_CODECFILTER_OGG_VORBIS ssize_t muroard_cf_ogg_vorbis_read (int id, struct muroard_stream * stream, void * buf, size_t len); int muroard_cf_ogg_vorbis_close(int id, struct muroard_stream * stream); #endif #endif #endif //ll muroard-0.1.14/cf_au.c0000644000175000017500000000633412126652353012624 0ustar phiphi//cf_au.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2011-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #if defined(MUROARD_FEATURE_CODECFILTER) && defined(MUROARD_FEATURE_CODECFILTER_AU) static void muroard_cf_au_read_extra_header (int id, struct muroard_stream * stream) { char buf[128]; ssize_t ret; size_t size; while ( stream->cf_data.au.dataoffset ) { size = (size_t)stream->cf_data.au.dataoffset > sizeof(buf) ? sizeof(buf) : (size_t)stream->cf_data.au.dataoffset; ret = muroard_stream_network_read(id, buf, size); if ( ret < 1 ) return; stream->cf_data.au.dataoffset -= ret; } } ssize_t muroard_cf_au_read(int id, struct muroard_stream * stream, void * buf, size_t len) { uint32_t data[6]; unsigned int i; int processed_header = 0; if ( !stream->cf_data.au.headeroffset ) { processed_header = 1; stream->cf_data.au.dataoffset = 24; stream->cf_data.au.headeroffset = muroard_stream_network_read(id, data, sizeof(data)); if ( stream->cf_data.au.headeroffset != stream->cf_data.au.dataoffset ) return -1; for (i = 0; i < (sizeof(data)/sizeof(*data)); i++) data[i] = ntohl(data[i]); if ( data[0] != 0x2e736e64 ) /* magic, ".snd" */ return -1; if ( data[1] < (uint32_t)stream->cf_data.au.dataoffset ) return -1; stream->cf_data.au.dataoffset = data[1]; stream->cf_data.au.dataoffset -= stream->cf_data.au.headeroffset; if ( data[4] != (uint32_t)muroard_state_member(sa_rate) ) return -1; stream->info.channels = data[5]; switch (data[3]) { case 1: stream->info.bits = 8; stream->info.codec = MUROAR_CODEC_MULAW; break; case 2: stream->info.bits = 8; stream->info.codec = MUROAR_CODEC_PCM_S; break; case 3: stream->info.bits = 16; stream->info.codec = MUROAR_CODEC_PCM_S_BE; break; case 4: stream->info.bits = 24; stream->info.codec = MUROAR_CODEC_PCM_S_BE; break; case 5: stream->info.bits = 32; stream->info.codec = MUROAR_CODEC_PCM_S_BE; break; case 27: stream->info.bits = 8; stream->info.codec = MUROAR_CODEC_ALAW; break; default: return -1; break; } if ( muroard_stream_cksupport(&(stream->info), STREAM_DATADIR_IN) != 1 ) return -1; } if ( stream->cf_data.au.dataoffset ) { processed_header = 1; muroard_cf_au_read_extra_header(id, stream); } if ( stream->cf_data.au.dataoffset || processed_header ) { *(char*)buf = 0; return 1; } return muroard_stream_network_read(id, buf, len); } #endif //ll muroard-0.1.14/cf_ogg_vorbis.c0000644000175000017500000000665012126652353014360 0ustar phiphi//cf_ogg_vorbis.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #if defined(MUROARD_FEATURE_CODECFILTER) && defined(MUROARD_FEATURE_CODECFILTER_OGG_VORBIS) #if ROAR_CODEC_DEFAULT == ROAR_CODEC_PCM_S_LE #define _bigendianp 0 #define _codec MUROAR_CODEC_PCM #else #define _bigendianp 1 #define _codec MUROAR_CODEC_PCM_S_BE // force because ROAR_CODEC_DEFAULT can be something non-BE, too. #endif static int muroard_cf_ogg_vorbis_private_return_err (void) { return -1; } static size_t muroard_cf_ogg_vorbis_private_read (void *ptr, size_t size, size_t nmemb, void *datasource) { ssize_t r; r = muroard_stream_network_read(((struct muroard_stream *)datasource)->cf_data.ogg_vorbis.stream_id, ptr, size*nmemb); if ( r == -1 ) { return 0; } r /= size; return r; } static const ov_callbacks _callbacks = { .read_func = muroard_cf_ogg_vorbis_private_read, .seek_func = (int (*)(void *, ogg_int64_t, int )) muroard_cf_ogg_vorbis_private_return_err, .close_func = (int (*)(void * )) muroard_cf_ogg_vorbis_private_return_err, .tell_func = (long (*)(void * )) muroard_cf_ogg_vorbis_private_return_err }; ssize_t muroard_cf_ogg_vorbis_read(int id, struct muroard_stream * stream, void * buf, size_t len) { vorbis_info * vi; int current_section; long r; long todo = len; long done = 0; int ret; if ( !stream->cf_data.ogg_vorbis.opened ) { stream->cf_data.ogg_vorbis.stream_id = id; if ( (ret = ov_open_callbacks((void*)stream, &(stream->cf_data.ogg_vorbis.vf), NULL, 0, _callbacks)) < 0 ) { return -1; } vi = ov_info(&(stream->cf_data.ogg_vorbis.vf), -1); if ( vi->rate != muroard_state_member(sa_rate) ) { ov_clear(&(stream->cf_data.ogg_vorbis.vf)); return -1; } stream->info.channels = vi->channels; stream->info.bits = 16; stream->info.codec = _codec; if ( muroard_stream_cksupport(&(stream->info), STREAM_DATADIR_IN) != 1 ) { ov_clear(&(stream->cf_data.ogg_vorbis.vf)); return -1; } stream->cf_data.ogg_vorbis.opened = 1; } while (todo) { r = ov_read(&(stream->cf_data.ogg_vorbis.vf), buf+done, todo, _bigendianp, 2, 1, ¤t_section); if ( r == OV_HOLE ) { } else if ( r < 1 ) { break; } else { todo -= r; done += r; } } if ( done == 0 ) { // do some EOF handling... return 0; } else { return len; } } int muroard_cf_ogg_vorbis_close(int id, struct muroard_stream * stream) { (void)id; if ( !stream->cf_data.ogg_vorbis.opened ) return 0; ov_clear(&(stream->cf_data.ogg_vorbis.vf)); return 0; } #endif //ll muroard-0.1.14/cf_riff_wave.c0000644000175000017500000000445212126652353014166 0ustar phiphi//cf_riff_wave.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2011-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #if defined(MUROARD_FEATURE_CODECFILTER) && defined(MUROARD_FEATURE_CODECFILTER_RIFF_WAVE) ssize_t muroard_cf_riff_wave_read(int id, struct muroard_stream * stream, void * buf, size_t len) { unsigned char header[44]; uint32_t tmp; (void)len; if ( muroard_stream_network_read(id, header, 44) != 44 ) return -1; if ( strncmp((char*)header+ 0, "RIFF", 4) != 0 || strncmp((char*)header+ 8, "WAVE", 4) != 0 || strncmp((char*)header+12, "fmt ", 4) != 0 || strncmp((char*)header+36, "data", 4) != 0 ) return -1; tmp = (uint32_t)header[20] + ((uint32_t)header[21] << 8); switch (tmp) { case 0x0001: stream->info.codec = MUROAR_CODEC_PCM_S_LE; break; case 0x0006: stream->info.codec = MUROAR_CODEC_ALAW; break; case 0x0007: stream->info.codec = MUROAR_CODEC_MULAW; break; default: return -1; break; } tmp = (uint32_t)header[22] + ((uint32_t)header[23] << 8); stream->info.channels = tmp; tmp = (uint32_t)header[24] + ((uint32_t)header[25] << 8) + ((uint32_t)header[26] << 16) + ((uint32_t)header[27] << 24); if ( tmp != (uint32_t)muroard_state_member(sa_rate) ) return -1; tmp = (uint32_t)header[34] + ((uint32_t)header[35] << 8); stream->info.bits = tmp; if ( muroard_stream_cksupport(&(stream->info), STREAM_DATADIR_IN) != 1 ) return -1; stream->cf_read = NULL; *(char*)buf = 0; return 1; } #endif //ll muroard-0.1.14/clients.c0000644000175000017500000004725212210335316013203 0ustar phiphi//clients.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #ifdef MUROARD_FEATURE_CMD_GETTIMEOFDAY #include #endif #define _FILTER_ANY 0 int muroard_client_init(void) { memset(muroard_state_member(client), 0, sizeof(muroard_state_member(client))); // state unused = 0! #ifdef MUROARD_FEATURE_INTERNAL_CLIENT muroard_state_member(client)[0].state = CLIENT_STATE_INTERNAL; muroard_state_member(client)[0].sock = MUROARD_HANDLE_INVALID; muroard_state_member(client)[0].stream = -1; #endif return 0; } int muroard_client_free(void) { int i; int ret = 0; for (i = 0; i < MUROARD_MAX_CLIENTS; i++) { if ( muroard_state_member(client)[i].state != CLIENT_STATE_UNUSED ) { if ( muroard_client_delete(i) == -1 ) ret = -1; } } return ret; } int muroard_client_new(muroard_handle_t sock) { int i; if ( muroard_network_nonblock(sock, 0) == -1 ) return -1; for (i = 0; i < MUROARD_MAX_CLIENTS; i++) { if ( muroard_state_member(client)[i].state == CLIENT_STATE_UNUSED ) { muroard_state_member(client)[i].state = CLIENT_STATE_NEW; muroard_state_member(client)[i].sock = sock; muroard_state_member(client)[i].stream = -1; return i; } } return -1; } int muroard_client_delete(int id) { int ret = 0; if ( id >= MUROARD_MAX_CLIENTS || id < 0 ) return -1; #ifdef MUROARD_FEATURE_INTERNAL_CLIENT if ( muroard_state_member(client)[id].state == CLIENT_STATE_INTERNAL ) return 0; #endif if ( muroard_state_member(client)[id].state == CLIENT_STATE_UNUSED || muroard_state_member(client)[id].state == CLIENT_STATE_CLOSING ) return 0; muroard_state_member(client)[id].state = CLIENT_STATE_CLOSING; if ( muroard_state_member(client)[id].stream != -1 ) { if ( muroard_stream_delete(muroard_state_member(client)[id].stream) == -1 ) ret = -1; } if ( muroard_state_member(client)[id].sock != MUROARD_HANDLE_INVALID ) { muroard_network_close(muroard_state_member(client)[id].sock); } muroard_state_member(client)[id].state = CLIENT_STATE_UNUSED; return ret; } muroard_handle_t muroard_client_exec(int id) { muroard_handle_t sock = muroard_state_member(client)[id].sock; muroard_state_member(client)[id].sock = MUROARD_HANDLE_INVALID; muroard_state_member(client)[id].state = CLIENT_STATE_EXECED; return sock; } int muroard_client_handle(int id) { struct muroard_message m; muroard_handle_t sock = muroard_state_member(client)[id].sock; int ret = 0; #ifdef MUROARD_FEATURE_VOLUME_CONTROL uint16_t volume; size_t channels; uint16_t tmp; #endif if ( muroard_proto_recv(sock, &m) == -1 ) { muroard_client_delete(id); return -1; } if ( m.stream > MUROARD_MAX_STREAMS && m.stream != (uint16_t)-1 ) { ret = -1; } else { switch (m.cmd) { case MUROAR_CMD_NOOP: case MUROAR_CMD_IDENTIFY: case MUROAR_CMD_AUTH: #ifdef MUROARD_FEATURE_NOOP_SIUCMDS case MUROAR_CMD_SET_META: #endif // no need to do anything m.datalen = 0; break; case MUROAR_CMD_QUIT: m.cmd = MUROAR_CMD_OK; m.datalen = 0; muroard_proto_send(sock, &m); muroard_client_delete(id); return 0; break; case MUROAR_CMD_EXEC_STREAM: m.datalen = 0; if ( m.stream != (uint16_t)-1 && m.stream == muroard_state_member(client)[id].stream ) { if ( muroard_stream_exec(m.stream) == -1 ) ret = -1; } else { ret = -1; } break; #ifdef MUROARD_FEATURE_CMD_WHOAMI case MUROAR_CMD_WHOAMI: m.datalen = 1; m.data[0] = id; break; #endif #ifdef MUROARD_FEATURE_CMD_EXIT case MUROAR_CMD_EXIT: // we simply set muroard_state_member(alive) to zero so we will die with the next cycle. if ( m.datalen == 0 ) { // default: exit muroard_state_member(alive) = 0; } else if ( m.datalen == 1 && m.data[0] == 0 ) { // explicit: exit muroard_state_member(alive) = 0; #ifndef MUROARD_FEATURE_TERMINATE } else if ( m.datalen == 1 && m.data[0] == 1 ) { // explicit: terminate ret = muroard_network_prefree(); #endif } else { // terminate or unsupported command version ret = -1; } m.datalen = 0; break; #endif #ifdef MUROARD_FEATURE_STANDBY case MUROAR_CMD_SET_STANDBY: if ( m.datalen != 2 ) { ret = -1; } else { if ( m.data[0] != 0 ) { ret = -1; } else { switch (m.data[1]) { case 0: muroard_waveform_standby(0, -1); break; case 1: muroard_waveform_standby(1, -1); break; default: ret = -1; } } } break; #endif #ifdef MUROARD_FEATURE_CMD_GET_STANDBY case MUROAR_CMD_GET_STANDBY: m.datalen = 2; m.data[0] = 0; #ifdef MUROARD_FEATURE_STANDBY m.data[1] = muroard_waveform_standby(-1, -1); #else m.data[1] = 0; #endif break; #endif #ifdef MUROARD_FEATURE_CMD_GET_VOL case MUROAR_CMD_GET_VOL: // we support only the most up to date version of the command: if ( m.datalen < 2 || m.data[0] != 0 || m.data[1] != 1 || m.stream == (uint16_t)-1 ) { ret = -1; } else { m.datalen = 6*2; // version: 1 m.data[ 0] = 0; m.data[ 1] = 1; // channels: 1 m.data[ 2] = 0; m.data[ 3] = 1; // scale: m.data[ 4] = 0xFF; m.data[ 5] = 0xFF; // rpg mul: m.data[ 6] = 0; m.data[ 7] = 1; // rpg div: m.data[ 8] = 0; m.data[ 9] = 1; // our only channel: #ifdef MUROARD_FEATURE_VOLUME_CONTROL volume = muroard_stream_get_volume(m.stream); m.data[10] = (volume & 0xFF00) >> 8; m.data[11] = volume & 0x00FF; #else m.data[10] = 0xFF; m.data[11] = 0xFF; #endif } break; #endif #ifdef MUROARD_FEATURE_VOLUME_CONTROL case MUROAR_CMD_SET_VOL: if ( m.datalen < (4*2) || m.data[0] != 0 || m.data[1] != 1 || !muroard_stream_exist(m.stream) ) { ret = -1; } else { channels = (m.datalen - 3*2)/2; volume = 0; tmp = ntohs(((uint16_t*)m.data)[2]); ret = 0; switch (tmp) { case 1: // ROAR_SET_VOL_ALL case 4: // ROAR_SET_VOL_UNMAPPED switch (channels) { case 1: // mono volume = ntohs(((uint16_t*)m.data)[3]); break; case 2: // stereo volume = ((uint_least32_t)ntohs(((uint16_t*)m.data)[3]) + (uint_least32_t)ntohs(((uint16_t*)m.data)[4]))/2; // printf("l=%u, r=%u, avg=%u\n", (unsigned)ntohs(((uint16_t*)m.data)[3]), (unsigned)ntohs(((uint16_t*)m.data)[4]), (unsigned)volume); break; default: ret = -1; break; } break; case 3: // ROAR_SET_VOL_MS if ( channels == 1 ) { volume = ntohs(((uint16_t*)m.data)[3]); } else { ret = -1; } break; default: ret = -1; break; } // printf("ret=%i, volume=%u\n", ret, (unsigned)volume); tmp = ntohs(((uint16_t*)m.data)[1]); volume = (float)volume*65535.f/(float)tmp; // printf("tmp=%u, volume=%u\n", (unsigned)tmp, (unsigned)volume); muroard_state_member(stream)[m.stream].volume = volume; } break; #endif #ifdef MUROARD_FEATURE_CMD_KICK case MUROAR_CMD_KICK: if ( m.datalen != 4 ) { ret = -1; } else { if ( m.data[0] != 0 ) { // type >= 256 ret = -1; } else { if ( m.data[2] != 0 ) { // id >= 256 ret = -1; } else if ( m.data[1] == 1 ) { // CLIENT ret = muroard_client_delete(m.data[3]); } else if ( m.data[1] == 2 ) { // STREAM ret = muroard_stream_delete(m.data[3]); } else { // unknown type ret = -1; } } } break; #endif #ifdef MUROARD_FEATURE_CMD_ATTACH case MUROAR_CMD_ATTACH: ret = muroard_client_handle_attach(id, &m); break; #endif #ifdef MUROARD_FEATURE_CMD_SERVER_OINFO case MUROAR_CMD_SERVER_OINFO: ret = muroard_client_handle_server_oinfo(id, &m); break; #endif #ifdef MUROARD_FEATURE_CMD_PASSFH case MUROAR_CMD_PASSFH: ret = muroard_client_handle_passfh(id, &m); break; #endif #ifdef MUROARD_FEATURE_CMD_LIST_CLIENTS case MUROAR_CMD_LIST_CLIENTS: ret = muroard_client_handle_list_clients(id, &m); break; #endif #ifdef MUROARD_FEATURE_CMD_LIST_STREAMS case MUROAR_CMD_LIST_STREAMS: ret = muroard_client_handle_list_streams(id, &m); break; #endif #ifdef MUROARD_FEATURE_CMD_GET_CLIENT case MUROAR_CMD_GET_CLIENT: ret = muroard_client_handle_get_client(id, &m); break; #endif #ifdef MUROARD_FEATURE_CMD_GET_STREAM case MUROAR_CMD_GET_STREAM: ret = muroard_client_handle_get_stream(id, &m); break; #endif #ifdef MUROARD_FEATURE_CMD_CAPS case MUROAR_CMD_CAPS: ret = muroard_client_handle_caps(id, &m); break; #endif #ifdef MUROARD_FEATURE_CMD_SERVER_INFO case MUROAR_CMD_SERVER_INFO: ret = muroard_client_handle_server_info(id, &m); break; #endif #ifdef MUROARD_FEATURE_CMD_GETTIMEOFDAY case MUROAR_CMD_GETTIMEOFDAY: ret = muroard_client_handle_gettimeofday(id, &m); break; #endif case MUROAR_CMD_NEW_STREAM: ret = muroard_client_handle_new_stream(id, &m); break; default: ret = -1; // we do not know this command } } if ( ret == 0 ) { m.cmd = MUROAR_CMD_OK; } else { m.cmd = MUROAR_CMD_ERROR; m.stream = -1; m.pos = 0; m.datalen = 0; } if ( muroard_proto_send(sock, &m) == -1 ) { muroard_client_delete(id); return -1; } return 0; } int muroard_client_handle_new_stream(int id, struct muroard_message * mes) { struct muroard_audio_info info; uint32_t * data = (uint32_t*)mes->data; int ret; int i; if ( mes->datalen != (6*4) ) return -1; mes->datalen = 0; for (i = 0; i < 6; i++) { data[i] = ntohl(data[i]); } if ( data[1] != (uint32_t)-1 ) return -1; if ( data[2] != (uint32_t)muroard_state_member(sa_rate) ) return -1; info.bits = data[3]; info.channels = data[4]; info.codec = data[5]; ret = muroard_stream_new(id, data[0], &info); if ( ret == -1 ) return -1; mes->stream = ret; return 0; } #ifdef MUROARD_FEATURE_CMD_ATTACH int muroard_client_handle_attach(int id, struct muroard_message * mes) { int client; (void)id; // we do not need tis parameter if ( mes->datalen != 6 ) return -1; // we do a quick and dirty check: // 0) 16 bit version must be zero // 1) we only support SIMPLE attach, const 16 bit, too. // 2) upper 8 bit of client must be zero (we do not support > 256 clients!) if ( mes->data[0] != 0 || mes->data[1] != 0 || mes->data[2] != 0 || mes->data[3] != 1 || mes->data[4] != 0 ) return -1; client = mes->data[5]; if ( client < 0 ) return -1; if ( (client + 1) > MUROARD_MAX_CLIENTS ) return -1; if ( muroard_state_member(client)[client].state != CLIENT_STATE_NEW && #ifdef MUROARD_FEATURE_INTERNAL_CLIENT muroard_state_member(client)[client].state != CLIENT_STATE_INTERNAL && #endif muroard_state_member(client)[client].state != CLIENT_STATE_OLD ) return -1; if ( muroard_state_member(client)[client].stream != -1 ) return -1; if ( muroard_stream_move_client(mes->stream, client) == -1 ) return -1; #ifdef MUROARD_FEATURE_INTERNAL_CLIENT if ( muroard_state_member(client)[client].state != CLIENT_STATE_INTERNAL ) #endif muroard_state_member(client)[client].stream = mes->stream; mes->datalen = 0; return 0; } #endif #ifdef MUROARD_FEATURE_CMD_SERVER_OINFO int muroard_client_handle_server_oinfo(int id, struct muroard_message * mes) { uint32_t * data = (uint32_t*) mes->data; int i; (void)id; // we do not need this parameter if ( mes->datalen != 0 ) return -1; mes->datalen = 6*4; mes->stream = -1; mes->pos = -1; data[0] = 6; // TODO: do not use magic number. this is ROAR_DIR_MIXING data[1] = -1; data[2] = muroard_state_member(sa_rate); data[3] = 16; data[4] = muroard_state_member(sa_channels); data[5] = MUROAR_CODEC_PCM; for (i = 0; i < 6; i++) { data[i] = htonl(data[i]); } return 0; } #endif #ifdef MUROARD_FEATURE_CMD_PASSFH int muroard_client_handle_passfh(int id, struct muroard_message * mes) { muroard_handle_t fh; mes->datalen = 0; fh = muroard_network_recvfh(muroard_state_member(client)[id].sock); if ( fh == MUROARD_HANDLE_INVALID ) return -1; if ( muroard_network_nonblock(fh, 0) == -1 ) { muroard_network_close(fh); return -1; } if ( !muroard_stream_exist(mes->stream) ) { muroard_network_close(fh); return -1; } if ( muroard_stream_get_sock(mes->stream) != MUROARD_HANDLE_INVALID ) { muroard_network_close(fh); return -1; } if ( muroard_stream_set_sock(mes->stream, fh) == -1 ) { muroard_network_close(fh); return -1; } return 0; } #endif #ifdef MUROARD_FEATURE_CMD_LIST_CLIENTS int muroard_client_handle_list_clients(int id, struct muroard_message * mes) { int len = 0; int i; (void)id; // we do not need tis parameter if ( mes->datalen != 7 ) return -1; if ( mes->data[0] != 0 ) return -1; if ( mes->data[1] != _FILTER_ANY ) return -1; for (i = 0; i < MUROARD_MAX_CLIENTS; i++) { if ( muroard_state_member(client)[i].state != CLIENT_STATE_UNUSED ) { mes->data[len++] = i; } } mes->datalen = len; return 0; } #endif #ifdef MUROARD_FEATURE_CMD_LIST_STREAMS int muroard_client_handle_list_streams(int id, struct muroard_message * mes) { int len = 0; int i; (void)id; // we do not need tis parameter if ( mes->datalen != 7 ) return -1; if ( mes->data[0] != 0 ) return -1; if ( mes->data[1] != _FILTER_ANY ) return -1; for (i = 0; i < MUROARD_MAX_STREAMS; i++) { if ( muroard_state_member(stream)[i].state != STREAM_STATE_UNUSED ) { mes->data[len++] = i; } } mes->datalen = len; return 0; } #endif #ifdef MUROARD_FEATURE_CMD_GET_CLIENT int muroard_client_handle_get_client(int id, struct muroard_message * mes) { struct muroard_client * c; int client; int len = 0; (void)id; // we do not need tis parameter if ( mes->datalen != 1 ) return -1; client = (unsigned char)mes->data[0]; if ( client >= MUROARD_MAX_CLIENTS ) return -1; if ( (c = &(muroard_state_member(client)[client]))->state == CLIENT_STATE_UNUSED ) return -1; mes->data[len++] = 0; // version if ( c->stream == -1 ) { mes->data[len++] = -1; // not execed because we do not have a stream } else { if ( muroard_state_member(stream)[c->stream].state == STREAM_STATE_EXECED ) { mes->data[len++] = c->stream; } else { mes->data[len++] = -1; // not execed } } if ( c->stream == -1 ) { mes->data[len++] = 0; // no streams } else { mes->data[len++] = 1; // one stream mes->data[len++] = c->stream; } mes->data[len++] = 1; // name has size of one byte #ifdef MUROARD_FEATURE_GET_CLIENT_DUMMYNAME snprintf(&(mes->data[len]), sizeof(mes->data) - len, "Client %i", client); mes->data[len - 1] = strlen(&(mes->data[len])) + 1; len += mes->data[len - 1] - 1; #endif mes->data[len++] = 0; // \0 memset(&(mes->data[len]), 0xFF, 3*4); // PID, UID, GID len += 3*4; // Protocol: RoarAudio = 1, 32 bit network byte order mes->data[len++] = 0; mes->data[len++] = 0; mes->data[len++] = 0; mes->data[len++] = 1; // Byte order we use: Network byte order = 0x02, 32 bit network byte order mes->data[len++] = 0; mes->data[len++] = 0; mes->data[len++] = 0; mes->data[len++] = 0x02; mes->datalen = len; return 0; } #endif #ifdef MUROARD_FEATURE_CMD_GET_STREAM int muroard_client_handle_get_stream(int id, struct muroard_message * mes) { struct muroard_stream * s; uint32_t * data = (uint32_t*) mes->data; int i; (void)id; // we do not need tis parameter if ( !muroard_stream_exist(mes->stream) ) { return -1; } s = &(muroard_state_member(stream)[mes->stream]); //fprintf(stderr, "%s:%i: dir=%i\n", __FILE__, __LINE__, s->dir); mes->datalen = 6*4; #ifdef MUROARD_FEATURE_POSITION mes->pos = s->pos; #else mes->pos = -1; #endif data[0] = s->dir; data[1] = -1; data[2] = muroard_state_member(sa_rate); data[3] = s->info.bits; data[4] = s->info.channels; data[5] = s->info.codec; for (i = 0; i < 6; i++) { data[i] = htonl(data[i]); } return 0; } #endif #ifdef MUROARD_FEATURE_CMD_CAPS #if BYTE_ORDER == LITTLE_ENDIAN || defined(__WIN32) #define _HTONS(x) ( \ (((uint32_t)(x) & 0x000000FF) << 24) | \ (((uint32_t)(x) & 0x0000FF00) << 8) | \ (((uint32_t)(x) & 0x00FF0000) >> 8) | \ (((uint32_t)(x) & 0xFF000000) >> 24) \ ) #elif BYTE_ORDER == BIG_ENDIAN #define _HTONS(x) (x) #else #error CAPS support not supported for your byte order #endif #define _MKSTD(vendor,standard,version) _HTONS(((((uint32_t)(vendor) & 0x00FF) << 24) | \ (((uint32_t)(standard) & 0xFFFF) << 8) | \ ((uint32_t)(version) & 0x00FF) )) #define _RA 0 #define _TERM 0xFFFFFFFF #define _TERM_SIZE 4 static const uint32_t _caps_standards[] = { _MKSTD(_RA, 0, 0), // Version 0 messages #ifdef MUROARD_FEATURE_SOCKET_INET _MKSTD(_RA, 25, 0), #endif #ifdef MUROARD_FEATURE_SOCKET_UNIX _MKSTD(_RA, 23, 0), #endif _TERM }; int muroard_client_handle_caps(int id, struct muroard_message * mes) { uint16_t flags; (void)id; // check if header is complet. if ( mes->datalen < 4 ) return -1; // check if version is supported. if ( mes->data[0] != 0 ) return -1; // check if type is supported. if ( mes->data[1] != MUROAR_CT_STANDARDS ) return -1; flags = ntohs(((uint16_t*)mes->data)[1]); if ( !(flags & MUROAR_CF_REQUEST) ) { mes->datalen = 0; return 0; } mes->datalen = 4 + (sizeof(_caps_standards) - _TERM_SIZE); if ( mes->datalen > sizeof(mes->data) ) return -1; // clear flags: mes->data[2] = 0; mes->data[3] = 0; memcpy(mes->data + 4, _caps_standards, sizeof(_caps_standards) - _TERM_SIZE); return 0; } #endif #ifdef MUROARD_FEATURE_CMD_SERVER_INFO int muroard_client_handle_server_info(int id, struct muroard_message * mes) { const char * version = MUROARD_VERSION; const size_t len = strlen(version); (void)id, (void)mes; // test length: if ( mes->datalen != 4 ) return -1; // test version: if ( mes->data[0] != 0 || mes->data[1] != 0 ) return -1; // test type (0x0001 = IT_SERVER): if ( mes->data[2] != 0 || mes->data[3] != 1 ) return -1; mes->datalen = 8 + len; // version: mes->data[0] = 0x00; // reserved: mes->data[1] = 0x00; // indexlen: mes->data[2] = 0x00; mes->data[3] = 0x01; // index 0: // - reserved mes->data[4] = 0x00; // - type (0x00 = ITST_VERSION) mes->data[5] = 0x00; // - len mes->data[6] = (len & 0xFF00) >> 8; mes->data[7] = (len & 0x00FF); memcpy(&(mes->data[8]), version, len); return 0; } #endif #ifdef MUROARD_FEATURE_CMD_GETTIMEOFDAY int muroard_client_handle_gettimeofday(int id, struct muroard_message * mes) { uint32_t * data = (uint32_t *)mes->data; int32_t now = time(NULL); (void)id; mes->datalen = 8*4; data[0] = 0; data[1] = 0; data[2] = now < 0 ? 0xFFFFFFFFLU : 0LU; data[3] = htonl((uint32_t)now); data[4] = 0; data[5] = 0; data[6] = 0; data[7] = htonl(1000000000UL); return 0; } #endif //ll muroard-0.1.14/clients.h0000644000175000017500000000671712210352111013201 0ustar phiphi//clients.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _MUROARD_CLIENTS_H_ #define _MUROARD_CLIENTS_H_ #define CLIENT_STATE_UNUSED 0 #define CLIENT_STATE_NEW 1 #define CLIENT_STATE_OLD 2 #define CLIENT_STATE_EXECED 3 #define CLIENT_STATE_CLOSING 4 #ifdef MUROARD_FEATURE_INTERNAL_CLIENT #define CLIENT_STATE_INTERNAL 5 #endif struct muroard_client { int state; int stream; muroard_handle_t sock; }; int muroard_client_init(void); int muroard_client_free(void); int muroard_client_new(muroard_handle_t sock); int muroard_client_delete(int id); int muroard_client_handle(int id); muroard_handle_t muroard_client_exec(int id); int muroard_client_handle_new_stream(int id, struct muroard_message * mes); #ifdef MUROARD_FEATURE_CMD_ATTACH int muroard_client_handle_attach(int id, struct muroard_message * mes); #endif #ifdef MUROARD_FEATURE_CMD_SERVER_OINFO int muroard_client_handle_server_oinfo(int id, struct muroard_message * mes); #endif #ifdef MUROARD_FEATURE_CMD_PASSFH int muroard_client_handle_passfh(int id, struct muroard_message * mes); #endif #ifdef MUROARD_FEATURE_CMD_LIST_CLIENTS int muroard_client_handle_list_clients(int id, struct muroard_message * mes); #endif #ifdef MUROARD_FEATURE_CMD_LIST_STREAMS int muroard_client_handle_list_streams(int id, struct muroard_message * mes); #endif #ifdef MUROARD_FEATURE_CMD_GET_CLIENT int muroard_client_handle_get_client(int id, struct muroard_message * mes); #endif #ifdef MUROARD_FEATURE_CMD_GET_STREAM int muroard_client_handle_get_stream(int id, struct muroard_message * mes); #endif #ifdef MUROARD_FEATURE_CMD_CAPS int muroard_client_handle_caps(int id, struct muroard_message * mes); #endif #ifdef MUROARD_FEATURE_CMD_SERVER_INFO int muroard_client_handle_server_info(int id, struct muroard_message * mes); #endif #ifdef MUROARD_FEATURE_CMD_GETTIMEOFDAY int muroard_client_handle_gettimeofday(int id, struct muroard_message * mes); #endif #define client_get_sock(id) (muroard_state_member(client)[(id)].state == CLIENT_STATE_UNUSED ? -1 : muroard_state_member(client)[(id)].sock) #define client_get_stream(id) (muroard_state_member(client)[(id)].state == CLIENT_STATE_UNUSED ? -1 : muroard_state_member(client)[(id)].stream) #define client_set_stream_check(id, s) (muroard_state_member(client)[(id)].state == CLIENT_STATE_UNUSED || \ muroard_state_member(client)[(id)].stream != -1 ? -1 : 0) #define client_set_stream(id, s) (client_set_stream_check((id),(s)) == -1 ? -1 : \ (muroard_state_member(client)[(id)].stream = (s)) && 0) #endif //ll muroard-0.1.14/configure0000755000175000017500000002062312126651665013314 0ustar phiphi#!/bin/sh # IDs officaly assigned DEV_VENDOR=0 DEV_VENDOR_NAME='RoarAudio' #-------- TF_C=testit.c TF_E=./testit LDPATH='' INCPATH='' PREFIX='/usr/local' PREFIX_BIN='' PREFIX_LIB='' PREFIX_INC='' PREFIX_MAN='' SHARED='-shared' SHARED_CF='' SHARED_SUFFIX='.so' fPIC=true Wextra=false BUILD_SHARED=true TARGET_WIN32=false TARGET_MICROCONTROLLER=false DRIVER='' DRIVER_LIBS='' echo -n "checking for version of this package... " VERSION=`head -n 1 ChangeLog | cut -d' ' -f2` echo "$VERSION" echo -n "checking for C compiler... " if [ "$CC" != '' ] then echo $CC else CC=$(which gcc cc 2> /dev/null | grep ^/ | head -n 1) if [ "$CC" = '' ] then echo 'none' exit 1; fi echo $CC fi echo -n "checking for ranlib... " if [ "$RANLIB" != '' ] then echo $RANLIB else _guess=`echo $CC | sed 's/[gp]*cc\(-.*\)*//'` RANLIB=$(which ${_guess}ranlib ranlib 2> /dev/null | grep ^/ | head -n 1) if [ "$RANLIB" = '' ] then echo 'none' fi echo $RANLIB fi echo -n "checking for sysname... " SYSNAME=$(uname -s) echo "$SYSNAME" while [ "$1" != '' ] do case "$1" in '--help'|'-h') echo '--help - This Help' echo echo '--ldpath DIR - Add DIR to (compile time) search list for libs' echo '--incpath DIR - Add DIR to search list for headers' echo '--addpath DIR - Add DIR/lib to lib, DIR/include to header search list' echo echo '--cc CC - Set name of C compiler (CC) to CC' echo echo '--prefix DIR - Set general prefix (default: '"$PREFIX"')' echo '--prefix-bin DIR - Set prefix for binarys (default: $PREFIX/bin)' echo '--prefix-lib DIR - Set prefix for librarys (default: $PREFIX/lib)' echo '--prefix-inc DIR - Set prefix for include files (default: $PREFIX/include)' echo '--prefix-man DIR - Set prefix for manpages (default: $PREFIX/share/man)' echo echo '--distribution-version-string STRING' echo ' - Sets distribution part of version string' echo echo '--driver DRIVER - Set the driver to use' echo echo '--target-win32 - Compile for win32' echo '--target-microcontroller - Set Options for mircocontrollers without a OS' exit 0; ;; '--ldpath') LDPATH="$LDPATH -L$2" shift; ;; '--incpath') INCPATH="$INCPATH -I$2" shift; ;; '--addpath') LDPATH="$LDPATH -L$2/lib/" INCPATH="$INCPATH -I$2/include/" shift; ;; '--cc') CC="$2" shift; ;; '--prefix') PREFIX="$2" shift; ;; '--prefix-bin') PREFIX_BIN="$2" shift; ;; '--prefix-lib') PREFIX_LIB="$2" shift; ;; '--prefix-inc') PREFIX_INC="$2" shift; ;; '--prefix-man') PREFIX_MAN="$2" shift; ;; #################################### # autof* options block: '--prefix=*') PREFIX=$(echo "$1" | cut -d= -f2) ;; '--prefix-bin=*') PREFIX_BIN=$(echo "$1" | cut -d= -f2) ;; '--prefix-lib=*') PREFIX_LIB=$(echo "$1" | cut -d= -f2) ;; '--prefix-inc=*') PREFIX_INC=$(echo "$1" | cut -d= -f2) ;; '--prefix-man=*') PREFIX_MAN=$(echo "$1" | cut -d= -f2) ;; #################################### '--distribution-version-string') DISTRIBUTION_VERSION_STRING="$2" shift; ;; '--driver') DRIVER="$2" shift; ;; '--target-win32') TARGET_WIN32=true ;; '--target-microcontroller') TARGET_MICROCONTROLLER=true ;; *) echo "Error: unknown option: $1" >&2; echo "Try: $0 --help" >&2; exit 1; ;; esac; shift; done exec 4> Makefile.conf 5> config.log TARGET_WIN32=`echo "$SYSNAME" | if grep MINGW32 > /dev/null; then echo true; else echo $TARGET_WIN32; fi` if $TARGET_WIN32 then echo "Adding win32 build arguments..." fPIC=false SHARED_SUFFIX='.dll' BUILD_SHARED=false [ "$DRIVER" = '' ] && DRIVER='WMM' elif [ "`uname -s`" = 'OpenBSD' ] then echo "Adding OpenBSD build arguments..." [ "$DRIVER" = '' ] && DRIVER='OSS' fi if $TARGET_MICROCONTROLLER then echo "Adding microcontroller build arguments..." BUILD_SHARED=false fi DRIVER=`echo "$DRIVER" | tr a-z A-Z` case "$DRIVER" in 'MUROAR') DRIVER_LIBS='$(lib_muroar)' ;; 'ESD') DRIVER_LIBS='-lesd' ;; 'LIBAO') DRIVER_LIBS='$(lib_ao)' ;; 'OSS') : # no need to do anything # NOTE: some systems need -lossaudio or simular. # users need to pass it in this case DRIVER_LIBS=-lossaudio make ... DRIVER_LIBS='$(lib_ossaudio)' ;; 'WMM') DRIVER_LIBS='$(lib_winmm)' ;; 'SNDIO') DRIVER_LIBS='-lsndio' ;; 'TINYALSA') DRIVER_LIBS='-ltinyalsa' ;; esac CCTF="$CC $CFLAGS $LDFLAGS $LDPATH $INCPATH -o $TF_E $TF_C" # Check for -Wextra #Wextra echo -n "checking if compiler supports -Wextra... " echo 'int main (void) { return 0; }' > $TF_C if $CCTF -Wextra 2> /dev/null; then echo yes Wextra=true else echo no Wextra=false fi [ "$PREFIX_BIN" = '' ] && PREFIX_BIN="$PREFIX/bin/" [ "$PREFIX_LIB" = '' ] && PREFIX_LIB="$PREFIX/lib/" [ "$PREFIX_INC" = '' ] && PREFIX_INC="$PREFIX/include/" [ "$PREFIX_MAN" = '' ] && PREFIX_MAN="$PREFIX/share/man/" { echo "EMPTY=" echo "VERSION=$VERSION" echo "DEV_VENDOR=$DEV_VENDOR" echo "DEV_VENDOR_NAME=$DEV_VENDOR_NAME" echo "DEV_VENDOR_STRING=$DEV_VENDOR/$DEV_VENDOR_NAME" if [ "$DISTRIBUTION_VERSION_STRING" = '' ] then echo "DISTRIBUTION_VERSION_STRING=" else echo "DISTRIBUTION_VERSION_STRING=\$(EMPTY) ($DISTRIBUTION_VERSION_STRING)" fi if [ "$DRIVER" = '' ] then echo "DRIVER_def=" else echo "DRIVER_def=-DMUROARD_FEATURE_DRIVER=MUROARD_DRIVER_$DRIVER" fi echo "DRIVER_LIBS+=$DRIVER_LIBS" echo echo "SHARED=$SHARED" echo "SHARED_CF=$SHARED_CF" echo "SHARED_SUFFIX=$SHARED_SUFFIX" $fPIC && echo 'fPIC=-fPIC' $Wextra && echo 'Wextra=-Wextra' echo "BUILD_SHARED=$BUILD_SHARED" echo echo "CC=$CC" echo "RANLIB=$RANLIB" echo "LDPATH=$LDPATH" echo "INCPATH=$INCPATH" echo echo "CFLAGS=$CFLAGS" echo "LDPATH=$LDPATH" echo echo "PREFIX=$PREFIX" echo "PREFIX_BIN=$PREFIX_BIN" echo "PREFIX_LIB=$PREFIX_LIB" echo "PREFIX_INC=$PREFIX_INC" echo "PREFIX_MAN=$PREFIX_MAN" echo $TARGET_MICROCONTROLLER && echo "TARGET_MICROCONTROLLER=-DTARGET_MICROCONTROLLER" } >&4 { cat <<'EOF' //config.log: /* * Logfile for configure script $Revision: 1.19 $ of µRoarD */ EOF echo '/* uname: ' $(uname -a) '*/' echo '/* Date : ' $(date) '*/' echo echo echo echo "ARGS(): $_CARGS" for i in PATH SHELL CC RANLIB PKG_CONFIG SYSNAME \ TARGET_WIN32 TARGET_MICROCONTROLLER do eval echo "BASICCONF\($i\): \$$i"; done echo echo } >&5 test_lib () { echo > $TF_C name="$1" echo -n "checking for $name... " echo "TEST LIB: $name" >&5 shift; lib="$1" LIBS='' while [ "$1" != '--' ] do case "$1" in 'c'|'-lc') :; # no need to do anything ;; '-'*) LIBS="$LIBS $1" ;; *) LIBS="$LIBS -l$1" ;; esac shift; done shift; echo "LIB($name) IS TESTED USING LIBS: $LIBS" >&5 while [ "$1" != '' ] do echo "#include <$1>" >> $TF_C shift; done echo 'int main (void) { return 0; }' >> $TF_C echo "LIB($name) IS TESTED USING TEST CODE:" >&5 echo "--- BEGIN OF CODE BLOCK ---" >&5 cat $TF_C >&5 echo "--- END OF CODE BLOCK ---" >&5 echo "LIB($name) HAS COMPILER/LINKER OUTPUT:" >&5 echo "--- BEGIN OF CHILD OUTPUT BLOCK ---" >&5 $CCTF $LIBS >&5 2>&5; R=$? echo "--- END OF CHILD OUTPUT BLOCK ---" >&5 if [ "$R" = '0' ] then echo 'yes' echo "LIB($name) WAS FOUND" >&5 if [ "$lib" != 'c' ] then echo "lib_$lib=$LIBS" >&4 echo "def_$lib=-DHAVE_LIB_"`echo "$lib" | tr a-z A-Z` >&4 fi else echo 'no' echo "LIB($name) NOT FOUND" >&5 fi return $R } test_lib DECnet dnet -- sys/socket.h netdnet/dn.h netdnet/dnetdb.h test_lib DECnetDaemon dnet_daemon dnet -- sys/socket.h netdnet/dn.h netdnet/dnetdb.h test_lib WinSockP0 wsock32 -- winsock2.h test_lib WinSockP1 ws2_32 -- winsock2.h test_lib libao ao -- ao/ao.h test_lib BSDOSS ossaudio -- sys/ioctl.h test_lib libwinmm winmm -- windows.h mmsystem.h test_lib libvorbisfile vorbisfile -- vorbis/vorbisfile.h test_lib muRoar muroar -- muroar.h if [ "$?" != '0' ] then echo "Error: can not find libmuroar" >&2 exit 1 fi echo -n 'checking if cp supports -v... ' if cp -v --help > /dev/null 2> /dev/null then echo "cp_v=-v" >&4 echo yes else echo "cp_v=" >&4 echo no fi echo >&5 echo '//ll' >&5 rm -f $TF_C $TF_E #ll muroard-0.1.14/deps.h0000644000175000017500000001226012133577131012500 0ustar phiphi//deps.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _MUROARD_DEPS_H_ #define _MUROARD_DEPS_H_ #if defined(MUROARD_FEATURE_SOCKET_DECNET) && !defined(HAVE_LIB_DNET_DAEMON) #undef MUROARD_FEATURE_SOCKET_DECNET #endif #if defined(MUROARD_FEATURE_CODECFILTER_OGG_VORBIS) && !defined(HAVE_LIB_VORBISFILE) #undef MUROARD_FEATURE_CODECFILTER_OGG_VORBIS #endif /*** define things we disabple below if not supported ***/ #ifndef TARGET_MICROCONTROLLER #define MUROARD_HAVE_FORK #define MUROARD_HAVE_FCHMOD #define MUROARD_HAVE_UMASK #endif /*** calc TARGET_MICROCONTROLLER stuff first ***/ #ifdef TARGET_MICROCONTROLLER #ifdef MUROARD_FEATURE_HELP_TEXT #undef MUROARD_FEATURE_HELP_TEXT #endif #ifdef MUROARD_FEATURE_VERSION_TEXT #undef MUROARD_FEATURE_VERSION_TEXT #endif #ifdef MUROARD_FEATURE_SOCKET_UNIX #undef MUROARD_FEATURE_SOCKET_UNIX #endif #ifdef MUROARD_FEATURE_SIGNALS #undef MUROARD_FEATURE_SIGNALS #endif #endif /*** calc general things ***/ #ifndef MUROARD_FEATURE_ARGV // disable help: #ifdef MUROARD_FEATURE_HELP_TEXT #undef MUROARD_FEATURE_HELP_TEXT #endif #ifdef MUROARD_FEATURE_VERSION_TEXT #undef MUROARD_FEATURE_VERSION_TEXT #endif #ifdef MUROARD_FEATURE_CLIENT_FH #undef MUROARD_FEATURE_CLIENT_FH #endif #endif /*** calc network things ***/ #ifndef MUROARD_FEATURE_SOCKET_LISTEN // disable all kinds of listen sockets: // IP sockets: #ifdef MUROARD_FEATURE_SOCKET_INET #undef MUROARD_FEATURE_SOCKET_INET #endif // UNIX sockets: #ifdef MUROARD_FEATURE_SOCKET_UNIX #undef MUROARD_FEATURE_SOCKET_UNIX #endif // DECnet sockets: #ifdef MUROARD_FEATURE_SOCKET_DECNET #undef MUROARD_FEATURE_SOCKET_DECNET #endif #endif // disable things Win32 does not support: #if defined(__WIN32) // No UNIX sockets support on win32 #ifdef MUROARD_FEATURE_SOCKET_UNIX #undef MUROARD_FEATURE_SOCKET_UNIX #endif // No Signals on win32 #ifdef MUROARD_FEATURE_SIGNALS #undef MUROARD_FEATURE_SIGNALS #endif // No fork() on win32: #ifdef MUROARD_HAVE_FORK #undef MUROARD_HAVE_FORK #endif // No fchmod() on win32: #ifdef MUROARD_HAVE_FCHMOD #undef MUROARD_HAVE_FCHMOD #endif // No umask() on win32: #ifdef MUROARD_HAVE_UMASK #undef MUROARD_HAVE_UMASK #endif #endif #ifndef MUROARD_FEATURE_SOCKET_UNIX #ifdef MUROARD_FEATURE_CMD_PASSFH #undef MUROARD_FEATURE_CMD_PASSFH #endif #endif /*** calc support of functions ***/ #if !defined(MUROARD_HAVE_FORK) && !defined(__WIN32) #ifdef MUROARD_FEATURE_DAEMONIZE #undef MUROARD_FEATURE_DAEMONIZE #endif #endif #ifndef MUROARD_HAVE_FCHMOD #ifdef MUROARD_DEFAULT_LISTEN_CHMOD #undef MUROARD_DEFAULT_LISTEN_CHMOD #endif #endif /*** calc list of needed dsp functions ***/ #ifdef MUROARD_FEATURE_UPMIX_INPUT #define MUROARD_FEATURE_UPMIX #endif #ifdef MUROARD_FEATURE_UPSCALE_INPUT #define MUROARD_FEATURE_UPSCALE #endif #ifdef MUROARD_FEATURE_DOWNMIX_OUTPUT #define MUROARD_FEATURE_DOWNMIX #endif #ifdef MUROARD_FEATURE_DOWNSCALE_OUTPUT #define MUROARD_FEATURE_DOWNSCALE #endif /*** calc minimum requirements, throw error if we hit a error ***/ #if !defined(MUROARD_FEATURE_ARGV) && !defined(MUROARD_FEATURE_SOCKET_LISTEN) #if !(defined(MUROARD_FEATURE_SOCKET_INET) || defined(MUROARD_FEATURE_SOCKET_UNIX)) #error You did not configure any way to comunicate with the clients #endif #endif #if defined(MUROARD_MEMMGR_NOUSE_MALLOC) && !defined(MUROARD_FIXED_ABUFFER_SIZE) #error You must define MUROARD_FIXED_ABUFFER_SIZE in feature.h if going to use MUROARD_MEMMGR_NOUSE_MALLOC #endif /*** calc defaults based on what is left ***/ #ifdef MUROARD_FEATURE_SOCKET_LISTEN #ifndef MUROARD_DEFAULT_LISTEN_TYPE #ifdef MUROARD_FEATURE_SOCKET_UNIX #define MUROARD_DEFAULT_LISTEN_TYPE MUROARD_NETWORK_TYPE_UNIX #elif defined(MUROARD_FEATURE_SOCKET_INET) #define MUROARD_DEFAULT_LISTEN_TYPE MUROARD_NETWORK_TYPE_INET #elif defined(MUROARD_FEATURE_SOCKET_DECNET) #define MUROARD_DEFAULT_LISTEN_TYPE MUROARD_NETWORK_TYPE_DECNET #else #undef MUROARD_FEATURE_SOCKET_LISTEN #endif #endif #endif #ifndef MUROARD_FEATURE_DRIVER #ifdef __WIN32 #define MUROARD_FEATURE_DRIVER MUROARD_DRIVER_WMM #else #define MUROARD_FEATURE_DRIVER MUROARD_DRIVER_OSS #endif #endif #if defined(MUROARD_FEATURE_SOCKET_DECNET) && !defined(MUROARD_FEATURE_SOCKET_LISTEN_SOCKTYPE) #define MUROARD_FEATURE_SOCKET_LISTEN_SOCKTYPE #endif #if defined(MUROARD_FEATURE_REREADWRITE) && defined(__WIN32) #undef MUROARD_FEATURE_REREADWRITE #endif #endif //ll muroard-0.1.14/driver.c0000644000175000017500000000612412126652353013037 0ustar phiphi//driver.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #ifndef MUROARD_FEATURE_DRIVER #define MUROARD_FEATURE_DRIVER MUROARD_DRIVER_NONE #endif #if MUROARD_FEATURE_DRIVER == MUROARD_DRIVER_NONE /* use dummy driver from below */ #elif MUROARD_FEATURE_DRIVER == MUROARD_DRIVER_MUROAR #include "driver_muroar.c" #elif MUROARD_FEATURE_DRIVER == MUROARD_DRIVER_LIBAO #include "driver_ao.c" #elif MUROARD_FEATURE_DRIVER == MUROARD_DRIVER_OSS #include "driver_oss.c" #elif MUROARD_FEATURE_DRIVER == MUROARD_DRIVER_WMM #include "driver_wmm.c" #elif MUROARD_FEATURE_DRIVER == MUROARD_DRIVER_ESD #include "driver_esd.c" #elif MUROARD_FEATURE_DRIVER == MUROARD_DRIVER_SNDIO #include "driver_sndio.c" #elif MUROARD_FEATURE_DRIVER == MUROARD_DRIVER_TINYALSA #include "driver_tinyalsa.c" #else #error Invalid driver setting. check MUROARD_FEATURE_DRIVER #endif #ifndef DRIVER_HAVE_INIT int muroard_driver_init(const char * dev) { (void)dev; return 0; } #endif #ifndef DRIVER_HAVE_FREE int muroard_driver_free(void) { #ifdef DRIVER_USE_SYSIO if ( muroard_state_member(driver_fh) != -1 ) return close(muroard_state_member(driver_fh)); #endif return 0; } #endif #ifndef DRIVER_HAVE_WRITE ssize_t muroard_driver_write(int16_t * data, size_t len, enum muroard_blocking blocking) { #ifdef DRIVER_USE_SYSIO ssize_t ret; size_t done = 0; if ( blocking != muroard_state_member(driver_old_blocking) ) { muroard_network_nonblock(muroard_state_member(driver_fh), blocking != MUROARD_BLOCKING_NONE); muroard_state_member(driver_old_blocking) = blocking; } while (len) { ret = write(muroard_state_member(driver_fh), data, len); #ifndef __WIN32 if ( blocking == MUROARD_BLOCKING_NONE && ret == -1 && errno == EAGAIN ) ret = 0; #endif if ( ret > 0 ) { done += ret; len -= ret; data += ret; } if ( ret < 0 ) { return -1; } else { // ret == 0 return done; } } return done; #else (void)data; if ( blocking == MUROARD_BLOCKING_NONE ) return len; #ifndef __WIN32 usleep(muroard_g_abuffer_size*1000000LLU/(long long unsigned)(muroard_g_sa_rate*muroard_g_sa_channels*2)); #else Sleep(muroard_g_abuffer_size*1000LLU/(long long unsigned)(muroard_g_sa_rate*muroard_g_sa_channels*2)); #endif return len; #endif } #endif //ll muroard-0.1.14/driver.h0000644000175000017500000000267412126652353013052 0ustar phiphi//driver.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _MUROARD_DRIVER_H_ #define _MUROARD_DRIVER_H_ #define MUROARD_DRIVER_NONE 0 #define MUROARD_DRIVER_MUROAR 1 #define MUROARD_DRIVER_ESD 2 #define MUROARD_DRIVER_LIBAO 3 #define MUROARD_DRIVER_OSS 4 #define MUROARD_DRIVER_WMM 5 #define MUROARD_DRIVER_SNDIO 6 #define MUROARD_DRIVER_TINYALSA 7 int muroard_driver_init(const char * dev); int muroard_driver_free(void); ssize_t muroard_driver_write(int16_t * data, size_t len, enum muroard_blocking blocking); #endif //ll muroard-0.1.14/driver_ao.c0000644000175000017500000000475612126652353013527 0ustar phiphi//driver_ao.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #include #define DRIVER_HAVE_INIT #define DRIVER_HAVE_FREE #define DRIVER_HAVE_WRITE int muroard_driver_init(const char * dev) { ao_sample_format format; int driver; #ifdef HAVE_LIBAO_MATRIX char * map = NULL; #endif ao_initialize(); if ( dev == NULL ) { driver = ao_default_driver_id(); } else { driver = ao_driver_id(dev); } if (driver < 0) return -1; muroard_memzero(&format, sizeof(format)); format.bits = 16; format.channels = muroard_state_member(sa_channels); format.rate = muroard_state_member(sa_rate); format.byte_format = AO_FMT_NATIVE; #ifdef HAVE_LIBAO_MATRIX switch (muroard_state_member(sa_channels)) { case 1: map = "M"; break; case 2: map = "L,R"; break; case 3: map = "L,R,C"; break; case 4: map = "L,R,BL,BR"; break; case 5: map = "L,R,C,BL,BR"; break; case 6: map = "L,R,C,LFE,BL,BR"; break; } if ( map != NULL ) { format.matrix = map; } #endif muroard_state_member(driver_vp) = ao_open_live(driver, &format, NULL /* no options */); if ( muroard_state_member(driver_vp) == NULL ) return -1; return 0; } int muroard_driver_free(void) { if ( muroard_state_member(driver_vp) != NULL ) ao_close(muroard_state_member(driver_vp)); ao_shutdown(); return 0; } ssize_t muroard_driver_write(int16_t * data, size_t len, enum muroard_blocking blocking) { if ( blocking == MUROARD_BLOCKING_NONE ) return -1; if ( ao_play(muroard_state_member(driver_vp), (char*)data, len) == 0 ) return -1; return 0; } //ll muroard-0.1.14/driver_esd.c0000644000175000017500000000274212126652354013675 0ustar phiphi//driver_esd.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #include #define DRIVER_HAVE_INIT #define DRIVER_USE_SYSIO int muroard_driver_init(const char * dev) { esd_format_t fmt = ESD_PLAY|ESD_STREAM|ESD_BITS16; switch (muroard_state_member(sa_channels)) { case 1: fmt |= ESD_MONO; break; case 2: fmt |= ESD_STEREO; break; default: return -1; break; } muroard_state_member(driver_fh) = esd_play_stream_fallback(fmt, muroard_state_member(sa_rate), dev, MUROARD_DEFAULT_DRIVER_CLIENT_NAME); if ( muroard_state_member(driver_fh) == -1 ) return -1; return 0; } //ll muroard-0.1.14/driver_muroar.c0000644000175000017500000000333412126652354014425 0ustar phiphi//driver_muroar.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #define DRIVER_HAVE_INIT #define DRIVER_USE_SYSIO int muroard_driver_init(const char * dev) { if ( (muroard_state_member(driver_fh) = muroar_connect(dev, MUROARD_DEFAULT_DRIVER_CLIENT_NAME)) == -1 ) return -1; if ( (muroard_state_member(driver_fh) = muroar_stream(muroard_state_member(driver_fh), MUROAR_PLAY_WAVE, NULL, MUROAR_CODEC_PCM, muroard_state_member(sa_rate), muroard_state_member(sa_channels), 16)) == -1 ) return -1; return 0; } //ll muroard-0.1.14/driver_oss.c0000644000175000017500000000617612126652354013733 0ustar phiphi//driver_oss.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #if defined(__OpenBSD__) || defined(__NetBSD__) #include #else #include #endif #include /* for ioctl() */ #include /* for open() */ #define DRIVER_HAVE_INIT #define DRIVER_USE_SYSIO #if defined(MUROARD_FEATURE_DRIVER_OSS_SETFRAGMENT) && defined(SNDCTL_DSP_SETFRAGMENT) #define driver_set_fragments(x) driver_try_buf_setups((x)) static void driver_try_buf_setups(int fh) { unsigned int blocksizes[] = {11, 12, 13}; unsigned int blocks[] = {4, 5, 6, 3, 7, 2, 8}; unsigned int bs, b; int tmp; for (bs = 0; bs < sizeof(blocksizes)/sizeof(int); bs++) { for (b = 0; b < sizeof(blocks) /sizeof(int); b++ ) { tmp = blocksizes[bs] | (blocks[b] << 16); if ( ioctl(fh, SNDCTL_DSP_SETFRAGMENT, &tmp) == 0 ) return; } } } #else #define driver_set_fragments(x) ((void)(x)) #endif #define _err() close(muroard_state_member(driver_fh)); return -1 int muroard_driver_init(const char * dev) { int ctmp, tmp; #ifdef MUROARD_DEFAULT_DRIVER_OSS_DEV if ( dev == NULL ) dev = MUROARD_DEFAULT_DRIVER_OSS_DEV; #endif muroard_state_member(driver_fh) = open(dev, O_WRONLY, 0644); if ( muroard_state_member(driver_fh) == -1 ) return -1; // channels: #ifdef SNDCTL_DSP_CHANNELS tmp = muroard_state_member(sa_channels); if ( ioctl(muroard_state_member(driver_fh), SNDCTL_DSP_CHANNELS, &tmp) == -1 ) { _err(); } if ( tmp != muroard_state_member(sa_channels) ) { _err(); } #else switch (muroard_state_member(sa_channels)) { case 1: tmp = 0; break; case 2: tmp = 1; break; default: _err(); } if ( ioctl(muroard_state_member(driver_fh), SNDCTL_DSP_STEREO, &tmp) == -1 ) { _err(); } #endif ctmp = tmp = AFMT_S16_NE; #ifdef SNDCTL_DSP_SETFMT if ( ioctl(muroard_state_member(driver_fh), SNDCTL_DSP_SETFMT, &tmp) == -1 ) { #else if ( ioctl(muroard_state_member(driver_fh), SNDCTL_DSP_SAMPLESIZE, &tmp) == -1 ) { #endif _err(); } if ( tmp != ctmp ) { _err(); } tmp = muroard_state_member(sa_rate); if ( ioctl(muroard_state_member(driver_fh), SNDCTL_DSP_SPEED, &tmp) == -1 ) { _err(); } if ( tmp != muroard_state_member(sa_rate) ) { _err(); } driver_set_fragments(muroard_state_member(driver_fh)); return 0; } //ll muroard-0.1.14/driver_sndio.c0000644000175000017500000000403612210336016014220 0ustar phiphi//driver_muroar.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #include #define DRIVER_HAVE_INIT #define DRIVER_HAVE_FREE #define DRIVER_HAVE_WRITE int muroard_driver_init(const char * dev) { struct sio_par par; sio_initpar(&par); par.bits = 16; par.rate = muroard_state_member(sa_rate); par.pchan = muroard_state_member(sa_channels); par.le = SIO_LE_NATIVE; par.sig = 1; if ( (muroard_state_member(driver_vp) = sio_open(dev, SIO_PLAY, 0)) == NULL ) return -1; if ( sio_setpar(muroard_state_member(driver_vp), &par) == 0 ) { sio_close(muroard_state_member(driver_vp)); return -1; } if ( sio_start(muroard_state_member(driver_vp)) == 0 ) { sio_close(muroard_state_member(driver_vp)); return -1; } return 0; } int muroard_driver_free(void) { if ( muroard_state_member(driver_vp) != NULL ) { sio_stop(muroard_state_member(driver_vp)); sio_close(muroard_state_member(driver_vp)); } return 0; } ssize_t muroard_driver_write(int16_t * data, size_t len, enum muroard_blocking blocking) { if ( blocking == MUROARD_BLOCKING_NONE ) return -1; return (ssize_t)sio_write(muroard_state_member(driver_vp), data, len); } //ll muroard-0.1.14/driver_tinyalsa.c0000644000175000017500000000425412126651665014752 0ustar phiphi//driver_tinyalsa.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #include #define DRIVER_HAVE_INIT #define DRIVER_HAVE_FREE #define DRIVER_HAVE_WRITE // this driver seems to only work on little endian systems... int muroard_driver_init(const char * dev) { struct pcm_config config; unsigned int period_size = muroard_state_member(abuffer_size); unsigned int period_count = 4; unsigned int card = 0; unsigned int device = 0; config.channels = muroard_state_member(sa_channels); config.rate = muroard_state_member(sa_rate); config.format = PCM_FORMAT_S16_LE; config.start_threshold = 0; config.stop_threshold = 0; config.silence_threshold = 0; config.period_size = period_size; config.period_count = period_count; muroard_state_member(driver_vp) = pcm_open(card, device, PCM_OUT, &config); if (!muroard_state_member(driver_vp) || !pcm_is_ready(muroard_state_member(driver_vp))) return -1; return 0; } int muroard_driver_free(void) { if ( muroard_state_member(driver_vp) != NULL ) { pcm_close(muroard_state_member(driver_vp)); } return 0; } ssize_t muroard_driver_write(int16_t * data, size_t len, enum muroard_blocking blocking) { if ( blocking == MUROARD_BLOCKING_NONE ) return -1; pcm_write(muroard_state_member(driver_vp), data, len); return 0; } //ll muroard-0.1.14/driver_wmm.c0000644000175000017500000002525712126652354013730 0ustar phiphi//driver_wmm.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009-2013 * Copyright (C) Benjamin Gerard - March 2007 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #include #include #define _debug 0 #define dbg _debug && #define DRIVER_HAVE_INIT #define DRIVER_HAVE_FREE #define DRIVER_HAVE_WRITE struct driver_wmm { UINT id; /* device id */ HWAVEOUT hwo; /* waveout handler */ WAVEOUTCAPS caps; /* device caps */ WAVEFORMATEX wavefmt; /* sample format */ int opened; /* device has been opened */ int prepared; /* waveheaders have been prepared */ int blocks; /* number of blocks (wave headers) */ int splPerBlock; /* sample per blocks. */ int msPerBlock; /* millisecond per block (approx.) */ void * bigbuffer; /* Allocated buffer for waveheaders and sound data */ struct { WAVEHDR wh; /* waveheader */ char * data; /* sample data ptr */ int idx; /* index of this header */ int count; /* current byte count */ int length; /* size of data */ int sent; /* set when header is sent to device */ } * wh; /* Pointer to waveheaders in bigbuffer */ BYTE * spl; /* Pointer to sound data in bigbuffer */ int sent_blocks; /* Number of waveheader sent (not ack). */ int full_blocks; /* Number of waveheader full (ready to send). */ int widx; /* Index to the block being currently filled. */ int ridx; /* Index to the block being sent. */ }; static int _alloc_wave_headers(struct driver_wmm * self) { int bytesPerBlock = self->wavefmt.nBlockAlign * self->splPerBlock; /* int bytes = internal->blocks * (sizeof(WAVEHDR) + bytesPerBlock); */ int bytes = self->blocks * (sizeof(*self->wh) + bytesPerBlock); int res; MMRESULT mmres; self->bigbuffer = malloc(bytes); if (self->bigbuffer != NULL) { int i; BYTE * b; muroard_memzero(self->bigbuffer, bytes); self->wh = self->bigbuffer; self->spl = (LPBYTE) (self->wh+self->blocks); for (i=0, b=self->spl; iblocks; ++i, b+=bytesPerBlock) { self->wh[i].data = b; self->wh[i].wh.lpData = self->wh[i].data; self->wh[i].length = bytesPerBlock; self->wh[i].wh.dwBufferLength = self->wh[i].length; self->wh[i].wh.dwUser = (DWORD_PTR)self; mmres = waveOutPrepareHeader(self->hwo, &self->wh[i].wh,sizeof(WAVEHDR)); if (MMSYSERR_NOERROR != mmres) { break; } } if (iblocks) { while (--i >= 0) { waveOutUnprepareHeader(self->hwo, &self->wh[i].wh,sizeof(WAVEHDR)); } free(self->bigbuffer); self->wh = 0; self->spl = 0; self->bigbuffer = 0; } else { /* all ok ! */ } } res = (self->bigbuffer != NULL); return res; } static int _get_free_block(struct driver_wmm * self); static int _wait_wave_headers(struct driver_wmm * self, int wait_all) { int res = 1; while (self->sent_blocks > 0) { int n; _get_free_block(self); n = self->sent_blocks; if (n > 0) { unsigned int ms = (self->msPerBlock>>1)+1; if (wait_all) ms *= n; Sleep(ms); } } res &= !self->sent_blocks; return res; } static int _get_free_block(struct driver_wmm * self) { const int idx = self->widx; int ridx = self->ridx; while (self->wh[ridx].sent && !!(self->wh[ridx].wh.dwFlags & WHDR_DONE)) { /* block successfully sent to hardware, release it */ /*debug("_ao_get_free_block: release block %d\n",ridx);*/ self->wh[ridx].sent = 0; self->wh[ridx].wh.dwFlags &= ~WHDR_DONE; --self->full_blocks; if (self->full_blocks<0) { self->full_blocks = 0; } --self->sent_blocks; if (self->sent_blocks<0) { self->sent_blocks = 0; } if (++ridx >= self->blocks) ridx = 0; } self->ridx = ridx; return self->wh[idx].sent ? -1 : idx; } static int _free_wave_headers(struct driver_wmm * self) { MMRESULT mmres; int res = 1; if (self->wh) { int i; /* Reset so we dont need to wait ... Just a satefy net * since _ao_wait_wave_headers() has been called once before. */ mmres = waveOutReset(self->hwo); /* Wait again to be sure reseted waveheaders has been released. */ _wait_wave_headers(self, 0); for (i=self->blocks; --i>=0; ) { mmres = waveOutUnprepareHeader(self->hwo, &self->wh[i].wh,sizeof(WAVEHDR)); res &= mmres == MMSYSERR_NOERROR; } self->wh = 0; self->spl = 0; } return res; } /* Send a block to audio hardware */ static int _send_block(struct driver_wmm * self, const int idx) { MMRESULT mmres; dbg printf("_send_block(*) = ?\n"); /* Satanity checks */ if (self->wh[idx].sent) { return 0; } if (!!(self->wh[idx].wh.dwFlags & WHDR_DONE)) { return 0; } /* count <= 0, just pretend it's been sent */ if (self->wh[idx].count <= 0) { self->wh[idx].sent = 2; /* set with 2 so we can track these special cases */ self->wh[idx].wh.dwFlags |= WHDR_DONE; ++self->sent_blocks; return 1; } self->wh[idx].wh.dwBufferLength = self->wh[idx].count; self->wh[idx].count = 0; mmres = waveOutWrite(self->hwo, &self->wh[idx].wh, sizeof(WAVEHDR)); self->wh[idx].sent = (mmres == MMSYSERR_NOERROR); /*&& !(internal->wh[idx].wh.dwFlags & WHDR_DONE);*/ self->sent_blocks += self->wh[idx].sent; return mmres == MMSYSERR_NOERROR; } int muroard_driver_init(const char * dev) { struct driver_wmm * self = muroard_malloc(sizeof(struct driver_wmm)); MMRESULT mmres; muroard_state_member(driver_vp) = self; dbg printf("muroard_driver_init(dev='%s') = ?\n", dev); dbg printf("muroard_driver_init(dev='%s'): rate=%i, channels=%i, bits=16\n", dev, muroard_state_member(sa_rate), muroard_state_member(sa_channels)); muroard_memzero(self, sizeof(*self)); // WMM Setup: self->wavefmt.wFormatTag = WAVE_FORMAT_PCM; self->wavefmt.nChannels = muroard_state_member(sa_channels); self->wavefmt.wBitsPerSample = 16; self->wavefmt.nSamplesPerSec = muroard_state_member(sa_rate); self->wavefmt.nBlockAlign = (self->wavefmt.wBitsPerSample>>3)*self->wavefmt.nChannels; self->wavefmt.nAvgBytesPerSec = self->wavefmt.nSamplesPerSec*self->wavefmt.nBlockAlign; self->wavefmt.cbSize = 0; /* $$$ later this should be optionnal parms */ self->id = WAVE_MAPPER; self->blocks = MUROARD_FEATURE_DRIVER_WMM_FRAGMENTS; //self->splPerBlock = 512; #ifdef MUROARD_FIXED_ABUFFER_SIZE self->splPerBlock = MUROARD_FIXED_ABUFFER_SIZE / self->wavefmt.nBlockAlign; #else self->splPerBlock = MUROARD_DEFAULT_FRAMES_PER_CYCLE; #endif self->msPerBlock = (self->splPerBlock * 1000 + muroard_state_member(sa_rate) - 1) / muroard_state_member(sa_rate); mmres = waveOutOpen(&(self->hwo), self->id, &(self->wavefmt), (DWORD_PTR)0/* waveOutProc */, (DWORD_PTR)self, CALLBACK_NULL/* |WAVE_FORMAT_DIRECT */|WAVE_ALLOWSYNC); if ( mmres != MMSYSERR_NOERROR ) { muroard_driver_free(); dbg printf("muroard_driver_init(dev='%s') = -1 //mmres=%i, WAVERR_BADFORMAT=%i\n", dev, (int)mmres, WAVERR_BADFORMAT); return -1; } // FIXME: do error checking waveOutGetID(self->hwo, &(self->id)); _alloc_wave_headers(self); self->opened = 1; dbg printf("muroard_driver_init(dev='%s') = 0\n", dev); return 0; } int muroard_driver_free(void) { struct driver_wmm * self = muroard_state_member(driver_vp); dbg printf("muroard_driver_free(void) = ?\n"); if ( self->opened ) { _wait_wave_headers(self, 1); _free_wave_headers(self); waveOutClose(self->hwo); } muroard_free(self); dbg printf("muroard_driver_free(void) = 0\n"); return 0; } ssize_t muroard_driver_write(int16_t * data, size_t len, enum muroard_blocking blocking) { struct driver_wmm * self = muroard_state_member(driver_vp); ssize_t ret_ok = len; int ret = 1; if ( blocking == MUROARD_BLOCKING_NONE ) return -1; dbg printf("muroard_driver_write(data=%p) = ?\n", data); if ( ! self->opened ) return -1; dbg printf("muroard_driver_write(data=%p) = ?\n", data); dbg printf("-----------------\n"); while(ret && len > 0) { int n; const int idx = _get_free_block(self); dbg printf("muroard_driver_write(data=%p): XXX\n", data); if (idx == -1) { dbg printf("sleep of %ims\n", self->msPerBlock); Sleep(self->msPerBlock); continue; } else { dbg printf("continue...\n"); } /* Get free bytes in the block */ n = self->wh[idx].wh.dwBufferLength - self->wh[idx].count; /* debug("free in block %d : %d/%d\n", */ /* idx,n,internal->wh[idx].dwBufferLength); */ /* Get amount to copy */ if (n > (int)len) { n = len; } /* debug("copy = %d\n",n); */ /* Do copy */ CopyMemory((char*)self->wh[idx].wh.lpData + self->wh[idx].count, data, n); /* Updates pointers and counters */ data += n; len -= n; /* debug("rem = %d\n",num_bytes); */ self->wh[idx].count += n; /* Is this block full ? */ if (self->wh[idx].count == self->wh[idx].wh.dwBufferLength) { ++self->full_blocks; /* debug("blocks %d full, total:%d\n",internal->widx,internal->full_blocks); */ if (++self->widx == self->blocks) { self->widx = 0; } ret = _send_block(self, idx); } } dbg printf("muroard_driver_write(data=%p) = %i\n", data, (int)(ret > -1 ? ret_ok : -1)); return ret > -1 ? ret_ok : -1; } //ll muroard-0.1.14/dsp.c0000644000175000017500000001146112126652354012333 0ustar phiphi//dsp.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" int muroard_dsp_mixer(int16_t * out, int16_t ** in, size_t num) { size_t i; size_t n; register int32_t s; switch (num) { #ifdef MUROARD_FEATURE_OPTIMIZE case 0: muroard_memzero(out, muroard_state_member(abuffer_size)); break; /* This case can not happen as the waveform code will use zero-copy. case 1: memcpy(out, in[0], muroard_state_member(abuffer_size)); break; */ case 2: for (i = 0; i < muroard_state_member(abuffer_size)/2; i++) { s = 0; s += in[0][i]; s += in[1][i]; out[i] = s; } break; case 3: for (i = 0; i < muroard_state_member(abuffer_size)/2; i++) { s = 0; s += in[0][i]; s += in[1][i]; s += in[2][i]; out[i] = s; } break; #endif default: for (i = 0; i < muroard_state_member(abuffer_size)/2; i++) { s = 0; for (n = 0; n < num; n++) s += in[n][i]; out[i] = s; } break; } return 0; } #ifdef MUROARD_FEATURE_UPMIX void muroard_dsp_upmix(void * data, size_t samples) { int16_t * ds = data; int16_t * dd = data; ssize_t i, c; register int32_t s; samples--; #ifdef MUROARD_FEATURE_OPTIMIZE switch (muroard_state_member(sa_channels)) { case 1: return; break; case 2: for (i = samples*2 /* stereo */; i >= 0; i -= 2) { s = ds[i/2]; dd[i+0] = s; dd[i+1] = s; } break; case 3: for (i = samples*3 /* 3 channel */; i >= 0; i -= 3) { s = ds[i/3]; dd[i+0] = s; dd[i+1] = s; dd[i+2] = s; } break; case 4: for (i = samples*4 /* quad */; i >= 0; i -= 4) { s = ds[i/4]; dd[i+0] = s; dd[i+1] = s; dd[i+2] = s; dd[i+3] = s; } break; default: #endif for (i = samples; i >= 0; i--) { s = ds[i]; for (c = 0; c < muroard_state_member(sa_channels); c++) { dd[i*muroard_state_member(sa_channels)+c] = s; } } #ifdef MUROARD_FEATURE_OPTIMIZE break; } #endif } #endif #ifdef MUROARD_FEATURE_DOWNMIX void muroard_dsp_downmix(void * data, size_t samples) { int16_t * ds = data; int16_t * dd = data; ssize_t c; size_t i; register int32_t s; #ifdef MUROARD_FEATURE_OPTIMIZE switch (muroard_state_member(sa_channels)) { case 1: return; break; case 2: for (i = 0; i < samples*2; i += 2) { s = ds[i + 0]; s += ds[i + 1]; dd[i/2] = s / 2; } break; case 3: for (i = 0; i < samples*3; i += 3) { s = ds[i + 0]; s += ds[i + 1]; s += ds[i + 2]; dd[i/3] = s / 3; } break; case 4: for (i = 0; i < samples*4; i += 4) { s = ds[i + 0]; s += ds[i + 1]; s += ds[i + 2]; s += ds[i + 3]; dd[i/4] = s / 4; } break; default: #endif for (i = 0; i < samples; i++) { s = 0; for (c = 0; c < muroard_state_member(sa_channels); c++) { s += ds[i*muroard_state_member(sa_channels) + c]; } dd[i] = s / muroard_state_member(sa_channels); } #ifdef MUROARD_FEATURE_OPTIMIZE } #endif } #endif #ifdef MUROARD_FEATURE_UPSCALE void muroard_dsp_upscale(void * data, size_t samples) { char * ds = data; int16_t * dd = data; ssize_t i; samples--; for (i = samples; i >= 0; i--) dd[i] = ds[i] << 8; } #endif #ifdef MUROARD_FEATURE_DOWNSCALE void muroard_dsp_downscale(void * data, size_t samples) { int16_t * ds = data; char * dd = data; size_t i; for (i = 0; i < samples; i++) dd[i] = ds[i] >> 8; } #endif #ifdef MUROARD_FEATURE_BYTE_SWAP void muroard_dsp_swap16(int16_t * data, size_t samples) { register size_t i; for (i = 0; i < samples; i++) { data[i] = ((data[i] << 8) & 0xFF00) | ((data[i] >> 8) & 0x00FF); } } #endif #ifdef MUROARD_FEATURE_VOLUME_CONTROL void muroard_dsp_volume(int16_t * data, size_t samples, uint16_t volume) { register int_least32_t s; register size_t i; for (i = 0; i < samples; i++) { s = data[i] * volume; s /= 65535; data[i] = s; } } #endif //ll muroard-0.1.14/dsp.h0000644000175000017500000000405212126652354012336 0ustar phiphi//dsp.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _MUROARD_DSP_H_ #define _MUROARD_DSP_H_ // macros to test if we need to swap: #ifdef MUROARD_FEATURE_BYTE_SWAP #if MUROAR_CODEC_PCM_S == MUROAR_CODEC_PCM_S_BE #define muroard_dsp_need_swap_s(c) ((c) == MUROAR_CODEC_PCM_S_BE ? 0 : 1) #define muroard_dsp_need_swap_u(c) ((c) == MUROAR_CODEC_PCM_U_BE ? 0 : 1) #else #define muroard_dsp_need_swap_s(c) ((c) == MUROAR_CODEC_PCM_S_BE ? 1 : 0) #define muroard_dsp_need_swap_u(c) ((c) == MUROAR_CODEC_PCM_U_BE ? 1 : 0) #endif #endif int muroard_dsp_mixer(int16_t * out, int16_t ** in, size_t num); #ifdef MUROARD_FEATURE_UPMIX void muroard_dsp_upmix(void * data, size_t samples); #endif #ifdef MUROARD_FEATURE_DOWNMIX void muroard_dsp_downmix(void * data, size_t samples); #endif #ifdef MUROARD_FEATURE_UPSCALE void muroard_dsp_upscale(void * data, size_t samples); #endif #ifdef MUROARD_FEATURE_DOWNSCALE void muroard_dsp_downscale(void * data, size_t samples); #endif #ifdef MUROARD_FEATURE_BYTE_SWAP void muroard_dsp_swap16(int16_t * data, size_t samples); #endif #ifdef MUROARD_FEATURE_VOLUME_CONTROL void muroard_dsp_volume(int16_t * data, size_t samples, uint16_t volume); #endif #endif //ll muroard-0.1.14/empty.c0000644000175000017500000000170012126652354012676 0ustar phiphi//*.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2011-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" //ll muroard-0.1.14/empty.h0000644000175000017500000000173712126652354012715 0ustar phiphi//*.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _MUROARD_*_H_ #define _MUROARD_*_H_ #endif //ll muroard-0.1.14/features.h0000644000175000017500000003120012133577165013365 0ustar phiphi//features.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ /* * This header contains the user configuration for µRoarD. */ #ifndef _MUROARD_FEATURES_H_ #define _MUROARD_FEATURES_H_ /*********************************************************/ /* below you find general/misc features */ /*********************************************************/ // Support help text? (--help/-h): #define MUROARD_FEATURE_HELP_TEXT // Support version text? (--version): #define MUROARD_FEATURE_VERSION_TEXT // Support progress arguments (argv[]): #define MUROARD_FEATURE_ARGV // Add unneeded code that optimzire CPU load?: // This may make the binary a bit bigger but faster #define MUROARD_FEATURE_OPTIMIZE // Include signal handling?: #define MUROARD_FEATURE_SIGNALS // Support to daemonize?: #define MUROARD_FEATURE_DAEMONIZE // Support standby mode?: #define MUROARD_FEATURE_STANDBY // Activate auto standby by default?: #define MUROARD_FEATURE_STANDBY_AUTOMODE // Start in standby mode by default?: //#define MUROARD_FEATURE_STANDBY_ACTIVE /*********************************************************/ /* below you find the default audio settings */ /*********************************************************/ // Sample rate for the server: // The server will reject all streams with a diffrent rate. #define MUROARD_DEFAULT_RATE 44100 // nummber of channels: #define MUROARD_DEFAULT_CHANNELS 2 // size of the internal cycle: #define MUROARD_DEFAULT_FRAMES_PER_CYCLE (muroard_state_member(sa_rate)/25) /* 40ms */ // Fixed audio buffer size (in Bytes): // This is used to use a fixed audio buffer size. // It is only useful in case when there is no malloc() for your system or // you want to enforce muroard is locked in memory. //#define MUROARD_FIXED_ABUFFER_SIZE 7056 /*********************************************************/ /* below you find the settings for DSP features */ /*********************************************************/ // Enable support for upmix signals from mono?: // This may be buggy. #define MUROARD_FEATURE_UPMIX_INPUT // Enable support for downmix signals to mono?: // This may be buggy. #define MUROARD_FEATURE_DOWNMIX_OUTPUT // Enable support fo upscale signals from 8 to 16 bit?: #define MUROARD_FEATURE_UPSCALE_INPUT // Enable support fo downscale signals from 16 to 8 bit?: #define MUROARD_FEATURE_DOWNSCALE_OUTPUT // Enable support to convert between diffrent byte orders?: #define MUROARD_FEATURE_BYTE_SWAP // Enable software volume control?: #define MUROARD_FEATURE_VOLUME_CONTROL /*********************************************************/ /* below you find the codecfilter settings */ /*********************************************************/ // Should we support codec filters at all?: #define MUROARD_FEATURE_CODECFILTER // Should we support the Sun's AU container?: #define MUROARD_FEATURE_CODECFILTER_AU // Should we support M$'s RIFF/WAVE container?: #define MUROARD_FEATURE_CODECFILTER_RIFF_WAVE // Should we support Xiph's Ogg Vorbis?: #define MUROARD_FEATURE_CODECFILTER_OGG_VORBIS /*********************************************************/ /* below you find the stream settings */ /*********************************************************/ // Should we support MONITOR streams? #define MUROARD_FEATURE_MONITOR // Should we support stream position handling?: #define MUROARD_FEATURE_POSITION // Should we support re-reading and re-writing?: // This does not work on win32 as we need nonblocking sockets // for this to work correctly. #define MUROARD_FEATURE_REREADWRITE /*********************************************************/ /* below you find client and stream options */ /*********************************************************/ // Maximum number of clients on this server: #define MUROARD_MAX_CLIENTS 8 // Maximum number of streams on this server: #define MUROARD_MAX_STREAMS 8 // Support internal client (used for background streams): #define MUROARD_FEATURE_INTERNAL_CLIENT // Support sources and additional sinks?: #define MUROARD_FEATURE_SOURCES /*********************************************************/ /* below you find driver options */ /*********************************************************/ // Which driver should we build? // Keep undefined to use internal defaults. //#define MUROARD_FEATURE_DRIVER MUROARD_DRIVER_OSS // Default device to be used when user does not give one or // when compiled without MUROARD_FEATURE_ARGV. // Use NULL for driver's internal default. #define MUROARD_DEFAULT_DRIVER_DEV NULL // Client name to be used by the driver. // This is only used by drivers for sound interface // which have some kind of client concept. // This string is commonly used to identify the client // to the user. #define MUROARD_DEFAULT_DRIVER_CLIENT_NAME "muRoarD" // Default device for OSS: // Comment this out for no default device. #define MUROARD_DEFAULT_DRIVER_OSS_DEV "/dev/audio" // Support setting of OSS fragment size? // This is recommneted as it will lead in extra-high latency // on some systems if not enabled. #define MUROARD_FEATURE_DRIVER_OSS_SETFRAGMENT // The number of fragments (blocks) used in the ring buffer of // the WMM driver. #define MUROARD_FEATURE_DRIVER_WMM_FRAGMENTS 8 /*********************************************************/ /* below you find protocol options */ /*********************************************************/ // This is the maximum size of the data part of a // RoarAudio protocol message: #define MUROARD_MAX_MSGSIZE 256 /*********************************************************/ /* below you find command options */ /*********************************************************/ // Handle some commands we do not support as noops?: // Some of the commands can safely be handel as noop. // This may help with random clients, must be considered // a workarounds. #define MUROARD_FEATURE_NOOP_SIUCMDS // Support WHOAMI command?: // This command is not used by much clients but not much // code is needed to implemeent this. // keep enabled if you do not require to safe every byte // you can. #define MUROARD_FEATURE_CMD_WHOAMI // Support EXIT command?: // This enables the EXIT command. If you want to support // the termination option of this command, too, you need to // enable MUROARD_FEATURE_TERMINATE in addition to this option. #define MUROARD_FEATURE_CMD_EXIT // Support terminate feature?: // This will clients enable to set the server into // termination state. In termination state it will // terminate as soon as the last client disconnects. // while in termination state the server will not accept // new connections and closes the listening socket so a // new instance of the server can re-open it. #define MUROARD_FEATURE_TERMINATE // Support ATTACH command?: // This will enable simple attaches. // it will not work with background streams but will // enable the use-execed workaround of libroar. #define MUROARD_FEATURE_CMD_ATTACH // Support GET_STANDBY command?: // As this server does not support standby will // allways return 'server active' to client. #define MUROARD_FEATURE_CMD_GET_STANDBY // Support SERVER_OINFO?: // This command is used by the client to get infos on // native format of server. This may be very helpfull // as we do not support much formats. #define MUROARD_FEATURE_CMD_SERVER_OINFO // Support PSSFH command?: // This enables the client for passive streams and multi-stream // architectures. #define MUROARD_FEATURE_CMD_PASSFH // Support GET_VOL command?: // this is just a dummy at the moment, returning a volume of // 0dB (100%). #define MUROARD_FEATURE_CMD_GET_VOL // Support to list clients?: // this will implement the LIST_CLIENTS command. // you will most probably also want to enable // the GET_CLIENT command. #define MUROARD_FEATURE_CMD_LIST_CLIENTS // Support to list streams?: // this will implement the LIST_STREAMS command. // you will most probably also want to enable // the GET_STREAMS command. #define MUROARD_FEATURE_CMD_LIST_STREAMS // Support to get infos on a client?: // this implements the GET_CLIENT command. #define MUROARD_FEATURE_CMD_GET_CLIENT // Support sending a dummy name for clients?: #define MUROARD_FEATURE_GET_CLIENT_DUMMYNAME // Support to get infos on a stream?: // this implements the GET_STREAM command. #define MUROARD_FEATURE_CMD_GET_STREAM // Support KICK command?: // This enables clients to ckick streams and clients. #define MUROARD_FEATURE_CMD_KICK // Support CAPS command?: // This enables the CAPS/Standards command, which is used by clients // to find out what features are supported by the server. #define MUROARD_FEATURE_CMD_CAPS // Support for SERVER_INFO command?: // This enables support for SERVER_INFO/IT_SERVER command. // This command can be used by clients to get the version string // of this server. Other data is currently not supported. #define MUROARD_FEATURE_CMD_SERVER_INFO // Support GETTIMEOFDAY command?: // This enables support for GETTIMEOFDAY command. // this command is used to get server's system time. #define MUROARD_FEATURE_CMD_GETTIMEOFDAY /*********************************************************/ /* below you find network options */ /*********************************************************/ // support for client socket passing: #define MUROARD_FEATURE_CLIENT_FH // support to listen on sockets: #define MUROARD_FEATURE_SOCKET_LISTEN // support for IPv4 sockets: #define MUROARD_FEATURE_SOCKET_INET // support for UNIX sockets: #define MUROARD_FEATURE_SOCKET_UNIX // support for DECnet sockets: #define MUROARD_FEATURE_SOCKET_DECNET // default type for listen sockets: // ensure that this type is enabled above! // keep undefined to use internal default. //#define MUROARD_DEFAULT_LISTEN_TYPE MUROARD_NETWORK_TYPE_UNIX // default address of UNIX socket to listen on: #define MUROARD_DEFAULT_LISTEN_ADDR_UNIX "/tmp/muroard" // default address of IPv4 host to listen on: #define MUROARD_DEFAULT_LISTEN_ADDR_INET "localhost" // default address of DECnet host to listen on: #define MUROARD_DEFAULT_LISTEN_ADDR_DECNET "::roar" // default port (only IPv4) to listen on: // port 16002 is RoarAudio default #define MUROARD_DEFAULT_LISTEN_PORT 16002 // File Mode to set on opened UNIX Sockets: // undef to not use this. #define MUROARD_DEFAULT_LISTEN_CHMOD 0770 /*********************************************************/ /* below you find memory mangement options */ /*********************************************************/ // Use internal malloc rutines: // It is only useful in case when there is no malloc() for your system or // you want to enforce muroard is locked in memory. //#define MUROARD_MEMMGR_NOUSE_MALLOC // Try to lock all memory?: // This is useful to ensure muRoarD running smoothly in an environment low on memory. // It is strongly recommended to use MUROARD_MEMMGR_NOUSE_MALLOC with this option. #define MUROARD_MEMMGR_LOCK_ALL // Should we fail if memory locking can not be done? // This is only useful in very special environments. //#define MUROARD_MEMMGR_LOCK_ALL_FAIL_ON_ERROR // Flags to pass to mlockall()?: // Most systems provide MCL_CURRENT and MCL_FUTURE. #define MUROARD_MEMMGR_LOCK_ALL_FLAGS MCL_CURRENT /*********************************************************/ /* below you find features which are not yet implemented */ /*********************************************************/ /* * #define MUROARD_FEATURE_UNSIGNED_8BIT * #define MUROARD_FEATURE_UNSIGNED_16BIT * #define MUROARD_FEATURE_UNSIGNED * #define MUROARD_FEATURE_UPMIX * #define MUROARD_FEATURE_DOWNMIX * #define MUROARD_FEATURE_CMD_BEEP * #define MUROARD_FEATURE_CMD_CON_STREAM // #39 * #define MUROARD_FEATURE_META_DATA // #42 * #define MUROARD_FEATURE_STREAM_FLAGS // #43 */ #endif //ll muroard-0.1.14/libmuroard.ckport0000644000175000017500000000742312155464351014770 0ustar phiphi#ckport(1) database for libmuroard: !NAME: muroard library !TYPE: func !TARGET: libmuroard3 # Startup and shutdown muroard_daemonize maybe only available if compiled with MUROARD_FEATURE_DAEMONIZE muroard_usage maybe only available if compiled with MUROARD_FEATURE_HELP_TEXT muroard_version maybe only available if compiled with MUROARD_FEATURE_VERSION_TEXT muroard_main ok muroard_main_initonly ok muroard_mainloop ok muroard_mainloop_iteration ok muroard_shutdown ok muroard_init ok muroard_init_signals maybe only available if compiled with MUROARD_FEATURE_SIGNALS muroard_on_sig internal muroard_para_init internal # Clients: muroard_client_init internal muroard_client_free internal muroard_client_new ok muroard_client_delete ok muroard_client_exec likely Calling with without request by the client may break stuff muroard_client_handle likely Is normally be called by muroard_network_check() muroard_client_handle_attach internal muroard_client_handle_caps internal muroard_client_handle_get_client internal muroard_client_handle_get_stream internal muroard_client_handle_gettimeofday internal muroard_client_handle_list_clients internal muroard_client_handle_list_streams internal muroard_client_handle_new_stream internal muroard_client_handle_passfh internal muroard_client_handle_server_info internal muroard_client_handle_server_oinfo internal # Streams: muroard_stream_free internal muroard_stream_init internal muroard_stream_delete ok muroard_stream_new ok muroard_stream_cksupport maybe only available if compiled with MUROARD_FEATURE_CODECFILTER muroard_stream_exec likely Calling with without request by the client may break stuff muroard_stream_move_client maybe only available if compiled with MUROARD_FEATURE_CMD_ATTACH muroard_stream_read ok muroard_stream_write maybe only available if compiled with MUROARD_FEATURE_MONITOR muroard_stream_network_read likely You normally want to call muroard_stream_read(). muroard_stream_network_write likely You normally want to call muroard_stream_write(). muroard_stream_new_source ok # Proto: muroard_proto_recv likely Communication with the client should not be done directly muroard_proto_send likely Communication with the client should not be done directly # Network: muroard_network_check ok muroard_network_free internal muroard_network_init internal muroard_network_listen maybe only available if compiled with MUROARD_FEATURE_SOCKET_LISTEN muroard_network_nonblock ok muroard_network_prefree ok muroard_network_recvfh likely Communication with the client should not be done directly # Waveform: muroard_waveform_free internal muroard_waveform_init internal muroard_waveform_standby maybe only available if compiled with MUROARD_FEATURE_STANDBY muroard_waveform_update ok # DSP stuff: muroard_dsp_mixer ok muroard_dsp_downmix maybe only available if compiled with MUROARD_FEATURE_DOWNMIX muroard_dsp_downscale maybe only available if compiled with MUROARD_FEATURE_DOWNSCALE muroard_dsp_swap16 maybe only available if compiled with MUROARD_FEATURE_BYTE_SWAP muroard_dsp_upmix maybe only available if compiled with MUROARD_FEATURE_UPMIX muroard_dsp_upscale maybe only available if compiled with MUROARD_FEATURE_UPSCALE muroard_dsp_volume maybe only available if compiled with MUROARD_FEATURE_VOLUME_CONTROL # Codec filters: muroard_cf_au_read internal muroard_cf_riff_wave_read internal # ... ogg_vorbis: _read internal _return_err internal muroard_cf_ogg_vorbis_close internal muroard_cf_ogg_vorbis_read internal muroard_cf_ogg_vorbis_private_read internal muroard_cf_ogg_vorbis_private_return_err internal # Memory functions: muroard_memmgr_lock_all internal !NAME: muroard backend library !TYPE: func !TARGET: libmuroard-backend3 muroard_driver_free ok muroard_driver_init ok muroard_driver_write ok #ll muroard-0.1.14/main.c0000644000175000017500000000210712126652354012466 0ustar phiphi//main.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2011-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" int main (int argc, char * argv[]) { struct muroard_state state; muroard_g_state = &state; return muroard_main(argc, argv); } //ll muroard-0.1.14/memmgr.c0000644000175000017500000000403712126652354013032 0ustar phiphi//memmgr.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2011-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #ifdef MUROARD_MEMMGR_LOCK_ALL #ifndef __WIN32 #include #endif #endif #ifdef MUROARD_MEMMGR_NOUSE_MALLOC #define POOLSIZE (1+MUROARD_MAX_STREAMS) static char _memory_pool[POOLSIZE][MUROARD_FIXED_ABUFFER_SIZE]; static char _memory_pool_map[POOLSIZE]; int muroard_memmgr_init(void) { muroard_memzero(_memory_pool, sizeof(_memory_pool)); muroard_memzero(_memory_pool_map, sizeof(_memory_pool_map)); return 0; } void * muroard_malloc(size_t size) { int i; if ( size != MUROARD_FIXED_ABUFFER_SIZE ) return NULL; for (i = 0; i < POOLSIZE; i++) { if ( _memory_pool_map[i] == 0 ) { _memory_pool_map[i] = 1; return _memory_pool[i]; } } return NULL; } void muroard_free(void * ptr) { int i; for (i = 0; i < POOLSIZE; i++) { if ( _memory_pool[i] == ptr ) { _memory_pool_map[i] = 0; return; } } } #endif #ifdef MUROARD_MEMMGR_LOCK_ALL int muroard_memmgr_lock_all(void) { #ifdef __WIN32 #warning MUROARD_MEMMGR_LOCK_ALL but not supported on win32. return -1; #else if ( mlockall(MUROARD_MEMMGR_LOCK_ALL_FLAGS) == -1 ) return -1; #endif return 0; } #endif //ll muroard-0.1.14/memmgr.h0000644000175000017500000000267212126652354013042 0ustar phiphi//memmgr.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _MUROARD_MEMMGR_H_ #define _MUROARD_MEMMGR_H_ #ifdef MUROARD_MEMMGR_NOUSE_MALLOC int muroard_memmgr_init(void); void * muroard_malloc(size_t size); void muroard_free(void * ptr); #else #define muroard_memmgr_init() (0) #define muroard_malloc(size) malloc((size)) #define muroard_free(ptr) free((ptr)) #endif #ifndef muroard_memzero #define muroard_memzero(ptr,size) memset((ptr), 0, (size)) #endif #ifdef MUROARD_MEMMGR_LOCK_ALL int muroard_memmgr_lock_all(void); #endif #endif //ll muroard-0.1.14/muroard.10000644000175000017500000000553412210357674013141 0ustar phiphi.\" muroard.1: .TH "muroard" "1" "March 2010" "RoarAudio" "System User's Manual: muroard" .SH NAME muroard \- minimalist sound server for the RoarAudio protocol .SH SYNOPSIS muroard [OPTIONS]... .SH DESCRIPTION muRoarD is a sound server supporting the RoarAudio protocol. It is designed to mix the audio data of multiple applications together to send it as a single stream to the soundcard. muRoarD is a minimalist version of such a sound server. It does only implement the very minimum part the the protocol but is very much smaller than the original roard. .SH "MISC OPTIONS" .TP \fB-h \-\-help\fR Print a short help and exit. .TP \fB--version\fR Print version information of the daemon and exit. .TP \fB--daemon\fR Bring the server into background after init. On win32 this hides the console window. This only works if used within a Shortcut. .TP \fB--autostandby\fR Start in autostandby mode. .TP \fB--no-autostandby\fR Do not start in autostandby mode. .TP \fB--standby\fR Start in standby mode. .TP \fB--no-standby\fR Do not start in standby mode. .SH "AUDIO OPTIONS" .TP \fB-R \-\-rate RATE\fR Set server sample rate. .TP \fB-C \-\-chans CHANNELS\fR Set server number of channels channels. .SH "DRIVER OPTIONS" .TP \fB-O \-\-odevice DEV\fR Set output device (sound card). The possible values of this depend on the used driver. .SH "SOURCES OPTIONS" .TP \fB-S DEV\fR Set the file or device for the new source. .TP \fB-sC CHANS\fR Sets the number of channels for the source. This is the same as '\-sO channels=XXX' for roard. .TP \fB-sB BITS\fR Sets the number of bits for the source. This is the same as '\-sO bits=XXX' for roard. .TP \fB-sE CODEC\fR Sets codec for the source. This is the same as '\-sO codec=XXX' for roard. .TP \fB-sD DIR\fR Sets direction of the source: in (source) or out (dump). .SH "NETWORK OPTIONS" .TP \fB--no-listen\fR Disable listen socket. This may be used for example to implement the server type '+fork' but is absolutly useless for normal users. .TP \fB--client-fh FH\fR Add a client via FH. See \fB--no-listen\fR. .TP \fB--bind ADDR\fR Set path/hostname of listen socket. This may be a /path/to/sock for UNIX Sockets or a hostname or address for TCP/IP. Please do not use IP Addresses directly if not needed. Use hostnames. On win32 there is no support for UNIX sockets. Only IP is supported. .TP \fB--port PORT\fR Set port of listen socket. This only applys for TCP/IP sockets and is ignorged for UNIX Sockets. .TP \fB-u \-\-unix\fR Use UNIX Domain listen socket. This is not supported on win32. .TP \fB-t \-\-tcp\fR Use TCP/IP listen socket. .TP \fB-n \-\-decnet\fR Use DECnet listen socket. .SH "SEE ALSO" \fBmuroarstream\fR(1), \fBRoarAudio\fR(7). .SH "HISTORY" The first offical version of muRoarD (0.1beta0) was released on Wed Mar 03 2010 24:26 CET. For more information please see the file ChangeLog. .\" ll muroard-0.1.14/muroard.c0000644000175000017500000002733512210357674013226 0ustar phiphi//muroard.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #if defined(MUROARD_FEATURE_DAEMONIZE) && defined(__WIN32) #include #endif struct muroard_state * muroard_g_state; #ifdef MUROARD_FEATURE_HELP_TEXT void muroard_usage (void) { printf("Usage: muroard [OPTIONS]...\n\n"); printf("Misc Options:\n\n"); printf(" -h --help - Print this help\n" #ifdef MUROARD_FEATURE_VERSION_TEXT " --version - Print version string\n" #endif #ifdef MUROARD_FEATURE_DAEMONIZE " --daemon - Bring the server into background after init\n" #endif #ifdef MUROARD_FEATURE_STANDBY " --autostandby - Start in autostandby mode" #ifdef MUROARD_FEATURE_STANDBY_AUTOMODE " (default)\n" #else "\n" #endif " --no-autostandby - Do not start in autostandby mode" #ifdef MUROARD_FEATURE_STANDBY_AUTOMODE "\n" #else " (default)\n" #endif " --standby - Start in standby mode" #ifdef MUROARD_FEATURE_STANDBY_ACTIVE " (default)\n" #else "\n" #endif " --no-standby - Do not start in standby mode" #ifdef MUROARD_FEATURE_STANDBY_ACTIVE "\n" #else " (default)\n" #endif #endif ); printf("\nAudio Options:\n\n"); printf( " -R --rate RATE - Set server rate\n" " -C --chans CHANNELS - Set server channels\n" ); printf("\nDriver Options:\n\n"); printf( " -O --odevice DEV - Set output device\n" ); #ifdef MUROARD_FEATURE_SOURCES printf("\nSources Options:\n\n"); printf( " -S DEV - Set source device or filename\n" " -sC CHANS - Set source number of channels\n" " -sB BITS - Set source number of bits\n" " -sE CODEC - Set source codec (no symbolic names)\n" " -sD DIR - Set source direction: in or out\n" ); #endif printf("\nNetwork Options:\n\n"); printf("" #ifdef MUROARD_FEATURE_SOCKET_LISTEN " --no-listen - Disable listen socket\n" #endif #ifdef MUROARD_FEATURE_CLIENT_FH " --client-fh FH - Add a client via FH\n" #endif #ifdef MUROARD_FEATURE_SOCKET_LISTEN " --bind ADDR - Set path/hostname of listen socket\n" " --port PORT - Set port of listen socket\n" #endif #ifdef MUROARD_FEATURE_SOCKET_UNIX " -u --unix - Use UNIX Domain listen socket\n" #endif #ifdef MUROARD_FEATURE_SOCKET_INET " -t --tcp - Use TCP listen socket\n" #endif #ifdef MUROARD_FEATURE_SOCKET_DECNET " -n --decnet - Use DECnet listen socket\n" #endif ); } #else #define muroard_usage() #endif #ifdef MUROARD_FEATURE_VERSION_TEXT void muroard_version (void) { printf("Version: %s\n", MUROARD_VERSION); } #endif // signal handler: #ifdef MUROARD_FEATURE_SIGNALS void muroard_on_sig(int sig) { (void)sig; // we do not need this parameter muroard_state_member(alive) = 0; // terminate daemon } #endif #ifdef MUROARD_FEATURE_SIGNALS void muroard_init_signals(void) { signal(SIGINT, muroard_on_sig); signal(SIGTERM, muroard_on_sig); signal(SIGPIPE, SIG_IGN); } #endif #ifdef MUROARD_FEATURE_DAEMONIZE void muroard_daemonize(void) { #ifdef __WIN32 FreeConsole(); #else close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); if ( fork() ) exit(0); setsid(); #endif } #endif int muroard_init(void) { if ( muroard_memmgr_init() == -1 ) { return -1; } #ifdef MUROARD_MEMMGR_LOCK_ALL #ifdef MUROARD_MEMMGR_LOCK_ALL_FAIL_ON_ERROR if ( muroard_memmgr_lock_all() == -1 ) { return -1; } #else muroard_memmgr_lock_all(); #endif #endif if ( muroard_network_init() == -1 ) { return -1; } if ( muroard_waveform_init() == -1 ) { return -1; } if ( muroard_client_init() == -1 ) { return -1; } if ( muroard_stream_init() == -1 ) { return -1; } return 0; } int muroard_mainloop_iteration(enum muroard_blocking network_blocking, enum muroard_blocking audio_blocking) { int ret; if ( muroard_network_check(network_blocking) == -1 ) { muroard_state_member(alive) = 0; return -1; } if ( (ret = muroard_waveform_update(audio_blocking)) == -1 ) { muroard_state_member(alive) = 0; return -1; } return ret; } void muroard_mainloop(void) { #ifdef MUROARD_FEATURE_STANDBY int ret = 0; #endif while (muroard_state_member(alive)) { #ifdef MUROARD_FEATURE_STANDBY ret = muroard_mainloop_iteration(ret == 0 ? MUROARD_BLOCKING_NONE : MUROARD_BLOCKING_LONG, MUROARD_BLOCKING_LONG); if ( ret == -1 ) break; #else if ( muroard_mainloop_iteration(MUROARD_BLOCKING_NONE, MUROARD_BLOCKING_LONG) == -1 ) break; #endif } } void muroard_shutdown(void) { muroard_network_prefree(); // this will free the listen socket early muroard_driver_free(); muroard_stream_free(); muroard_client_free(); muroard_waveform_free(); muroard_network_free(); } int muroard_main_initonly (int argc, char * argv[]) { #ifdef __WIN32 #define __check_argc(num) if ( (argc - i) <= (num) ) { return 64; } #else #define __check_argc(num) if ( (argc - i) <= (num) ) { errno = EINVAL; return 64; } #endif #ifdef MUROARD_FEATURE_SOCKET_LISTEN int n_type = MUROARD_DEFAULT_LISTEN_TYPE; const char * n_addr = NULL; // use defualts from network module int n_port = MUROARD_DEFAULT_LISTEN_PORT; int n_no_listen = 0; #endif #ifdef MUROARD_FEATURE_ARGV int i; const char * k; const char * o_dev = MUROARD_DEFAULT_DRIVER_DEV; #ifdef MUROARD_FEATURE_DAEMONIZE int daemon = 0; #endif #ifdef MUROARD_FEATURE_CLIENT_FH muroard_handle_t c_sock[MUROARD_MAX_CLIENTS]; int c_sock_count = 0; // this is int so we can use 'i' in the for(){}. #endif #endif #ifdef MUROARD_FEATURE_SOURCES const char * s_filename = NULL; int s_dir = STREAM_DATADIR_IN; struct muroard_audio_info s_info = {.channels = muroard_state_member(sa_channels), .bits = 16, .codec = MUROAR_CODEC_PCM_S}; #endif #ifndef MUROARD_FEATURE_ARGV (void)argc, (void)argv; #endif muroard_para_init(muroard_g_state); #ifdef MUROARD_FEATURE_ARGV for (i = 1; i < argc; i++) { k = argv[i]; #ifdef MUROARD_FEATURE_HELP_TEXT if ( !strcmp(k, "--help") || !strcmp(k, "-h") ) { __check_argc(0) muroard_usage(); return 0; #else if ( 0 ) { // noop. #endif #ifdef MUROARD_FEATURE_VERSION_TEXT } else if ( !strcmp(k, "--version") ) { __check_argc(0) muroard_version(); return 0; #endif #ifdef MUROARD_FEATURE_DAEMONIZE } else if ( !strcmp(k, "--daemon") ) { __check_argc(0) daemon = 1; #endif #ifdef MUROARD_FEATURE_STANDBY } else if ( !strcmp(k, "--autostandby") ) { __check_argc(0) muroard_waveform_standby(-1, 1); } else if ( !strcmp(k, "--no-autostandby") ) { __check_argc(0) muroard_waveform_standby(-1, 0); } else if ( !strcmp(k, "--standby") ) { __check_argc(0) muroard_waveform_standby(1, -1); } else if ( !strcmp(k, "--no-standby") ) { __check_argc(0) muroard_waveform_standby(0, -1); #endif } else if ( !strcmp(k, "--rate") || !strcmp(k, "-R") ) { __check_argc(1) muroard_state_member(sa_rate) = atoi(argv[++i]); } else if ( !strcmp(k, "--channels") || !strcmp(k, "-C") ) { __check_argc(1) muroard_state_member(sa_channels) = atoi(argv[++i]); } else if ( !strcmp(k, "--odevice") || !strcmp(k, "-O") ) { __check_argc(1) o_dev = argv[++i]; #ifdef MUROARD_FEATURE_SOURCES } else if ( !strcmp(k, "-S") ) { __check_argc(1) s_filename = argv[++i]; } else if ( !strcmp(k, "-sC") ) { __check_argc(1) s_info.channels = atoi(argv[++i]); } else if ( !strcmp(k, "-sB") ) { __check_argc(1) s_info.bits = atoi(argv[++i]); } else if ( !strcmp(k, "-sE") ) { __check_argc(1) s_info.codec = atoi(argv[++i]); } else if ( !strcmp(k, "-sD") ) { __check_argc(1) i++; if ( !strcmp(argv[i], "in") ) { s_dir = STREAM_DATADIR_IN; } else if ( !strcmp(argv[i], "out") ) { s_dir = STREAM_DATADIR_OUT; } else { fprintf(stderr, "Error: Unknown stream direction: %s.\n", argv[i]); return 1; } /* TODO: this is currently not supported as the init for the streams will overwrite it. } else if ( !strcmp(k, "-sN") ) { if ( s_filename != NULL ) { if ( muroard_stream_new_source(s_filename, s_dir, &s_info) == -1 ) { fprintf(stderr, "Error: Can not add source/sink: %s.\n", s_filename); } } s_filename = NULL; s_dir = STREAM_DATADIR_IN; s_info.channels = muroard_g_sa_channels; s_info.bits = 16; s_info.codec = MUROAR_CODEC_PCM_S; */ #endif #ifdef MUROARD_FEATURE_SOCKET_LISTEN } else if ( !strcmp(k, "--no-listen") ) { __check_argc(0) n_no_listen = 1; #endif #ifdef MUROARD_FEATURE_CLIENT_FH } else if ( !strcmp(k, "--client-fh") ) { __check_argc(1) c_sock[c_sock_count++] = atoi(argv[++i]); #endif #ifdef MUROARD_FEATURE_SOCKET_LISTEN } else if ( !strcmp(k, "--bind") ) { __check_argc(1) n_addr = argv[++i]; } else if ( !strcmp(k, "--port") ) { __check_argc(1) n_port = atoi(argv[++i]); #ifdef MUROARD_FEATURE_SOCKET_UNIX } else if ( !strcmp(k, "--unix") || !strcmp(k, "-u") ) { __check_argc(0) n_type = MUROARD_NETWORK_TYPE_UNIX; #endif #ifdef MUROARD_FEATURE_SOCKET_INET } else if ( !strcmp(k, "--tcp") || !strcmp(k, "-t") ) { __check_argc(0) n_type = MUROARD_NETWORK_TYPE_INET; #endif #ifdef MUROARD_FEATURE_SOCKET_DECNET } else if ( !strcmp(k, "--decnet") || !strcmp(k, "-n") ) { __check_argc(0) n_type = MUROARD_NETWORK_TYPE_DECNET; #endif #endif } else { muroard_usage(); return 1; } } #endif if ( muroard_init() == -1 ) return 1; #ifdef MUROARD_FEATURE_ARGV if ( muroard_driver_init(o_dev) == -1 ) { #else if ( muroard_driver_init(MUROARD_DEFAULT_DRIVER_DEV) == -1 ) { #endif return 3; } #ifdef MUROARD_FEATURE_SOURCES if ( s_filename != NULL ) { if ( muroard_stream_new_source(s_filename, s_dir, &s_info) == -1 ) { fprintf(stderr, "Error: Can not add source/sink: %s.\n", s_filename); } } #endif #ifdef MUROARD_FEATURE_CLIENT_FH for (i = 0; i < c_sock_count; i++) { if ( muroard_client_new(c_sock[i]) == -1 ) { return 1; } } #endif #ifdef MUROARD_FEATURE_SOCKET_LISTEN if ( !n_no_listen ) { if ( muroard_network_listen(n_type, n_addr, n_port) == -1 ) { return 2; } } #endif // everything is up, get it running!: muroard_state_member(alive) = 1; #ifdef MUROARD_FEATURE_SIGNALS muroard_init_signals(); #endif #if defined(MUROARD_FEATURE_DAEMONIZE) && defined(MUROARD_FEATURE_ARGV) if ( daemon ) { muroard_daemonize(); } #endif return 0; } int muroard_main (int argc, char * argv[]) { int ret; if ( (ret = muroard_main_initonly(argc, argv)) != 0 ) return ret; muroard_mainloop(); muroard_shutdown(); return 0; } //ll muroard-0.1.14/muroard.h0000644000175000017500000000612012126652355013220 0ustar phiphi//muroard.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _MUROARD_H_ #define _MUROARD_H_ #include "features.h" /* feature config */ #include "deps.h" /* calc deps of config options */ // MUROARD_VERSION can not be used by externel applications as it depends // on parameters passed by the Makefile. #define MUROARD_VERSION "muroard/" PACKAGE_VERSION " <" DEVICE_VENDOR_STRING ">" DISTRIBUTION_VERSION_STRING #define muroard_handle_t int #define MUROARD_HANDLE_INVALID -1 #include #include #include #include /* Socket includes */ #ifdef __WIN32 #include #include #else #include #include #if defined(PF_UNIX) #include #endif #include #ifdef MUROARD_FEATURE_SOCKET_DECNET #include #include #endif #endif #if !defined(TARGET_MICROCONTROLLER) #include #endif #ifndef __WIN32 #include #endif #ifdef MUROARD_FEATURE_SIGNALS #include #endif #ifdef MUROARD_HAVE_FCHMOD #include #include #endif #ifdef __OpenBSD__ #include #endif #if defined(MUROARD_FEATURE_CODECFILTER) && defined(MUROARD_FEATURE_CODECFILTER_OGG_VORBIS) #define OV_EXCLUDE_STATIC_CALLBACKS #include #endif struct muroard_state; #include /* µRoar header file */ #include "para.h" /* server parameter and config */ #include "memmgr.h" /* macros for memory functions */ #include "callbacks.h" enum muroard_blocking { MUROARD_BLOCKING_NONE = 0, MUROARD_BLOCKING_LONG = -1, }; #include "network.h" #include "waveform.h" #include "proto.h" #include "driver.h" #include "dsp.h" #include "clients.h" #include "streams.h" #ifdef MUROARD_FEATURE_CODECFILTER #include "cf.h" #endif #include "state.h" void muroard_usage (void); void muroard_version (void); void muroard_init_signals(void); void muroard_daemonize(void); int muroard_init(void); int muroard_mainloop_iteration(enum muroard_blocking network_blocking, enum muroard_blocking audio_blocking); void muroard_mainloop(void); void muroard_shutdown(void); int muroard_main_initonly (int argc, char * argv[]); int muroard_main (int argc, char * argv[]); #endif //ll muroard-0.1.14/network.c0000644000175000017500000002225312126652355013240 0ustar phiphi//network.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #ifndef __WIN32 #include #endif int muroard_network_init(void) { #ifdef __WIN32 WSADATA wsadata; WSAStartup(MAKEWORD(1,1) , &wsadata); #endif return 0; } int muroard_network_free(void) { return muroard_network_prefree(); } int muroard_network_prefree(void) { #ifdef MUROARD_FEATURE_SOCKET_LISTEN if ( muroard_state_member(listen_socket) != MUROARD_HANDLE_INVALID ) muroard_network_close(muroard_state_member(listen_socket)); muroard_state_member(listen_socket) = MUROARD_HANDLE_INVALID; #ifdef MUROARD_FEATURE_SOCKET_LISTEN_SOCKTYPE muroard_state_member(listen_type) = -1; #endif #endif return 0; } #ifdef MUROARD_FEATURE_SOCKET_UNIX static inline int muroard_network_test_unix (const char * addr) { struct sockaddr_un un; muroard_handle_t fh; int ret; if ( (fh = socket(AF_UNIX, SOCK_STREAM, 0)) == MUROARD_HANDLE_INVALID ) return -1; un.sun_family = AF_UNIX; strncpy(un.sun_path, addr, sizeof(un.sun_path) - 1); if ( connect(fh, (struct sockaddr *)&un, sizeof(struct sockaddr_un)) == -1 ) { if ( errno == ECONNREFUSED ) { ret = 0; } else { ret = -1; } } else { ret = 1; } muroard_network_close(fh); return ret; } #endif #ifdef MUROARD_FEATURE_SOCKET_LISTEN int muroard_network_listen(int type, const char * addr, int port) { #ifdef MUROARD_FEATURE_SOCKET_UNIX struct sockaddr_un un; #endif #ifdef MUROARD_FEATURE_SOCKET_INET struct hostent * he; struct sockaddr_in in; #endif muroard_handle_t fh; #ifdef MUROARD_DEFAULT_LISTEN_CHMOD mode_t defmask; #endif #ifdef MUROARD_FEATURE_SOCKET_DECNET struct sockaddr_dn dn; size_t objlen; #ifdef DSO_ACCEPTMODE int acceptmode; #endif #endif switch (type) { #ifdef MUROARD_FEATURE_SOCKET_UNIX case MUROARD_NETWORK_TYPE_UNIX: if ( addr == NULL ) addr = MUROARD_DEFAULT_LISTEN_ADDR_UNIX; if ( (fh = socket(AF_UNIX, SOCK_STREAM, 0)) == MUROARD_HANDLE_INVALID ) return -1; un.sun_family = PF_UNIX; strncpy(un.sun_path, addr, sizeof(un.sun_path) - 1); #ifdef MUROARD_DEFAULT_LISTEN_CHMOD defmask = umask(0000); if ( fchmod(fh, MUROARD_DEFAULT_LISTEN_CHMOD) == -1 ) { muroard_network_close(fh); return -1; } #endif if ( bind(fh, (struct sockaddr *)&un, sizeof(struct sockaddr_un)) == -1 ) { if ( muroard_network_test_unix(addr) != 0 ) { muroard_network_close(fh); return -1; } if ( unlink(addr) == -1 ) { muroard_network_close(fh); return -1; } if ( bind(fh, (struct sockaddr *)&un, sizeof(struct sockaddr_un)) == -1 ) { muroard_network_close(fh); return -1; } } #ifdef MUROARD_DEFAULT_LISTEN_CHMOD umask(defmask); #endif break; #endif #ifdef MUROARD_FEATURE_SOCKET_INET case MUROARD_NETWORK_TYPE_INET: if ( addr == NULL ) addr = MUROARD_DEFAULT_LISTEN_ADDR_INET; if ( (he = gethostbyname(addr)) == NULL ) { return -1; } if ( (fh = socket(AF_INET, SOCK_STREAM, 0)) == MUROARD_HANDLE_INVALID ) return -1; memcpy((struct in_addr *)&in.sin_addr, he->h_addr, sizeof(struct in_addr)); in.sin_family = AF_INET; in.sin_port = htons(port); if ( bind(fh, (const struct sockaddr *)&in, sizeof(in)) == -1 ) { muroard_network_close(fh); return -1; } break; #endif #ifdef MUROARD_FEATURE_SOCKET_DECNET case MUROARD_NETWORK_TYPE_DECNET: if ( addr == NULL ) addr = MUROARD_DEFAULT_LISTEN_ADDR_DECNET; // we only support empty node addresses here (bind globaly). if ( addr[0] != ':' || addr[1] != ':' ) return -1; addr += 2; if ( (fh = socket(AF_DECnet, SOCK_SEQPACKET, DNPROTO_NSP)) == MUROARD_HANDLE_INVALID ) return -1; #ifdef DSO_ACCEPTMODE acceptmode = ACC_DEFER; setsockopt(fh, DNPROTO_NSP, DSO_ACCEPTMODE, &acceptmode, sizeof(acceptmode)); #endif muroard_memzero(&dn, sizeof(dn)); dn.sdn_family = AF_DECnet; dn.sdn_flags = 0; dn.sdn_objnum = 0; objlen = strlen(addr); #if MUROAR_CODEC_PCM_S_LE == MUROAR_CODEC_PCM_S dn.sdn_objnamel = objlen; #elif MUROAR_CODEC_PCM_S_BE == MUROAR_CODEC_PCM_S if ( sizeof(unsigned short) == 2 ) { dn.sdn_objnamel = ((objlen & 0xFF00) >> 8) | ((objlen & 0x00FF) << 8); } else { return -1; } #else #error Unsupported Endianess. #endif strcpy((char *)dn.sdn_objname, addr); bind(fh, (struct sockaddr *)&dn, sizeof(dn)); break; #endif default: return -1; break; } if ( listen(fh, 8) == -1 ) { muroard_network_close(fh); } muroard_state_member(listen_socket) = fh; #ifdef MUROARD_FEATURE_SOCKET_LISTEN_SOCKTYPE muroard_state_member(listen_type) = type; #endif return 0; } #endif #ifndef __WIN32 int muroard_network_nonblock(muroard_handle_t fh, int reset) { int flags; if ( (flags = fcntl(fh, F_GETFL, 0)) == -1 ) return -1; flags |= O_NONBLOCK; if (reset) flags -= O_NONBLOCK; return fcntl(fh, F_SETFL, flags); } #endif int muroard_network_check(enum muroard_blocking blocking) { struct timeval tv; fd_set rfds; void * data; int ret; muroard_handle_t fh; int i; int max_fh = -1; switch (blocking) { case MUROARD_BLOCKING_NONE: tv.tv_sec = 0; tv.tv_usec = 1; break; case MUROARD_BLOCKING_LONG: tv.tv_sec = 1024; tv.tv_usec = 0; break; } FD_ZERO(&rfds); #ifdef MUROARD_FEATURE_SOCKET_LISTEN if ( muroard_state_member(listen_socket) != MUROARD_HANDLE_INVALID ) { FD_SET(muroard_state_member(listen_socket), &rfds); max_fh = muroard_state_member(listen_socket); } #endif for (i = 0; i < MUROARD_MAX_STREAMS; i++) { if ( muroard_stream_get_datadir(i) == STREAM_DATADIR_IN ) { if ( (fh = muroard_stream_get_sock(i)) != MUROARD_HANDLE_INVALID ) { FD_SET(fh, &rfds); if ( fh > max_fh ) max_fh = fh; } } } for (i = 0; i < MUROARD_MAX_CLIENTS; i++) { if ( (fh = client_get_sock(i)) != MUROARD_HANDLE_INVALID ) { FD_SET(fh, &rfds); if ( fh > max_fh ) max_fh = fh; } } if ( max_fh == -1 ) { // all IOs are gone, terminate the daemon muroard_state_member(alive) = 0; return 0; } ret = select(max_fh + 1, &rfds, NULL, NULL, &tv); if ( ret == -1 ) return -1; if ( ret == 0 ) { for (i = 0; i < MUROARD_MAX_STREAMS; i++) { if ( muroard_stream_get_datadir(i) == STREAM_DATADIR_IN ) { if ( (data = muroard_stream_get_iobuf(i)) != NULL ) { muroard_memzero(data, muroard_state_member(abuffer_size)); } } } return 0; } #ifdef MUROARD_FEATURE_SOCKET_LISTEN if ( muroard_state_member(listen_socket) != MUROARD_HANDLE_INVALID ) { if ( FD_ISSET(muroard_state_member(listen_socket), &rfds) ) { fh = accept(muroard_state_member(listen_socket), NULL, NULL); #ifdef MUROARD_FEATURE_SOCKET_DECNET if ( muroard_state_member(listen_type) == MUROARD_NETWORK_TYPE_DECNET ) dnet_accept(fh, 0, NULL, 0); #endif muroard_client_new(fh); } } #endif for (i = 0; i < MUROARD_MAX_STREAMS; i++) { if ( muroard_stream_get_datadir(i) == STREAM_DATADIR_IN ) { if ( (fh = muroard_stream_get_sock(i)) != MUROARD_HANDLE_INVALID ) { if ( FD_ISSET(fh, &rfds) ) { muroard_stream_read(i); } else { if ( (data = muroard_stream_get_iobuf(i)) != NULL ) muroard_memzero(data, muroard_state_member(abuffer_size)); } } } } for (i = 0; i < MUROARD_MAX_CLIENTS; i++) { if ( (fh = client_get_sock(i)) != MUROARD_HANDLE_INVALID ) { if ( FD_ISSET(fh, &rfds) ) { muroard_client_handle(i); } } } return 0; } #ifdef MUROARD_FEATURE_CMD_PASSFH #define _SCMR_CONTROLLEN (sizeof(struct cmsghdr) + sizeof(int)) muroard_handle_t muroard_network_recvfh(muroard_handle_t fh) { struct iovec iov[1]; struct msghdr msg; char cmptr_buf[_SCMR_CONTROLLEN]; struct cmsghdr * cmptr = (struct cmsghdr *) cmptr_buf; char localmes[1]; iov[0].iov_base = localmes; iov[0].iov_len = 1; msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = (caddr_t) cmptr; msg.msg_controllen = _SCMR_CONTROLLEN; if ( recvmsg(fh, &msg, 0) == -1 ) { #ifndef __WIN32 if ( errno == EAGAIN ) { sched_yield(); if ( recvmsg(fh, &msg, 0) == -1 ) return MUROARD_HANDLE_INVALID; } else { return MUROARD_HANDLE_INVALID; } #else return MUROARD_HANDLE_INVALID; #endif } if ( msg.msg_controllen != _SCMR_CONTROLLEN ) return MUROARD_HANDLE_INVALID; return *(int *)CMSG_DATA(cmptr); } #endif //ll muroard-0.1.14/network.h0000644000175000017500000000374212126652355013247 0ustar phiphi//network.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _MUROARD_NETWORK_H_ #define _MUROARD_NETWORK_H_ #define MUROARD_NETWORK_TYPE_UNIX 1 #define MUROARD_NETWORK_TYPE_INET 2 #define MUROARD_NETWORK_TYPE_DECNET 3 int muroard_network_init(void); int muroard_network_free(void); int muroard_network_prefree(void); int muroard_network_listen(int type, const char * addr, int port); int muroard_network_check(enum muroard_blocking blocking); #ifdef __WIN32 #define muroard_network_read(fh,buf,len) recv((fh), (char*)(buf), (len), 0) #define muroard_network_write(fh,buf,len) send((fh), (const char*)(buf), (len), 0) #define muroard_network_close(fh) closesocket((fh)) #define muroard_network_nonblock(fh,reset) (0) #else #define muroard_network_read(fh,buf,len) read((fh), (buf), (len)) #define muroard_network_write(fh,buf,len) write((fh), (buf), (len)) #define muroard_network_close(fh) close((fh)) int muroard_network_nonblock(muroard_handle_t fh, int reset); #endif #ifdef MUROARD_FEATURE_CMD_PASSFH muroard_handle_t muroard_network_recvfh(muroard_handle_t fh); #endif #endif //ll muroard-0.1.14/para.c0000644000175000017500000000435412126652355012474 0ustar phiphi//para.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ /* * This C code file contains static initialisation for all global options. * NOTE: it must be ensured this is allways sync with para.h! */ #include "muroard.h" void muroard_para_init(struct muroard_state * state) { memset(state, 0, sizeof(*state)); /*********************************************************/ /* audio config */ /*********************************************************/ state->sa_rate = MUROARD_DEFAULT_RATE; state->sa_channels = MUROARD_DEFAULT_CHANNELS; /*********************************************************/ /* mixer config */ /*********************************************************/ state->abuffer_size = 0; /* we will calc this at runtime */ /*********************************************************/ /* network config */ /*********************************************************/ #ifdef MUROARD_FEATURE_SOCKET_LISTEN state->listen_socket = MUROARD_HANDLE_INVALID; /* listen socket to use */ #endif #ifdef MUROARD_FEATURE_SOCKET_LISTEN_SOCKTYPE state->listen_type = -1; #endif #ifdef MUROARD_FEATURE_OPTIMIZE state->waveform_last_scount = -1; #endif state->driver_old_blocking = MUROARD_BLOCKING_LONG; state->driver_fh = -1; } //ll muroard-0.1.14/para.h0000644000175000017500000000216412126652356012477 0ustar phiphi//para.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ /* * This header contains the declarations for all run-time options/parameters */ #ifndef _MUROARD_PARA_H_ #define _MUROARD_PARA_H_ void muroard_para_init(struct muroard_state * state); #endif //ll muroard-0.1.14/proto.c0000644000175000017500000000643012126652356012712 0ustar phiphi//proto.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #if !defined(__WIN32) && !defined(HAVE_LIB_YIFFC) #include #endif int muroard_proto_recv(muroard_handle_t sock, struct muroard_message * mes) { unsigned char header[10]; #ifndef __WIN32 ssize_t ret = -1; #endif if ( muroard_network_read(sock, header, 10) != 10 ) return -1; if ( header[0] != 0 ) /* version */ return -1; mes->cmd = header[1]; mes->stream = ((uint16_t)header[2] << 8) + (uint16_t)header[3]; mes->pos = ((uint32_t)header[4] << 24) + ((uint32_t)header[5] << 16) + ((uint32_t)header[6] << 8) + (uint32_t)header[7]; mes->datalen = ((uint16_t)header[8] << 8) + (uint16_t)header[9]; // fprintf(stderr, "MSG IN : ver=0, cmd=%i, stream=%i, pos=%u, datalen=%u\n", mes->cmd, mes->stream, mes->pos, mes->datalen); if ( mes->datalen == 0 ) return 0; if ( mes->datalen > MUROARD_MAX_MSGSIZE ) return -1; #ifndef __WIN32 ret = muroard_network_read(sock, mes->data, mes->datalen); if ( ret == -1 && errno == EAGAIN ) { sched_yield(); ret = muroard_network_read(sock, mes->data, mes->datalen); if ( ret == -1 && errno == EAGAIN ) { usleep(muroard_state_member(abuffer_size)*25000LLU/(long long unsigned)(muroard_state_member(sa_rate)*muroard_state_member(sa_channels)*2)); sched_yield(); ret = muroard_network_read(sock, mes->data, mes->datalen); } } if ( ret != (ssize_t)mes->datalen ) return -1; #else if ( muroard_network_read(sock, mes->data, mes->datalen) != (ssize_t)mes->datalen ) return -1; #endif return 0; } int muroard_proto_send(muroard_handle_t sock, struct muroard_message * mes) { unsigned char header[10]; // fprintf(stderr, "MSG OUT: ver=0, cmd=%i, stream=%i, pos=%u, datalen=%u\n", mes->cmd, mes->stream, mes->pos, mes->datalen); header[0] = 0; // version; header[1] = mes->cmd; header[2] = (mes->stream & 0xFF00) >> 8; header[3] = (mes->stream & 0x00FF); header[4] = (mes->pos & 0xFF000000) >> 24; header[5] = (mes->pos & 0x00FF0000) >> 16; header[6] = (mes->pos & 0x0000FF00) >> 8; header[7] = (mes->pos & 0x000000FF); header[8] = (mes->datalen & 0xFF00) >> 8; header[9] = (mes->datalen & 0x00FF); if ( muroard_network_write(sock, header, 10) != 10 ) return -1; if ( mes->datalen == 0 ) return 0; if ( muroard_network_write(sock, mes->data, mes->datalen) != (ssize_t)mes->datalen ) return -1; return 0; } //ll muroard-0.1.14/proto.h0000644000175000017500000000240112126652356012711 0ustar phiphi//proto.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _MUROARD_PROTO_H_ #define _MUROARD_PROTO_H_ struct muroard_message { int cmd; uint16_t stream; uint32_t pos; size_t datalen; char data[MUROARD_MAX_MSGSIZE]; }; int muroard_proto_recv(muroard_handle_t sock, struct muroard_message * mes); int muroard_proto_send(muroard_handle_t sock, struct muroard_message * mes); #endif //ll muroard-0.1.14/state.h0000644000175000017500000000426112126652356012674 0ustar phiphi//state.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2012-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _MUROARD_STATE_H_ #define _MUROARD_STATE_H_ struct muroard_state { int alive; int standby; /*********************************************************/ /* audio config */ /*********************************************************/ int sa_rate; int sa_channels; /*********************************************************/ /* mixer config */ /*********************************************************/ size_t abuffer_size; /*********************************************************/ /* network config */ /*********************************************************/ #ifdef MUROARD_FEATURE_SOCKET_LISTEN muroard_handle_t listen_socket; #endif #ifdef MUROARD_FEATURE_SOCKET_LISTEN_SOCKTYPE int listen_type; #endif // ... int16_t * waveform_mixercore; struct muroard_client client[MUROARD_MAX_CLIENTS]; struct muroard_stream stream[MUROARD_MAX_STREAMS]; #ifdef MUROARD_FEATURE_OPTIMIZE ssize_t waveform_last_scount; #endif size_t waveform_offset; enum muroard_blocking driver_old_blocking; int driver_fh; void * driver_vp; }; extern struct muroard_state * muroard_g_state; #define muroard_state_member(m) (muroard_g_state->m) #endif //ll muroard-0.1.14/streams.c0000644000175000017500000004005112210357674013221 0ustar phiphi//streams.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" int muroard_stream_init(void) { muroard_memzero(muroard_state_member(stream), sizeof(muroard_state_member(stream))); // unused = 0 return 0; } int muroard_stream_free(void) { int i; int ret = 0; for (i = 0; i < MUROARD_MAX_STREAMS; i++) { if ( muroard_state_member(stream)[i].state != STREAM_STATE_UNUSED ) { if ( muroard_stream_delete(i) == -1 ) ret = -1; } } return ret; } int muroard_stream_new(int client, int dir, struct muroard_audio_info * info) { #if defined(MUROARD_FEATURE_UPSCALE_INPUT) || defined(MUROARD_FEATURE_DOWNSCALE_OUTPUT) int need_scale = 0; #define _NEED_SCALE need_scale #endif #if defined(MUROARD_FEATURE_UPMIX_INPUT) || defined(MUROARD_FEATURE_DOWNMIX_OUTPUT) int need_mix = 0; #define _NEED_MIX need_mix #endif #ifdef MUROARD_FEATURE_CODECFILTER int need_cf = 0; #define _NEED_CF need_cf #endif register struct muroard_stream * stream; int i; //fprintf(stderr, "%s:%i: dir=%i\n", __FILE__, __LINE__, dir); #ifdef _NEED_SCALE if ( info->bits == 8 ) { need_scale = 1; switch (info->codec) { case MUROAR_CODEC_PCM_S_LE: case MUROAR_CODEC_PCM_S_BE: case MUROAR_CODEC_PCM_S_PDP: info->codec = MUROAR_CODEC_PCM_S; break; #ifdef MUROARD_FEATURE_UNSIGNED_8BIT case MUROAR_CODEC_PCM_U_LE: case MUROAR_CODEC_PCM_U_BE: case MUROAR_CODEC_PCM_U_PDP: info->codec = MUROAR_CODEC_PCM_U; break; #endif } } else if ( info->bits != 16 ) { return -1; } #else if ( info->bits != 16 ) return -1; #endif #ifdef _NEED_MIX if ( info->channels == 1 ) { need_mix = 1; } else if ( info->channels != muroard_state_member(sa_channels) ) { return -1; } #else if ( info->channels != muroard_state_member(sa_channels) ) return -1; #endif #ifdef _NEED_CF switch (info->codec) { #ifdef MUROARD_FEATURE_CODECFILTER_AU case MUROAR_CODEC_AU: #endif #ifdef MUROARD_FEATURE_CODECFILTER_RIFF_WAVE case MUROAR_CODEC_RIFF_WAVE: #endif #ifdef MUROARD_FEATURE_CODECFILTER_OGG_VORBIS case MUROAR_CODEC_OGG_VORBIS: #endif _NEED_CF = info->codec; info->codec = MUROAR_CODEC_PCM; break; } #endif #ifdef MUROARD_FEATURE_BYTE_SWAP if ( info->bits > 16 && info->codec != MUROAR_CODEC_PCM ) return -1; switch (info->codec) { case MUROAR_CODEC_PCM_S_BE: case MUROAR_CODEC_PCM_S_LE: case MUROAR_CODEC_PCM_S_PDP: #ifdef MUROARD_FEATURE_UNSIGNED_8BIT case MUROAR_CODEC_PCM_U_LE: case MUROAR_CODEC_PCM_U_BE: case MUROAR_CODEC_PCM_U_PDP: #endif break; default: return -1; break; } #else if ( info->codec != MUROAR_CODEC_PCM ) return -1; #endif if ( client_get_stream(client) != -1 ) return -1; for (i = 0; i < MUROARD_MAX_STREAMS; i++) { if ( muroard_state_member(stream)[i].state == STREAM_STATE_UNUSED ) { stream = &(muroard_state_member(stream)[i]); muroard_memzero(stream, sizeof(*stream)); stream->state = STREAM_STATE_UNUSED; stream->iobuf = NULL; #ifdef _NEED_CF stream->cf_read = NULL; stream->cf_close = NULL; switch (_NEED_CF) { case 0: break; // no need to do anything. #ifdef MUROARD_FEATURE_CODECFILTER_AU case MUROAR_CODEC_AU: stream->cf_read = muroard_cf_au_read; break; #endif #ifdef MUROARD_FEATURE_CODECFILTER_RIFF_WAVE case MUROAR_CODEC_RIFF_WAVE: stream->cf_read = muroard_cf_riff_wave_read; break; #endif #ifdef MUROARD_FEATURE_CODECFILTER_OGG_VORBIS case MUROAR_CODEC_OGG_VORBIS: stream->cf_read = muroard_cf_ogg_vorbis_read; stream->cf_close = muroard_cf_ogg_vorbis_close; break; #endif default: return -1; } if ( _NEED_CF ) { #ifdef _NEED_SCALE _NEED_SCALE = 1; info->bits = 8; #endif #ifdef _NEED_MIX _NEED_MIX = 1; info->channels = 1; #endif } #endif switch (dir) { case MUROAR_PLAY_WAVE: stream->datadir = STREAM_DATADIR_IN; if ( (stream->iobuf = muroard_malloc(muroard_state_member(abuffer_size))) == NULL ) { return -1; } muroard_memzero(stream->iobuf, muroard_state_member(abuffer_size)); // clean memory to avoid noise break; #ifdef MUROARD_FEATURE_MONITOR case MUROAR_MONITOR_WAVE: stream->datadir = STREAM_DATADIR_OUT; // no neet to set up anything break; #endif default: return -1; break; } #ifdef _NEED_SCALE if ( _NEED_SCALE ) { switch (stream->datadir) { #ifdef MUROARD_FEATURE_UPSCALE_INPUT case STREAM_DATADIR_IN: break; #endif #ifdef MUROARD_FEATURE_DOWNSCALE_OUTPUT case STREAM_DATADIR_OUT: break; #endif default: if ( stream->iobuf != NULL ) muroard_free(stream->iobuf); return -1; } } #endif #ifdef _NEED_MIX if ( _NEED_MIX ) { switch (stream->datadir) { #ifdef MUROARD_FEATURE_UPMIX_INPUT case STREAM_DATADIR_IN: break; #endif #ifdef MUROARD_FEATURE_DOWNMIX_OUTPUT case STREAM_DATADIR_OUT: break; #endif default: if ( stream->iobuf != NULL ) muroard_free(stream->iobuf); return -1; } } #endif //fprintf(stderr, "%s:%i: dir=%i\n", __FILE__, __LINE__, dir); stream->sock = MUROARD_HANDLE_INVALID; stream->client = client; stream->dir = dir; // stream volume: #ifdef MUROARD_FEATURE_VOLUME_CONTROL stream->volume = 65535; #endif memcpy(&(stream->info), info, sizeof(stream->info)); if ( client_set_stream(client, i) == -1 ) { if ( stream->iobuf != NULL ) muroard_free(stream->iobuf); return -1; } stream->state = STREAM_STATE_NEW; return i; } } return -1; } int muroard_stream_delete(int id) { register struct muroard_stream * stream; int state; int ret = 0; if ( id >= MUROARD_MAX_STREAMS || id < 0 ) return -1; stream = &(muroard_state_member(stream)[id]); state = stream->state; if ( state == STREAM_STATE_UNUSED || state == STREAM_STATE_CLOSING ) return 0; stream->state = STREAM_STATE_CLOSING; #ifdef MUROARD_FEATURE_CODECFILTER if ( stream->cf_close != NULL ) stream->cf_close(id, stream); #endif if ( state == STREAM_STATE_EXECED ) { if ( stream->client != -1 ) if ( muroard_client_delete(stream->client) == -1 ) ret = -1; } else { muroard_state_member(client)[stream->client].stream = -1; } if ( stream->sock != MUROARD_HANDLE_INVALID ) { muroard_network_close(stream->sock); } if ( stream->iobuf != NULL ) muroard_free(stream->iobuf); stream->state = STREAM_STATE_UNUSED; return ret; } int muroard_stream_exec(int id) { muroard_handle_t sock; if ( (sock = muroard_client_exec(muroard_state_member(stream)[id].client)) == MUROARD_HANDLE_INVALID ) return -1; muroard_state_member(stream)[id].sock = sock; muroard_state_member(stream)[id].state = STREAM_STATE_EXECED; return 0; } #ifdef MUROARD_FEATURE_REREADWRITE ssize_t muroard_stream_network_read(int id, void * buf, size_t len) { muroard_handle_t fh = muroard_stream_get_sock(id); ssize_t done = 0; ssize_t ret; if ( fh == MUROARD_HANDLE_INVALID || buf == NULL ) return -1; while (len) { if ( (ret = muroard_network_read(fh, buf, len)) < 1 ) return done; done += ret; buf = (char *)buf + ret; len -= ret; } return done; } ssize_t muroard_stream_network_write(int id, const void * buf, size_t len) { muroard_handle_t fh = muroard_stream_get_sock(id); ssize_t done = 0; ssize_t ret; if ( fh == MUROARD_HANDLE_INVALID || buf == NULL ) return -1; while (len) { if ( (ret = muroard_network_write(fh, buf, len)) < 1 ) return done; done += ret; buf = (const char *)buf + ret; len -= ret; } return done; } #endif int muroard_stream_read(int id) { register struct muroard_stream * stream = &(muroard_state_member(stream)[id]); ssize_t len; size_t readsize = muroard_state_member(abuffer_size); #ifdef MUROARD_FEATURE_UPSCALE_INPUT if ( stream->info.bits == 8 ) readsize /= 2; #endif #ifdef MUROARD_FEATURE_UPMIX_INPUT if ( stream->info.channels == 1 && muroard_state_member(sa_channels) != 1 ) readsize /= muroard_state_member(sa_channels); #endif #ifdef MUROARD_FEATURE_CODECFILTER if ( stream->cf_read != NULL ) { len = stream->cf_read(id, stream, stream->iobuf, readsize); } else { #endif len = muroard_stream_network_read(id, stream->iobuf, readsize); #ifdef MUROARD_FEATURE_CODECFILTER } #endif if ( len == (ssize_t) readsize ) { // no op here. } else if ( len == 0 ) { return muroard_stream_delete(id); } else if ( len == -1 ) { muroard_stream_delete(id); return -1; } else { muroard_memzero(((void*)stream->iobuf)+len, muroard_state_member(abuffer_size) - len); } #ifdef MUROARD_FEATURE_POSITION stream->pos += len / (stream->info.bits / 8); #endif #ifdef MUROARD_FEATURE_UPSCALE_INPUT if ( stream->info.bits == 8 ) { muroard_dsp_upscale(stream->iobuf, len); len *= 2; } #endif #ifdef MUROARD_FEATURE_BYTE_SWAP if ( muroard_dsp_need_swap_s(stream->info.codec) ) muroard_dsp_swap16(stream->iobuf, len/2); #endif #ifdef MUROARD_FEATURE_UPMIX_INPUT if ( stream->info.channels == 1 && muroard_state_member(sa_channels) != 1 ) muroard_dsp_upmix(stream->iobuf, len/2); #endif return 0; } #ifdef MUROARD_FEATURE_MONITOR int muroard_stream_write(int id, int16_t * buf) { register struct muroard_stream * stream = &(muroard_state_member(stream)[id]); ssize_t len; size_t writesize = muroard_state_member(abuffer_size); #if defined(MUROARD_FEATURE_DOWNSCALE_OUTPUT) || defined(MUROARD_FEATURE_DOWNMIX_OUTPUT) || defined(MUROARD_FEATURE_BYTE_SWAP) size_t need_buf = 0; #define _NEED_BUF need_buf #endif if ( muroard_stream_get_sock(id) == MUROARD_HANDLE_INVALID ) return -1; #ifdef MUROARD_FEATURE_DOWNSCALE_OUTPUT if ( stream->info.bits == 8 ) { writesize /= 2; need_buf = 1; } #endif #ifdef MUROARD_FEATURE_DOWNMIX_OUTPUT if ( stream->info.channels == 1 && muroard_state_member(sa_channels) != 1 ) { writesize /= muroard_state_member(sa_channels); need_buf = 1; } #endif #ifdef MUROARD_FEATURE_BYTE_SWAP if ( muroard_dsp_need_swap_s(stream->info.codec) ) need_buf = 1; #endif #ifdef _NEED_BUF if ( _NEED_BUF ) { if ( stream->iobuf == NULL ) { muroard_state_member(stream)[id].iobuf = muroard_malloc(muroard_state_member(abuffer_size)); if ( stream->iobuf == NULL ) return -1; } memcpy(stream->iobuf, buf, muroard_state_member(abuffer_size)); buf = muroard_state_member(stream)[id].iobuf; #ifdef MUROARD_FEATURE_DOWNMIX_OUTPUT if ( stream->info.channels == 1 && muroard_state_member(sa_channels) != 1 ) { muroard_dsp_downmix(buf, muroard_state_member(abuffer_size)/(2*muroard_state_member(sa_channels))); } #endif #ifdef MUROARD_FEATURE_BYTE_SWAP if ( muroard_dsp_need_swap_s(stream->info.codec) ) muroard_dsp_swap16(buf, (muroard_state_member(abuffer_size)*stream->info.channels)/(2*muroard_state_member(sa_channels))); #endif #ifdef MUROARD_FEATURE_DOWNSCALE_OUTPUT if ( stream->info.bits == 8 ) { muroard_dsp_downscale(buf, writesize); } #endif } #endif len = muroard_stream_network_write(id, buf, writesize); if ( len < 1 ) { muroard_stream_delete(id); return -1; } #ifdef MUROARD_FEATURE_POSITION stream->pos += len / (stream->info.bits / 8); #endif return 0; } #endif #ifdef MUROARD_FEATURE_CMD_ATTACH int muroard_stream_move_client(int id, int client) { int old_client; if ( muroard_state_member(stream)[id].state == STREAM_STATE_UNUSED ) return -1; // check if the target client will accept the stream. if ( client_set_stream_check(client, id) == -1 ) return -1; old_client = muroard_state_member(stream)[id].client; // if we are execed we need to close the client, too. // we use a little trick: // we tell the stream it is closing and close the client. // after the client has been closed we reset the stream to NEW. if ( muroard_state_member(stream)[id].state == STREAM_STATE_EXECED ) { muroard_state_member(stream)[id].state = STREAM_STATE_CLOSING; if ( muroard_client_delete(old_client) == -1 ) { muroard_state_member(stream)[id].state = STREAM_STATE_NEW; muroard_stream_delete(id); return -1; } old_client = -1; muroard_state_member(stream)[id].state = STREAM_STATE_NEW; } if ( old_client != -1 ) muroard_state_member(client)[old_client].stream = -1; // now we have a free client we need to attach to the client like muroard_stream_new() does: #ifdef MUROARD_FEATURE_INTERNAL_CLIENT if ( muroard_state_member(client)[client].state == CLIENT_STATE_INTERNAL ) { muroard_state_member(stream)[id].client = -1; return 0; } #endif muroard_state_member(stream)[id].client = client; client_set_stream(client, id); // errors are checked above. return 0; } #endif #ifdef MUROARD_FEATURE_CODECFILTER int muroard_stream_cksupport(struct muroard_audio_info * info, int datadir) { if ( info->bits == 8 ) { switch (info->codec) { case MUROAR_CODEC_PCM_S_LE: case MUROAR_CODEC_PCM_S_BE: case MUROAR_CODEC_PCM_S_PDP: #ifdef MUROARD_FEATURE_UNSIGNED_8BIT case MUROAR_CODEC_PCM_U_LE: case MUROAR_CODEC_PCM_U_BE: case MUROAR_CODEC_PCM_U_PDP: #endif break; default: return 0; break; } } else if ( info->bits == 16 ) { switch (info->codec) { #if MUROAR_CODEC_PCM_S_LE == MUROAR_CODEC_PCM_S #ifdef MUROARD_FEATURE_BYTE_SWAP case MUROAR_CODEC_PCM_S_BE: #endif case MUROAR_CODEC_PCM_S_LE: case MUROAR_CODEC_PCM_S_PDP: break; #else #ifdef MUROARD_FEATURE_BYTE_SWAP case MUROAR_CODEC_PCM_S_LE: case MUROAR_CODEC_PCM_S_PDP: #endif case MUROAR_CODEC_PCM_S_BE: break; #endif #ifdef MUROARD_FEATURE_UNSIGNED_16BIT #if MUROAR_CODEC_PCM_S_LE == MUROAR_CODEC_PCM_S #ifdef MUROARD_FEATURE_BYTE_SWAP case MUROAR_CODEC_PCM_U_BE: #endif case MUROAR_CODEC_PCM_U_LE: case MUROAR_CODEC_PCM_U_PDP: break; #else #ifdef MUROARD_FEATURE_BYTE_SWAP case MUROAR_CODEC_PCM_U_LE: case MUROAR_CODEC_PCM_U_PDP: #endif case MUROAR_CODEC_PCM_U_BE: break; #endif #endif default: return 0; break; } } else { return 0; } if ( info->bits != 16 ) { if ( info->bits == 8 ) { if ( datadir == STREAM_DATADIR_IN ) { #ifndef MUROARD_FEATURE_UPSCALE_INPUT return 0; #endif } else if ( datadir == STREAM_DATADIR_OUT ) { #ifndef MUROARD_FEATURE_DOWNSCALE_OUTPUT return 0; #endif } else { return 0; } } } if ( info->channels != muroard_state_member(sa_channels) ) { if ( info->channels == 1 ) { if ( datadir == STREAM_DATADIR_IN ) { #ifndef MUROARD_FEATURE_UPMIX_INPUT return 0; #endif } else if ( datadir == STREAM_DATADIR_OUT ) { #ifndef MUROARD_FEATURE_DOWNMIX_OUTPUT return 0; #endif } else { return 0; } } else { return 0; } } return 1; } #endif #ifdef MUROARD_FEATURE_SOURCES int muroard_stream_new_source(const char * filename, int dir, struct muroard_audio_info * info) { int stream; #ifndef __WIN32 int flags = O_NONBLOCK; #else int flags = 0; #endif int fh; switch (dir) { case STREAM_DATADIR_IN: flags |= O_RDONLY; break; case STREAM_DATADIR_OUT: #ifndef O_LARGEFILE #define O_LARGEFILE 0 #endif flags |= O_WRONLY|O_CREAT|O_LARGEFILE|O_APPEND; break; default: return -1; break; } fh = open(filename, flags, 0666); if ( fh == -1 ) return -1; stream = muroard_stream_new(0, dir, info); if ( stream == -1 ) { close(fh); return -1; } if ( muroard_stream_move_client(stream, 0) == -1 ) { muroard_stream_delete(stream); return -1; } if ( muroard_stream_set_sock(stream, fh) == -1 ) { muroard_stream_delete(stream); return -1; } return stream; } #endif //ll muroard-0.1.14/streams.h0000644000175000017500000001057512126652356013237 0ustar phiphi//streams.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _MUROARD_STREAMS_H_ #define _MUROARD_STREAMS_H_ #define STREAM_STATE_UNUSED 0 #define STREAM_STATE_NEW 1 #define STREAM_STATE_OLD 2 #define STREAM_STATE_EXECED 3 #define STREAM_STATE_CLOSING 4 #define STREAM_DATADIR_IN 1 #define STREAM_DATADIR_OUT 2 struct muroard_audio_info { int channels; int bits; int codec; }; struct muroard_stream { // general data and IO: muroard_handle_t sock; int state; int client; int datadir; // Stream level data: int dir; // audio level data: struct muroard_audio_info info; // raw data: int16_t * iobuf; // stream volume: #ifdef MUROARD_FEATURE_VOLUME_CONTROL uint16_t volume; #endif // stream position: #ifdef MUROARD_FEATURE_POSITION uint32_t pos; #endif #ifdef MUROARD_FEATURE_CODECFILTER ssize_t (*cf_read)(int id, struct muroard_stream * stream, void * buf, size_t len); int (*cf_close)(int id, struct muroard_stream * stream); union { void * vp; // we need a dummy to comply the C standard. So we use something some codec filter may find useful. #ifdef MUROARD_FEATURE_CODECFILTER_AU struct { ssize_t dataoffset, headeroffset; } au; #endif #ifdef MUROARD_FEATURE_CODECFILTER_OGG_VORBIS struct { int opened; int stream_id; OggVorbis_File vf; } ogg_vorbis; #endif } cf_data; #endif }; int muroard_stream_init(void); int muroard_stream_free(void); int muroard_stream_new(int client, int dir, struct muroard_audio_info * info); int muroard_stream_delete(int id); int muroard_stream_exec(int id); int muroard_stream_read(int id); #ifdef MUROARD_FEATURE_MONITOR int muroard_stream_write(int id, int16_t * buf); #endif #ifdef MUROARD_FEATURE_CMD_ATTACH int muroard_stream_move_client(int id, int client); #endif #ifdef MUROARD_FEATURE_CODECFILTER int muroard_stream_cksupport(struct muroard_audio_info * info, int datadir); #endif #ifdef MUROARD_FEATURE_SOURCES int muroard_stream_new_source(const char * filename, int dir, struct muroard_audio_info * info); #endif #define muroard_stream_exist(id) (((uint16_t)(id)) == (uint16_t)-1 || muroard_state_member(stream)[(id)].state == STREAM_STATE_UNUSED ? 0 : 1) #define muroard_stream_get_sock(id) (muroard_state_member(stream)[(id)].state == STREAM_STATE_UNUSED ? MUROARD_HANDLE_INVALID : muroard_state_member(stream)[(id)].sock) #define muroard_stream_set_sock(id, s) (muroard_state_member(stream)[(id)].state == STREAM_STATE_UNUSED || muroard_state_member(stream)[(id)].sock != MUROARD_HANDLE_INVALID ? \ -1 : (muroard_state_member(stream)[(id)].sock = (s)) && 0) #define muroard_stream_get_iobuf(id) (muroard_state_member(stream)[(id)].state == STREAM_STATE_UNUSED ? NULL : muroard_state_member(stream)[(id)].iobuf) #define muroard_stream_get_datadir(id) (muroard_state_member(stream)[(id)].state == STREAM_STATE_UNUSED ? -1 : muroard_state_member(stream)[(id)].datadir) #ifdef MUROARD_FEATURE_VOLUME_CONTROL #define muroard_stream_get_volume(id) (muroard_state_member(stream)[(id)].state == STREAM_STATE_UNUSED ? -1 : muroard_state_member(stream)[(id)].volume) #endif #ifdef MUROARD_FEATURE_REREADWRITE ssize_t muroard_stream_network_read(int id, void * buf, size_t len); ssize_t muroard_stream_network_write(int id, const void * buf, size_t len); #else #define muroard_stream_network_read(id,buf,len) muroard_network_read(muroard_stream_get_sock((id)), (buf), (len)) #define muroard_stream_network_write(id,buf,len) muroard_network_write(muroard_stream_get_sock((id)), (buf), (len)) #endif #endif //ll muroard-0.1.14/waveform.c0000644000175000017500000001355012126652356013376 0ustar phiphi//waveform.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "muroard.h" #ifdef MUROARD_FEATURE_STANDBY #define STANDBY_ACTIVE 0x01 #define STANDBY_AUTOACTIVE 0x02 #define STANDBY_AUTO 0x20 #endif int muroard_waveform_init(void) { #ifdef MUROARD_FEATURE_STANDBY muroard_state_member(standby) = 0 #ifdef MUROARD_FEATURE_STANDBY_AUTOMODE |STANDBY_AUTO #endif #ifdef MUROARD_FEATURE_STANDBY_ACTIVE |STANDBY_ACTIVE #endif ; #endif #ifdef MUROARD_FIXED_ABUFFER_SIZE muroard_state_member(abuffer_size) = MUROARD_FIXED_ABUFFER_SIZE; #else muroard_state_member(abuffer_size) = muroard_state_member(sa_channels) * 2 * MUROARD_DEFAULT_FRAMES_PER_CYCLE; #endif if ( (muroard_state_member(waveform_mixercore) = muroard_malloc(muroard_state_member(abuffer_size))) == NULL ) return -1; return 0; } int muroard_waveform_free(void) { if ( muroard_state_member(waveform_mixercore) != NULL ) muroard_free(muroard_state_member(waveform_mixercore)); return 0; } int muroard_waveform_update(enum muroard_blocking blocking) { int16_t * out = NULL; int16_t * streams[MUROARD_MAX_STREAMS]; size_t scount = 0; int i; #ifdef MUROARD_FEATURE_VOLUME_CONTROL uint16_t volume; #endif ssize_t ret; size_t todo = muroard_state_member(abuffer_size) - muroard_state_member(waveform_offset); if ( !muroard_state_member(waveform_offset) ) { for (i = 0; i < MUROARD_MAX_STREAMS; i++) { if ( muroard_stream_get_datadir(i) == STREAM_DATADIR_IN ) { streams[scount] = muroard_stream_get_iobuf(i); if ( streams[scount] != NULL ) { #ifdef MUROARD_FEATURE_VOLUME_CONTROL #ifdef MUROARD_FEATURE_STANDBY if ( (muroard_state_member(standby) & STANDBY_ACTIVE) || (volume = muroard_stream_get_volume(i)) == 65535 ) { #else if ( (volume = muroard_stream_get_volume(i)) == 65535 ) { #endif // full volume scount++; } else { if ( volume ) { // non-muted muroard_dsp_volume(streams[scount], todo/2, muroard_stream_get_volume(i)); scount++; } } #else scount++; #endif } } } #ifdef MUROARD_FEATURE_STANDBY if ( !(muroard_state_member(standby) & STANDBY_ACTIVE) ) { #endif #ifdef MUROARD_FEATURE_OPTIMIZE if ( muroard_state_member(waveform_last_scount) == 0 && scount == 0 ) { out = muroard_state_member(waveform_mixercore); } else { #endif if ( scount == 1 ) { out = streams[0]; } else { if ( muroard_dsp_mixer(muroard_state_member(waveform_mixercore), streams, scount) == -1 ) return -1; out = muroard_state_member(waveform_mixercore); } #ifdef MUROARD_FEATURE_OPTIMIZE } muroard_state_member(waveform_last_scount) = scount; #endif #ifdef MUROARD_FEATURE_STANDBY } #endif } #ifdef MUROARD_FEATURE_STANDBY if ( scount == 0 && (muroard_state_member(standby) & STANDBY_AUTO) ) { //printf("-> STANDBY_AUTOACTIVE\n"); muroard_state_member(standby) |= STANDBY_AUTOACTIVE; } else if ( scount != 0 && (muroard_state_member(standby) & STANDBY_AUTOACTIVE) ) { //printf("<- STANDBY_AUTOACTIVE\n"); muroard_state_member(standby) -= STANDBY_AUTOACTIVE; } ret = todo; if ( (muroard_state_member(standby) & (STANDBY_ACTIVE|STANDBY_AUTOACTIVE)) == 0 ) { if ( (ret = muroard_driver_write(out+muroard_state_member(waveform_offset), todo, blocking)) == -1 ) return -1; } else if ( scount != 0 && blocking != MUROARD_BLOCKING_NONE ) { #ifndef __WIN32 usleep(todo*1000000LLU/(long long unsigned)(muroard_state_member(sa_rate)*muroard_state_member(sa_channels)*2)); #else Sleep(todo*1000LLU/(long long unsigned)(muroard_state_member(sa_rate)*muroard_state_member(sa_channels)*2)); #endif } #else if ( (ret = muroard_driver_write(out+muroard_state_member(waveform_offset), todo, blocking)) == -1 ) return -1; #endif if ( ret == -1 ) return -1; if ( ret < (ssize_t)todo ) { muroard_state_member(waveform_offset) += (ssize_t)ret; } else { muroard_state_member(waveform_offset) = 0; } #ifdef MUROARD_FEATURE_MONITOR if ( !muroard_state_member(waveform_offset) ) { for (i = 0; i < MUROARD_MAX_STREAMS; i++) { if ( muroard_stream_get_datadir(i) == STREAM_DATADIR_OUT ) { muroard_stream_write(i, out); } } } #endif #ifdef MUROARD_FEATURE_STANDBY return (muroard_state_member(standby) & (STANDBY_ACTIVE|STANDBY_AUTOACTIVE)) == 0 ? 0 : 1; #else return 0; #endif } #ifdef MUROARD_FEATURE_STANDBY int muroard_waveform_standby(int manual_mode, int auto_mode) { // printf("muroard_waveform_standby(manual_mode=%i, auto_mode=%i) = ?\n", manual_mode, auto_mode); if ( manual_mode != -1 ) { muroard_state_member(standby) |= STANDBY_ACTIVE; if ( manual_mode == 0 ) muroard_state_member(standby) -= STANDBY_ACTIVE; } if ( auto_mode != -1 ) { muroard_state_member(standby) |= STANDBY_AUTO; if ( auto_mode == 0 ) { muroard_state_member(standby) |= STANDBY_AUTOACTIVE; muroard_state_member(standby) -= STANDBY_AUTO|STANDBY_AUTOACTIVE; } } return (muroard_state_member(standby) & (STANDBY_ACTIVE|STANDBY_AUTOACTIVE)) == 0 ? 0 : 1; } #endif //ll muroard-0.1.14/waveform.h0000644000175000017500000000240512126652356013400 0ustar phiphi//waveform.h: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2013 * * This file is part of µRoarD, * a sound server daemon for using the RoarAudio protocol. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * or (at your option) any later version as published by * the Free Software Foundation. * * RoarAudio 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 software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _MUROARD_WAVEFORM_H_ #define _MUROARD_WAVEFORM_H_ int muroard_waveform_init(void); int muroard_waveform_free(void); int muroard_waveform_update(enum muroard_blocking blocking); #ifdef MUROARD_FEATURE_STANDBY int muroard_waveform_standby(int manual_mode, int auto_mode); #else #define muroard_waveform_standby (-1) #endif #endif //ll muroard-0.1.14/dist/0000755000175000017500000000000012210617627012337 5ustar phiphimuroard-0.1.14/dist/debian-like/0000755000175000017500000000000012210617627014503 5ustar phiphimuroard-0.1.14/dist/debian-like/defaults0000644000175000017500000000213611635141560016235 0ustar phiphi#µRoarD Configuration file # --- [ General Options ]--- # Start µRoarD? YES or NO: MUROARD='YES' # Additionl Options to pass to µRoarD, should normally be empty MUROARD_OPTS='' # Default location for µRoarD: # Set this to a remote address and disable local µRoarD # to run a network only setup. # ROARAUDIO_DEFAULT_SOCKET='server.local' # --- [ Network ] --- # Listening socket's address family: # UNIX - Local connections only # TCP - Connections via TCP/IP # DECnet - Connections via DECnet MUROARD_AF='UNIX' # Socket to listen on (UNIX): MUROARD_SOCKET='/tmp/roar' # Port to listen on (TCP): # MUROARD_PORT=16002 # Host/Nodename to listen on (TCP): # use a value of '0.0.0.0' to listen publicly for TCP. # MUROARD_HOST='0.0.0.0' # Object to listen on (DECnet): # MUROARD_OBJECT='roar' # --- [ Audio and Devices ] --- # Samplerate and number of channels; # MUROARD_RATE=44100 # MUROARD_CHANNELS=2 # Sound Device: # MUROARD_DEVICE='/dev/dsp' # --- [ Permitions ] --- # User and group for UNIX Sockets. # The user is allso used to run µRoarD as # MUROARD_USER='roard' # MUROARD_GROUP='audio' #ll muroard-0.1.14/dist/debian-like/muroard0000755000175000017500000001176312210333421016075 0ustar phiphi#!/bin/sh # µRoarD initscript # # Copyright (c) 2008-2011 Philipp 'ph3-der-loewe' Schafft # Copyright (c) 2007 Javier Fernandez-Sanguino # # This is free software; you may 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, # or (at your option) any later version. # # This 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 with # the Debian operating system, in /usr/share/common-licenses/GPL; if # not, write to the Free Software Foundation, Inc., 59 Temple Place, # Suite 330, Boston, MA 02111-1307 USA # ### BEGIN INIT INFO # Provides: muroard # Required-Start: $network $local_fs $remote_fs # Required-Stop: $network $local_fs $remote_fs # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: sound server for audio mixing # Description: µRoarD is a RoarAudio based server for audio mixing. # Its main purpose is to mix audio from # different clients before sending it to its output (normally a soundcard). # It is completely network transparent (UNIX sockets, TCP/IP). ### END INIT INFO #set -e . /lib/lsb/init-functions PATH=/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/bin/muroard NAME=muroard DESC="muRoarD" DAEMON_BN=`basename $DAEMON` PIDFILE=/var/run/$DAEMON_BN.pid SCRIPTNAME=/etc/init.d/$NAME USER_LIST="$DAEMON_BN roard roar nobody"; # Gracefully exit if the package has been removed. test -x $DAEMON || exit 0; # Read config file if it is present. if [ -r /etc/default/$NAME ] then . /etc/default/$NAME fi # This is no longer needed as done by start-stop-daemon. #MUROARD_OPTS="--daemon $MUROARD_OPTS" if [ "$ROARAUDIO_DEFAULT_SOCKET" != '' ] then ln -s "$ROARAUDIO_DEFAULT_SOCKET" /etc/roarserver fi case "$MUROARD_AF" in UNIX|unix) MUROARD_OPTS="--unix $MUROARD_OPTS" [ "$MUROARD_SOCKET" = '' ] || MUROARD_OPTS="--bind $MUROARD_SOCKET $MUROARD_OPTS" ;; TCP|tcp) MUROARD_OPTS="--tcp $MUROARD_OPTS" [ "$MUROARD_PORT" = '' ] || MUROARD_OPTS="--port $MUROARD_PORT $MUROARD_OPTS" [ "$MUROARD_HOST" = '' ] || MUROARD_OPTS="--bind $MUROARD_HOST $MUROARD_OPTS" ;; DECnet|DECNET|decnet) MUROARD_OPTS="-n $MUROARD_OPTS" [ "$MUROARD_OBJECT" = '' ] || MUROARD_OPTS="--bind ::$MUROARD_OBJECT $MUROARD_OPTS" ;; esac [ "$MUROARD_RATE" = '' ] || MUROARD_OPTS="--rate $MUROARD_RATE $MUROARD_OPTS" [ "$MUROARD_CHANNEL" = '' ] || MUROARD_OPTS="--chans $MUROARD_CHANNEL $MUROARD_OPTS" [ "$MUROARD_DEVICE" = '' ] || MUROARD_OPTS="--odevice $MUROARD_DEVICE $MUROARD_OPTS" if [ "$MUROARD_USER" = '' ] then for _u in $USER_LIST do _r=`id -un $_u 2> /dev/null` if [ "$_u" = "$_r" ] then MUROARD_USER="$_u"; break; fi done else _r=`id -un "$MUROARD_USER" 2> /dev/null` if [ "$_r" != "$MUROARD_USER" ] then echo "Error starting muRoarD: can not find configured user $MUROARD_USER" >&2 echo "Hint: re-configure user in /etc/default/$NAME (see MUROARD_USER)" >&2 exit 1; fi fi if [ "$MUROARD_USER" = '' ] then echo "Error starting muRoarD: can not find any user to run roard as." >&2 echo "Hint: configure user in /etc/default/$NAME explicitly (see MUROARD_USER)" >&2 exit 1; fi set -e SSD_OPTS="--pidfile $PIDFILE --user $MUROARD_USER --exec $DAEMON" if [ "$MUROARD_GROUP" != '' ] then CHUID="$MUROARD_USER:$MUROARD_GROUP" SSD_OPTS="$SSD_OPTS --group $MUROARD_GROUP" else CHUID="$MUROARD_USER" fi case "$1" in start) [ "$MUROARD" = 'YES' ] || exit 0; echo -n "Starting $DESC: " start-stop-daemon --start --chuid $CHUID $SSD_OPTS --make-pidfile --background -- $MUROARD_OPTS echo "$NAME." ;; stop|terminate|shutdown) echo -n "Stopping $DESC: " start-stop-daemon --stop --retry 8 --oknodo --quiet $SSD_OPTS || true echo "$NAME." ;; restart|force-reload) $0 stop $0 start ;; status) echo -n "Status of $DESC: " set +e if [ "$PIDFILE" != '' ] then PID=`cat $PIDFILE 2> /dev/null` if [ "$PID" != '' ] then kill -0 $PID 2> /dev/null if [ "$?" = '0' ] then echo "running." exit 0; else echo "dead (stale pid file)." exit 1; fi else echo "not running." exit 3; fi fi set -e echo "unknown (no pid file configured)." exit 4 ;; *) echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|terminate|shutdown|status}" >&2 exit 1 ;; esac exit 0 #ll