commit 1762dfbf982a75d895676b0063379e33b4f9b96a Author: Erik Walthinsen Date: Sun Jan 30 09:03:00 2000 +0000 initial checkin Original commit message from CVS: initial checkin diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000000..0172ce2c31 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Erik Walthinsen diff --git a/COPYING b/COPYING new file mode 100644 index 0000000000..d60c31a97a --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/COPYING.LIB b/COPYING.LIB new file mode 100644 index 0000000000..eb685a5ec9 --- /dev/null +++ b/COPYING.LIB @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library 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 Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000000..e69de29bb2 diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000000..b42a17ac46 --- /dev/null +++ b/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000000..21a11f864a --- /dev/null +++ b/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = gst plugins test editor tools docs diff --git a/NEWS b/NEWS new file mode 100644 index 0000000000..e69de29bb2 diff --git a/README b/README new file mode 100644 index 0000000000..b66f5df0ff --- /dev/null +++ b/README @@ -0,0 +1,7 @@ +This is gnome-streamer, a framework for streaming media in GNOME. The +fundamental design comes from the video pipeline at Oregon Graduate +Institute, as well as some ideas from DirectX. It's based on plug-ins +that will provide the various codec and other functionality. The +interface hopefully is generic enough for various companies (ahem, Apple) +to release binary codecs for Linux, until such time as they get a clue and +release the source. diff --git a/acconfig.h b/acconfig.h new file mode 100644 index 0000000000..de7a6f8ba9 --- /dev/null +++ b/acconfig.h @@ -0,0 +1,11 @@ +#undef PLUGINS_DIR +#undef PLUGINS_SRCDIR +#undef PLUGINS_USE_SRCDIR + +#undef HAVE_LIBGHTTP +#undef HAVE_LIBXML +#undef HAVE_LIBMMX + +#undef HAVE_ATOMIC_H + +#undef DEBUG_ENABLED diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000000..1e0e7be7f7 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,67 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +DIE=0 +package=gstreamer +srcfile=gst/gstobject.h + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have autoconf installed to compile $package." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(libtool --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have libtool installed to compile $package." + echo "Get ftp://alpha.gnu.org/gnu/libtool-1.2.tar.gz" + echo "(or a newer version if it is available)" + DIE=1 +} + +(automake --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have automake installed to compile $package." + echo "Get ftp://ftp.cygnus.com/pub/home/tromey/automake-1.2d.tar.gz" + echo "(or a newer version if it is available)" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +test -f $srcfile || { + echo "You must run this script in the top-level $package directory" + exit 1 +} + +if test -z "$*"; then + echo "I am going to run ./configure with no arguments - if you wish " + echo "to pass any to it, please specify them on the $0 command line." +fi + +libtoolize --copy --force +aclocal $ACLOCAL_FLAGS +automake --add-missing +autoconf +autoheader + +if [ "x$1" = "x--autogen-recurse" ];then + exit # the rest will happen later +fi + +for dir in `find * -name autogen.sh -print | grep -v '^autogen.sh$' | \ + sed 's/autogen.sh$//'`;do + echo "Recursively running autogen.sh in $dir" + pushd $dir > /dev/null + ./autogen.sh --autogen-recurse "$@" + popd > /dev/null +done + +./configure --enable-maintainer-mode "$@" + +echo +echo "Now type 'make' to compile $package." diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000000..cedb21b832 --- /dev/null +++ b/config.h.in @@ -0,0 +1,29 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if you need to in order for stat and other things to work. */ +#undef _POSIX_SOURCE + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +#undef PLUGINS_DIR +#undef PLUGINS_SRCDIR +#undef PLUGINS_USE_SRCDIR + +#undef HAVE_LIBGHTTP +#undef HAVE_LIBXML +#undef HAVE_LIBMMX + +#undef HAVE_ATOMIC_H + +#undef DEBUG_ENABLED + +/* Define if you have the header file. */ +#undef HAVE_ASM_ATOMIC_H + +/* Name of package */ +#undef PACKAGE + +/* Version number of package */ +#undef VERSION + diff --git a/configure.in b/configure.in new file mode 100644 index 0000000000..215cc776e4 --- /dev/null +++ b/configure.in @@ -0,0 +1,145 @@ +AC_INIT(gst/gstobject.h) + +AM_CONFIG_HEADER(config.h) + +STREAMER_MAJOR_VERSION=0 +STREAMER_MINOR_VERSION=0 +STREAMER_MICRO_VERSION=9.2 +STREAMER_VERSION=$STREAMER_MAJOR_VERSION.$STREAMER_MINOR_VERSION.$STREAMER_MICRO_VERSION + +dnl libtool +STREAMER_CURRENT=0 +STREAMER_REVISION=0 +STREAMER_AGE=0 + +AM_INIT_AUTOMAKE(gstreamer, $STREAMER_VERSION) + +AC_SUBST(STREAMER_MAJOR_VERSION) +AC_SUBST(STREAMER_MINOR_VERSION) +AC_SUBST(STREAMER_MICRO_VERSION) +AC_SUBST(STREAMER_VERSION) + +AC_SUBST(STREAMER_CURRENT) +AC_SUBST(STREAMER_REVISION) +AC_SUBST(STREAMER_AGE) + + +AM_MAINTAINER_MODE + +AC_ISC_POSIX +AC_PROG_CC +AC_STDC_HEADERS +AC_ARG_PROGRAM + +AM_DISABLE_STATIC +AC_LIBTOOL_DLOPEN +AM_PROG_LIBTOOL + +AM_PATH_GLIB(1.2.0, + [LIBS="$LIBS $GLIB_LIBS" CFLAGS="$CFLAGS $GLIB_CFLAGS"], + AC_MSG_ERROR(Cannot find glib: Is glib-config in path?), + glib gmodule gthread) +AM_PATH_GTK(1.2.0) + +dnl Check for libghttp +AC_CHECK_LIB(ghttp,ghttp_request_new, + [LIBS="$LIBS -lghttp" HAVE_LIBGHTTP="yes"], + AC_MSG_WARN(Cannot find libghttp: can't build gsthttpsrc), + $LIBS) +AC_DEFINE(HAVE_LIBGHTTP) +AM_CONDITIONAL(HAVE_LIBGHTTP, test "x$HAVE_LIBGHTTP" = "xyes") + + +AC_CHECK_HEADERS(asm/atomic.h, AC_DEFINE(HAVE_ATOMIC_H)) + + +AC_PATH_PROG(XML_CONFIG,xml-config,no) +if test x$XML_CONFIG = xno;then + AC_MSG_ERROR(Couldn't find xml-config) +fi +XML_LIBS=`xml-config --libs` +XML_CFLAGS=`xml-config --cflags` +AC_SUBST(XML_LIBS) +AC_SUBST(XML_CFLAGS) +AC_DEFINE(HAVE_LIBXML) +AM_CONDITIONAL(HAVE_LIBXML, test "x$HAVE_LIBXML" = "xyes") + + +AC_CHECK_HEADER(mmx.h,[HAVE_LIBMMX=yes],) +AC_DEFINE(HAVE_LIBMMX) +AM_CONDITIONAL(HAVE_LIBMMX, test "x$HAVE_LIBMMX" = "xyes") + + +PLUGINS_DIR=${libdir}/plugins +AC_DEFINE_UNQUOTED(PLUGINS_DIR,"$PLUGINS_DIR") +AC_SUBST(PLUGINS_DIR) + +PLUGINS_SRCDIR=`pwd`/$srcdir +AC_DEFINE_UNQUOTED(PLUGINS_SRCDIR,"$PLUGINS_SRCDIR") +AC_SUBST(PLUGINS_SRCDIR) + +AC_ARG_ENABLE(plugin-srcdir, +[ --enable-plugin-srcdir allow tests/demos to use non-installed plugins ], +[AC_DEFINE(PLUGINS_USE_SRCDIR)]) + +AC_DEFINE(PLUGINS_USE_SRCDIR) + +AC_ARG_ENABLE(debug, +[ --enable-debug spews lots of useless info at runtime], +[AC_DEFINE(DEBUG_ENABLED)]) + +AC_ARG_ENABLE(profiling, +[ --enable-profiling adds -pg to compiler commandline, for profiling], +[CFLAGS="$CFLAGS -pg"]) + + +AC_SUBST(CFLAGS) +AC_SUBST(CPPFLAGS) +AC_SUBST(LDFLAGS) + +AC_CHECK_PROG(GTKDOC, gtkdoc-mkdb, true, false) +AM_CONDITIONAL(HAVE_GTK_DOC, $GTKDOC) + + +AC_CONFIG_SUBDIRS(gist) +AC_CONFIG_SUBDIRS(plugins/mp3decode/xing/libxing) + +AC_OUTPUT([Makefile +gst/Makefile +gst/types/Makefile +gst/meta/Makefile +gst/elements/Makefile +gst/xml/Makefile +plugins/Makefile +plugins/au/Makefile +plugins/wav/Makefile +plugins/mp3decode/Makefile +plugins/mp3decode/xa/Makefile +plugins/mp3decode/xing/Makefile +plugins/mp3decode/mpg123/Makefile +plugins/mp3decode/parse/Makefile +plugins/mpeg2/Makefile +plugins/mpeg2/parse/Makefile +plugins/mpeg2/ac3parse/Makefile +plugins/mpeg2/ac3dec/Makefile +plugins/mpeg1/Makefile +plugins/mpeg1/parse/Makefile +plugins/effects/Makefile +plugins/effects/stereo/Makefile +plugins/effects/volume/Makefile +plugins/visualization/Makefile +plugins/visualization/spectrum/Makefile +plugins/visualization/vumeter/Makefile +plugins/visualization/synaesthesia/Makefile +plugins/visualization/smoothwave/Makefile +plugins/dvdsrc/Makefile +plugins/vcdsrc/Makefile +plugins/cobin/Makefile +test/Makefile +test/xml/Makefile +test/bindings/Makefile +test/cothreads/Makefile +editor/Makefile +tools/Makefile +docs/Makefile +stamp.h]) diff --git a/gst/Makefile.am b/gst/Makefile.am new file mode 100644 index 0000000000..7cf7b94bf5 --- /dev/null +++ b/gst/Makefile.am @@ -0,0 +1,61 @@ +# cheap trick to build . first... +SUBDIRS = . types meta elements xml + +lib_LTLIBRARIES = libgst.la + +GSTOBJECT_SRCS = \ + gstobject.c +GSTOBJECT_INCLUDES = \ + gstobject.h + +libgst_la_SOURCES = \ + gst.c \ + $(GSTOBJECT_SRCS) \ + gstpad.c \ + gstbuffer.c \ + gstelement.c \ + gstelementfactory.c \ + gstbin.c \ + gstpipeline.c \ + gstthread.c \ + gstsrc.c \ + gstfilter.c \ + gstsink.c \ + gstconnection.c \ + gsttype.c \ + gstplugin.c \ + gstutils.c \ + gsttrace.c \ + gstmeta.c \ + gsttee.c \ + gstxml.c \ + cothreads.c + +libgstincludedir = $(includedir)/gst +libgstinclude_HEADERS = \ + gst.h \ + gstlog.h \ + $(GSTOBJECT_INCLUDES) \ + gstpad.h \ + gstbuffer.h \ + gstelement.h \ + gstbin.h \ + gstpipeline.h \ + gstthread.h \ + gstsrc.h \ + gstfilter.h \ + gstsink.h \ + gstconnection.h \ + gsttype.h \ + gstplugin.h \ + gstutils.h \ + gsttrace.h \ + gstmeta.h \ + gsttee.h \ + gstxml.h \ + cothreads.h + +libgst_la_LIBADD = $(GLIB_LIBS) $(GTK_LIBS) $(XML_LIBS) +libgst_la_LDFLAGS = -version-info $(STREAMER_CURRENT):$(STREAMER_REVISION):$(STREAMER_AGE) + +EXTRA_DIST = ROADMAP diff --git a/gst/cothreads.c b/gst/cothreads.c new file mode 100644 index 0000000000..8b12b67083 --- /dev/null +++ b/gst/cothreads.c @@ -0,0 +1,143 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cothreads.h" + +pthread_key_t _cothread_key = -1; + +cothread_state *cothread_create(cothread_context *ctx) { + cothread_state *s; + + if (pthread_self() == 0) { + s = (cothread_state *)malloc(sizeof(int) * COTHREAD_STACKSIZE); + } else { + char *sp = CURRENT_STACK_FRAME; + unsigned long *stack_end = (unsigned long *)((unsigned long)sp & + ~(STACK_SIZE - 1)); + s = (cothread_state *)(stack_end + ((ctx->nthreads - 1) * + COTHREAD_STACKSIZE)); + if (mmap((char *)s,COTHREAD_STACKSIZE*(sizeof(int)), + PROT_READ|PROT_WRITE|PROT_EXEC,MAP_PRIVATE|MAP_ANONYMOUS, + -1,0) < 0) { + perror("mmap'ing cothread stack space"); + return NULL; + } + } + + s->ctx = ctx; + s->threadnum = ctx->nthreads; + s->flags = 0; + s->sp = (int *)(s + COTHREAD_STACKSIZE); + + ctx->threads[ctx->nthreads++] = s; + +// printf("created cothread at %p\n",s); + + return s; +} + +void cothread_setfunc(cothread_state *thread,cothread_func func,int argc,char **argv) { + thread->func = func; + thread->argc = argc; + thread->argv = argv; + thread->pc = (int *)func; +} + +cothread_context *cothread_init() { + cothread_context *ctx = (cothread_context *)malloc(sizeof(cothread_context)); + + if (_cothread_key == -1) { + if (pthread_key_create(&_cothread_key,NULL) != 0) { + perror("pthread_key_create"); + return; + } + } + pthread_setspecific(_cothread_key,ctx); + + memset(ctx->threads,0,sizeof(ctx->threads)); + + ctx->threads[0] = (cothread_state *)malloc(sizeof(cothread_state)); + ctx->threads[0]->ctx = ctx; + ctx->threads[0]->threadnum = 0; + ctx->threads[0]->func = NULL; + ctx->threads[0]->argc = 0; + ctx->threads[0]->argv = NULL; + ctx->threads[0]->flags = COTHREAD_STARTED; + ctx->threads[0]->sp = CURRENT_STACK_FRAME; + ctx->threads[0]->pc = 0; + +// fprintf(stderr,"0th thread is at %p\n",ctx->threads[0]); + + // we consider the initiating process to be cothread 0 + ctx->nthreads = 1; + ctx->current = 0; + + return ctx; +} + +cothread_state *cothread_main(cothread_context *ctx) { +// fprintf(stderr,"returning %p, the 0th cothread\n",ctx->threads[0]); + return ctx->threads[0]; +} + +void cothread_stub() { + cothread_context *ctx = pthread_getspecific(_cothread_key); + register cothread_state *thread = ctx->threads[ctx->current]; + + thread->flags |= COTHREAD_STARTED; + thread->func(thread->argc,thread->argv); + thread->flags &= ~COTHREAD_STARTED; + thread->pc = 0; +// printf("uh, yeah, we shouldn't be here, but we should deal anyway\n"); +} + +void cothread_switch(cothread_state *thread) { + cothread_context *ctx; + cothread_state *current; + int enter = 0; +// int i; + + if (thread == NULL) + return; + + ctx = thread->ctx; + + current = ctx->threads[ctx->current]; + if (current == NULL) { + fprintf(stderr,"there's no current thread, help!\n"); + exit(2); + } + + if (current == thread) { + fprintf(stderr,"trying to switch to same thread, legal but not necessary\n"); + return; + } + + // find the number of the thread to switch to + ctx->current = thread->threadnum; +// fprintf(stderr,"about to switch to thread #%d\n",ctx->current); + + /* save the current stack pointer, frame pointer, and pc */ + __asm__("movl %%esp, %0" : "=m"(current->sp) : : "esp", "ebp"); + enter = setjmp(current->jmp); + if (enter != 0) + return; + enter = 1; + + /* restore stack pointer and other stuff of new cothread */ + __asm__("movl %0, %%esp\n" : "=m"(thread->sp)); + if (thread->flags & COTHREAD_STARTED) { + // switch to it + longjmp(thread->jmp,1); + } else { + // start it + __asm__("jmp " SYMBOL_NAME_STR(cothread_stub)); + } +} diff --git a/gst/cothreads.h b/gst/cothreads.h new file mode 100644 index 0000000000..63fef42901 --- /dev/null +++ b/gst/cothreads.h @@ -0,0 +1,48 @@ +#ifndef __COTHREADS_H__ +#define __COTHREADS_H__ + +#include +#include + +#define COTHREAD_STACKSIZE 8192 +#define COTHREAD_MAXTHREADS 16 +#define STACK_SIZE 0x200000 + +#ifndef CURRENT_STACK_FRAME +#define CURRENT_STACK_FRAME ({ char __csf; &__csf; }) +#endif /* CURRENT_STACK_FRAME */ + +typedef struct _cothread_state cothread_state; +typedef struct _cothread_context cothread_context; + +typedef int (*cothread_func)(int argc,char **argv); + +#define COTHREAD_STARTED 0x01 + +struct _cothread_state { + cothread_context *ctx; + int threadnum; + + cothread_func func; + int argc; + char **argv; + + int flags; + int *sp; + int *pc; + jmp_buf jmp; +}; + +struct _cothread_context { + cothread_state *threads[COTHREAD_MAXTHREADS]; + int nthreads; + int current; +}; + +cothread_context *cothread_init(); +cothread_state *cothread_create(cothread_context *ctx); +void cothread_setfunc(cothread_state *thread,cothread_func func,int argc,char **argv); +void cothread_switch(cothread_state *thread); +cothread_state *cothread_main(cothread_context *ctx); + +#endif /* __COTHREAD_H__ */ diff --git a/gst/elements/Makefile.am b/gst/elements/Makefile.am new file mode 100644 index 0000000000..d035695115 --- /dev/null +++ b/gst/elements/Makefile.am @@ -0,0 +1,35 @@ +lib_LTLIBRARIES = libgstelements.la + +libgstelements_la_DEPENDENCIES = ../libgst.la +libgstelements_la_SOURCES = \ + gstelements.c \ + gstfakesrc.c \ + gstidentity.c \ + gstfakesink.c \ + gstdisksrc.c \ + gstasyncdisksrc.c \ + gstfdsrc.c \ + gsthttpsrc.c \ + gstaudiosink.c \ + gstaudiosrc.c \ + gstfdsink.c \ + gstqueue.c \ + gstsinesrc.c + +noinst_HEADERS = \ + gstfakesrc.h \ + gstidentity.h \ + gstfakesink.h \ + gstdisksrc.h \ + gstasyncdisksrc.h \ + gstfdsrc.h \ + gsthttpsrc.h \ + gstaudiosink.h \ + gstaudiosrc.h \ + gstfdsink.h \ + gstqueue.h \ + gstsinesrc.h + +libgstelements_la_LIBADD = $(GLIB_LIBS) $(GTK_LIBS) \ + $(top_srcdir)/gst/libgst.la +libgstelements_la_LDFLAGS = -version-info $(STREAMER_CURRENT):$(STREAMER_REVISION):$(STREAMER_AGE) diff --git a/gst/elements/gstasyncdisksrc.c b/gst/elements/gstasyncdisksrc.c new file mode 100644 index 0000000000..8587fa53be --- /dev/null +++ b/gst/elements/gstasyncdisksrc.c @@ -0,0 +1,346 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +#include + + +GstElementDetails gst_asyncdisksrc_details = { + "Asynchronous Disk Source", + "Source/File", + "Read from arbitrary point in a file", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* AsyncDiskSrc signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_LOCATION, + ARG_BYTESPERREAD, + ARG_LENGTH, + ARG_OFFSET, +}; + + +static void gst_asyncdisksrc_class_init(GstAsyncDiskSrcClass *klass); +static void gst_asyncdisksrc_init(GstAsyncDiskSrc *asyncdisksrc); +static void gst_asyncdisksrc_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_asyncdisksrc_get_arg(GtkObject *object,GtkArg *arg,guint id); + +static void gst_asyncdisksrc_push(GstSrc *src); +static void gst_asyncdisksrc_push_region(GstSrc *src,gulong offset, + gulong size); +static gboolean gst_asyncdisksrc_change_state(GstElement *element, + GstElementState state); + + +static GstSrcClass *parent_class = NULL; +static guint gst_asyncdisksrc_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_asyncdisksrc_get_type(void) { + static GtkType asyncdisksrc_type = 0; + + if (!asyncdisksrc_type) { + static const GtkTypeInfo asyncdisksrc_info = { + "GstAsyncDiskSrc", + sizeof(GstAsyncDiskSrc), + sizeof(GstAsyncDiskSrcClass), + (GtkClassInitFunc)gst_asyncdisksrc_class_init, + (GtkObjectInitFunc)gst_asyncdisksrc_init, + (GtkArgSetFunc)gst_asyncdisksrc_set_arg, + (GtkArgGetFunc)gst_asyncdisksrc_get_arg, + (GtkClassInitFunc)NULL, + }; + asyncdisksrc_type = gtk_type_unique(GST_TYPE_SRC,&asyncdisksrc_info); + } + return asyncdisksrc_type; +} + +static void +gst_asyncdisksrc_class_init(GstAsyncDiskSrcClass *klass) { + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + GstSrcClass *gstsrc_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + gstsrc_class = (GstSrcClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SRC); + + gtk_object_add_arg_type("GstAsyncDiskSrc::location", GTK_TYPE_STRING, + GTK_ARG_READWRITE, ARG_LOCATION); + gtk_object_add_arg_type("GstAsyncDiskSrc::bytesperread", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_BYTESPERREAD); + gtk_object_add_arg_type("GstAsyncDiskSrc::length", GTK_TYPE_LONG, + GTK_ARG_READABLE, ARG_LENGTH); + gtk_object_add_arg_type("GstAsyncDiskSrc::offset", GTK_TYPE_LONG, + GTK_ARG_READWRITE, ARG_OFFSET); + + gtkobject_class->set_arg = gst_asyncdisksrc_set_arg; + gtkobject_class->get_arg = gst_asyncdisksrc_get_arg; + + gstelement_class->change_state = gst_asyncdisksrc_change_state; + + gstsrc_class->push = gst_asyncdisksrc_push; + gstsrc_class->push_region = gst_asyncdisksrc_push_region; +} + +static void gst_asyncdisksrc_init(GstAsyncDiskSrc *asyncdisksrc) { + GST_SRC_SET_FLAGS(asyncdisksrc,GST_SRC_ASYNC); + + asyncdisksrc->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(asyncdisksrc),asyncdisksrc->srcpad); + + asyncdisksrc->filename = NULL; + asyncdisksrc->fd = 0; + asyncdisksrc->size = 0; + asyncdisksrc->map = NULL; + asyncdisksrc->curoffset = 0; + asyncdisksrc->bytes_per_read = 4096; + asyncdisksrc->seq = 0; +} + + +static void gst_asyncdisksrc_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstAsyncDiskSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_ASYNCDISKSRC(object)); + src = GST_ASYNCDISKSRC(object); + + switch(id) { + case ARG_LOCATION: + /* the element must be stopped in order to do this */ + g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING)); + + if (src->filename) g_free(src->filename); + /* clear the filename if we get a NULL (is that possible?) */ + if (GTK_VALUE_STRING(*arg) == NULL) { + src->filename = NULL; + gst_element_set_state(GST_ELEMENT(object),~GST_STATE_COMPLETE); + /* otherwise set the new filename */ + } else { + src->filename = g_strdup(GTK_VALUE_STRING(*arg)); + gst_element_set_state(GST_ELEMENT(object),GST_STATE_COMPLETE); + } + break; + case ARG_BYTESPERREAD: + src->bytes_per_read = GTK_VALUE_INT(*arg); + break; + case ARG_OFFSET: + src->curoffset = GTK_VALUE_LONG(*arg); + break; + default: + break; + } +} + +static void gst_asyncdisksrc_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstAsyncDiskSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_ASYNCDISKSRC(object)); + src = GST_ASYNCDISKSRC(object); + + switch (id) { + case ARG_LOCATION: + GTK_VALUE_STRING(*arg) = src->filename; + break; + case ARG_BYTESPERREAD: + GTK_VALUE_INT(*arg) = src->bytes_per_read; + break; + case ARG_LENGTH: + GTK_VALUE_LONG(*arg) = src->size; + break; + case ARG_OFFSET: + GTK_VALUE_LONG(*arg) = src->curoffset; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +/** + * gst_asyncdisksrc_push: + * @src: #GstSrc to push a buffer from + * + * Push a new buffer from the asyncdisksrc at the current offset. + */ +void gst_asyncdisksrc_push(GstSrc *src) { + GstAsyncDiskSrc *asyncdisksrc; + GstBuffer *buf; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_ASYNCDISKSRC(src)); + g_return_if_fail(GST_FLAG_IS_SET(src,GST_ASYNCDISKSRC_OPEN)); + asyncdisksrc = GST_ASYNCDISKSRC(src); + + /* deal with EOF state */ + if (asyncdisksrc->curoffset >= asyncdisksrc->size) { + gst_src_signal_eos(GST_SRC(asyncdisksrc)); + return; + } + + /* create the buffer */ + // FIXME: should eventually use a bufferpool for this + buf = GST_BUFFER(gst_buffer_new()); + g_return_if_fail(buf != NULL); + + /* simply set the buffer to point to the correct region of the file */ + GST_BUFFER_DATA(buf) = asyncdisksrc->map + asyncdisksrc->curoffset; + GST_BUFFER_OFFSET(buf) = asyncdisksrc->curoffset; + + if ((asyncdisksrc->curoffset + asyncdisksrc->bytes_per_read) > + asyncdisksrc->size) { + GST_BUFFER_SIZE(buf) = asyncdisksrc->size - asyncdisksrc->curoffset; + // FIXME: set the buffer's EOF bit here + } else + GST_BUFFER_SIZE(buf) = asyncdisksrc->bytes_per_read; + asyncdisksrc->curoffset += GST_BUFFER_SIZE(buf); + + /* we're done, push the buffer off now */ + gst_pad_push(asyncdisksrc->srcpad,buf); +} + +/** + * gst_asyncdisksrc_push_region: + * @src: #GstSrc to push a buffer from + * @offset: offset in file + * @size: number of bytes + * + * Push a new buffer from the asyncdisksrc of given size at given offset. + */ +void gst_asyncdisksrc_push_region(GstSrc *src,gulong offset,gulong size) { + GstAsyncDiskSrc *asyncdisksrc; + GstBuffer *buf; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_ASYNCDISKSRC(src)); + g_return_if_fail(GST_FLAG_IS_SET(src,GST_STATE_RUNNING)); + asyncdisksrc = GST_ASYNCDISKSRC(src); + + /* deal with EOF state */ + if (offset >= asyncdisksrc->size) { + gst_src_signal_eos(GST_SRC(asyncdisksrc)); + return; + } + + /* create the buffer */ + // FIXME: should eventually use a bufferpool for this + buf = gst_buffer_new(); + g_return_if_fail(buf); + + /* simply set the buffer to point to the correct region of the file */ + GST_BUFFER_DATA(buf) = asyncdisksrc->map + offset; + GST_BUFFER_OFFSET(buf) = asyncdisksrc->curoffset; + + if ((offset + size) > asyncdisksrc->size) { + GST_BUFFER_SIZE(buf) = asyncdisksrc->size - offset; + // FIXME: set the buffer's EOF bit here + } else + GST_BUFFER_SIZE(buf) = size; + asyncdisksrc->curoffset += GST_BUFFER_SIZE(buf); + + /* we're done, push the buffer off now */ + gst_pad_push(asyncdisksrc->srcpad,buf); +} + + +/* open the file and mmap it, necessary to go to RUNNING state */ +static gboolean gst_asyncdisksrc_open_file(GstAsyncDiskSrc *src) { + g_return_if_fail(!GST_FLAG_IS_SET(src,GST_ASYNCDISKSRC_OPEN)); + + /* open the file */ + src->fd = open(src->filename,O_RDONLY); + if (src->fd < 0) { + gst_element_error(GST_ELEMENT(src),"opening file"); + return FALSE; + } else { + /* find the file length */ + src->size = lseek(src->fd,0,SEEK_END); + lseek(src->fd,0,SEEK_SET); + /* map the file into memory */ + src->map = mmap(NULL,src->size,PROT_READ,MAP_SHARED,src->fd,0); + /* collapse state if that failed */ + if (src->map == NULL) { + close(src->fd); + gst_element_error(GST_ELEMENT(src),"mmapping file"); + return FALSE; + } + GST_FLAG_SET(src,GST_ASYNCDISKSRC_OPEN); + } + return TRUE; +} + +/* unmap and close the file */ +static void gst_asyncdisksrc_close_file(GstAsyncDiskSrc *src) { + g_return_if_fail(GST_FLAG_IS_SET(src,GST_ASYNCDISKSRC_OPEN)); + + /* unmap the file from memory */ + munmap(src->map,src->size); + /* close the file */ + close(src->fd); + + /* zero out a lot of our state */ + src->fd = 0; + src->size = 0; + src->map = NULL; + src->curoffset = 0; + src->seq = 0; + + GST_FLAG_UNSET(src,GST_ASYNCDISKSRC_OPEN); +} + + +static gboolean gst_asyncdisksrc_change_state(GstElement *element, + GstElementState state) { + g_return_if_fail(GST_IS_ASYNCDISKSRC(element)); + + switch (state) { + case GST_STATE_RUNNING: + if (!gst_asyncdisksrc_open_file(GST_ASYNCDISKSRC(element))) + return FALSE; + break; + case ~GST_STATE_RUNNING: + gst_asyncdisksrc_close_file(GST_ASYNCDISKSRC(element)); + break; + default: + break; + } + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + return TRUE; +} diff --git a/gst/elements/gstasyncdisksrc.h b/gst/elements/gstasyncdisksrc.h new file mode 100644 index 0000000000..5c50d6ef5b --- /dev/null +++ b/gst/elements/gstasyncdisksrc.h @@ -0,0 +1,88 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_ASYNCDISKSRC_H__ +#define __GST_ASYNCDISKSRC_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_asyncdisksrc_details; + + +#define GST_TYPE_ASYNCDISKSRC \ + (gst_asyncdisksrc_get_type()) +#define GST_ASYNCDISKSRC(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_ASYNCDISKSRC,GstAsyncDiskSrc)) +#define GST_ASYNCDISKSRC_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_ASYNCDISKSRC,GstAsyncDiskSrcClass)) +#define GST_IS_ASYNCDISKSRC(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_ASYNCDISKSRC)) +#define GST_IS_ASYNCDISKSRC_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_ASYNCDISKSRC))) + +// NOTE: per-element flags start with 16 for now +typedef enum { + GST_ASYNCDISKSRC_OPEN = (1 << 16), +} GstAsyncDiskSrcFlags; + +typedef struct _GstAsyncDiskSrc GstAsyncDiskSrc; +typedef struct _GstAsyncDiskSrcClass GstAsyncDiskSrcClass; + +struct _GstAsyncDiskSrc { + GstSrc src; + /* pads */ + GstPad *srcpad; + + /* filename */ + gchar *filename; + /* fd */ + gint fd; + + /* mapping parameters */ + gulong size; /* how long is the file? */ + guchar *map; /* where the file is mapped to */ + + /* details for fallback synchronous read */ + gulong curoffset; /* current offset in file */ + gulong bytes_per_read; /* bytes per read */ + + gulong seq; /* buffer sequence number */ +}; + +struct _GstAsyncDiskSrcClass { + GstSrcClass parent_class; +}; + +GtkType gst_asyncdisksrc_get_type(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_ASYNCDISKSRC_H__ */ diff --git a/gst/elements/gstaudiosink.c b/gst/elements/gstaudiosink.c new file mode 100644 index 0000000000..56523cbc56 --- /dev/null +++ b/gst/elements/gstaudiosink.c @@ -0,0 +1,291 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include +#include +#include +#include + +#include +#include + + +GstElementDetails gst_audiosink_details = { + "Audio Sink (OSS)", + "Sink/Audio", + "Output to a sound card via OSS", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +static gboolean gst_audiosink_open_audio(GstAudioSink *sink); +static void gst_audiosink_close_audio(GstAudioSink *sink); +static gboolean gst_audiosink_start(GstElement *element, + GstElementState state); +static gboolean gst_audiosink_stop(GstElement *element); +static gboolean gst_audiosink_change_state(GstElement *element, + GstElementState state); + + +/* AudioSink signals and args */ +enum { + HANDOFF, + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_audiosink_class_init(GstAudioSinkClass *klass); +static void gst_audiosink_init(GstAudioSink *audiosink); + + +static GstFilterClass *parent_class = NULL; +static guint gst_audiosink_signals[LAST_SIGNAL] = { 0 }; + +static guint16 gst_audiosink_type_audio = 0; + +GtkType +gst_audiosink_get_type(void) { + static GtkType audiosink_type = 0; + + if (!audiosink_type) { + static const GtkTypeInfo audiosink_info = { + "GstAudioSink", + sizeof(GstAudioSink), + sizeof(GstAudioSinkClass), + (GtkClassInitFunc)gst_audiosink_class_init, + (GtkObjectInitFunc)gst_audiosink_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + audiosink_type = gtk_type_unique(GST_TYPE_FILTER,&audiosink_info); + } + + if (!gst_audiosink_type_audio) + gst_audiosink_type_audio = gst_type_find_by_mime("audio/raw"); + + return audiosink_type; +} + +static void +gst_audiosink_class_init(GstAudioSinkClass *klass) { + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_FILTER); + + gst_audiosink_signals[HANDOFF] = + gtk_signal_new("handoff",GTK_RUN_LAST,gtkobject_class->type, + GTK_SIGNAL_OFFSET(GstAudioSinkClass,handoff), + gtk_marshal_NONE__POINTER_POINTER,GTK_TYPE_NONE,2, + GTK_TYPE_POINTER,GTK_TYPE_POINTER); + gtk_object_class_add_signals(gtkobject_class,gst_audiosink_signals, + LAST_SIGNAL); + + gstelement_class->start = gst_audiosink_start; + gstelement_class->stop = gst_audiosink_stop; + gstelement_class->change_state = gst_audiosink_change_state; +} + +static void gst_audiosink_init(GstAudioSink *audiosink) { + audiosink->sinkpad = gst_pad_new("sink",GST_PAD_SINK); + gst_element_add_pad(GST_ELEMENT(audiosink),audiosink->sinkpad); + if (!gst_audiosink_type_audio) + gst_audiosink_type_audio = gst_type_find_by_mime("audio/raw"); + gst_pad_set_type_id(audiosink->sinkpad,gst_audiosink_type_audio); + gst_pad_set_chain_function(audiosink->sinkpad,gst_audiosink_chain); + + audiosink->fd = -1; + + gst_element_set_state(GST_ELEMENT(audiosink),GST_STATE_COMPLETE); +} + +void gst_audiosink_sync_parms(GstAudioSink *audiosink) { + audio_buf_info ospace; + + g_return_if_fail(audiosink != NULL); + g_return_if_fail(GST_IS_AUDIOSINK(audiosink)); + g_return_if_fail(audiosink->fd > 0); + + ioctl(audiosink->fd,SNDCTL_DSP_RESET,0); + + ioctl(audiosink->fd,SNDCTL_DSP_SETFMT,&audiosink->format); + ioctl(audiosink->fd,SNDCTL_DSP_CHANNELS,&audiosink->channels); + ioctl(audiosink->fd,SNDCTL_DSP_SPEED,&audiosink->frequency); + + ioctl(audiosink->fd,SNDCTL_DSP_GETOSPACE,&ospace); + + g_print("setting sound card to %dKHz %d bit %s (%d bytes buffer)\n", + audiosink->frequency,audiosink->format, + (audiosink->channels == 2) ? "stereo" : "mono",ospace.bytes); +} + +GstElement *gst_audiosink_new(gchar *name) { + GstElement *audiosink = GST_ELEMENT(gtk_type_new(GST_TYPE_AUDIOSINK)); + gst_element_set_name(GST_ELEMENT(audiosink),name); + return audiosink; +} + +void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) { + GstAudioSink *audiosink; + MetaAudioRaw *meta; + + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(buf != NULL); + + /* this has to be an audio buffer */ +// g_return_if_fail(((GstMeta *)buf->meta)->type != +//gst_audiosink_type_audio); + audiosink = GST_AUDIOSINK(pad->parent); +// g_return_if_fail(GST_FLAG_IS_SET(audiosink,GST_STATE_RUNNING)); + + meta = (MetaAudioRaw *)gst_buffer_get_first_meta(buf); + if (meta != NULL) { + if ((meta->format != audiosink->format) || + (meta->channels != audiosink->channels) || + (meta->frequency != audiosink->frequency)) { + audiosink->format = meta->format; + audiosink->channels = meta->channels; + audiosink->frequency = meta->frequency; + gst_audiosink_sync_parms(audiosink); + g_print("sound device set to format %d, %d channels, %dHz\n", + audiosink->format,audiosink->channels,audiosink->frequency); + } + } + + gtk_signal_emit(GTK_OBJECT(audiosink),gst_audiosink_signals[HANDOFF], + audiosink); + if (GST_BUFFER_DATA(buf) != NULL) { + gst_trace_add_entry(NULL,0,buf,"audiosink: writing to soundcard"); + if (audiosink->fd > 2) + write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf)); + } + + gst_buffer_unref(buf); +// g_print("a"); +} + +void gst_audiosink_set_format(GstAudioSink *audiosink,gint format) { + g_return_if_fail(audiosink != NULL); + g_return_if_fail(GST_IS_AUDIOSINK(audiosink)); + + audiosink->format = format; + + gst_audiosink_sync_parms(audiosink); +} + +void gst_audiosink_set_channels(GstAudioSink *audiosink,gint channels) { + g_return_if_fail(audiosink != NULL); + g_return_if_fail(GST_IS_AUDIOSINK(audiosink)); + + audiosink->channels = channels; + + gst_audiosink_sync_parms(audiosink); +} + +void gst_audiosink_set_frequency(GstAudioSink *audiosink,gint frequency) { + g_return_if_fail(audiosink != NULL); + g_return_if_fail(GST_IS_AUDIOSINK(audiosink)); + + audiosink->frequency = frequency; + + gst_audiosink_sync_parms(audiosink); +} + +static gboolean gst_audiosink_open_audio(GstAudioSink *sink) { + g_return_if_fail(sink->fd == -1); + + g_print("attempting to open sound device\n"); + + /* first try to open the sound card */ + sink->fd = open("/dev/dsp",O_RDWR); + + /* if we have it, set the default parameters and go have fun */ + if (sink->fd > 0) { + /* set card state */ + sink->format = AFMT_S16_LE; + sink->channels = 2; /* stereo */ + sink->frequency = 44100; + gst_audiosink_sync_parms(sink); + g_print("opened audio\n"); + return TRUE; + } + + return FALSE; +} + +static void gst_audiosink_close_audio(GstAudioSink *sink) { + if (sink->fd < 0) return; + + close(sink->fd); + sink->fd = -1; + g_print("closed sound device\n"); +} + +static gboolean gst_audiosink_start(GstElement *element, + GstElementState state) { + g_return_if_fail(GST_IS_AUDIOSINK(element)); + + if (gst_audiosink_open_audio(GST_AUDIOSINK(element)) == TRUE) { + gst_element_set_state(element,GST_STATE_RUNNING | state); + return TRUE; + } + return FALSE; +} + +static gboolean gst_audiosink_stop(GstElement *element) { + g_return_if_fail(GST_IS_AUDIOSINK(element)); + + gst_audiosink_close_audio(GST_AUDIOSINK(element)); + gst_element_set_state(element,~GST_STATE_RUNNING); + return TRUE; +} + +static gboolean gst_audiosink_change_state(GstElement *element, + GstElementState state) { + g_return_if_fail(GST_IS_AUDIOSINK(element)); + + switch (state) { + case GST_STATE_RUNNING: + if (!gst_audiosink_open_audio(GST_AUDIOSINK(element))) + return FALSE; + break; + case ~GST_STATE_RUNNING: + gst_audiosink_close_audio(GST_AUDIOSINK(element)); + break; + default: + break; + } + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + return TRUE; +} diff --git a/gst/elements/gstaudiosink.h b/gst/elements/gstaudiosink.h new file mode 100644 index 0000000000..5159eb0a95 --- /dev/null +++ b/gst/elements/gstaudiosink.h @@ -0,0 +1,85 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_AUDIOSINK_H__ +#define __GST_AUDIOSINK_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_audiosink_details; + + +#define GST_TYPE_AUDIOSINK \ + (gst_audiosink_get_type()) +#define GST_AUDIOSINK(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_AUDIOSINK,GstAudioSink)) +#define GST_AUDIOSINK_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIOSINK,GstAudioSinkClass)) +#define GST_IS_AUDIOSINK(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_AUDIOSINK)) +#define GST_IS_AUDIOSINK_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIOSINK))) + +typedef struct _GstAudioSink GstAudioSink; +typedef struct _GstAudioSinkClass GstAudioSinkClass; + +struct _GstAudioSink { + GstFilter filter; + + GstPad *sinkpad; + + /* soundcard state */ + int fd; + gint format; + gint channels; + gint frequency; +}; + +struct _GstAudioSinkClass { + GstFilterClass parent_class; + + /* signals */ + void (*handoff) (GstElement *element,GstPad *pad); +}; + +GtkType gst_audiosink_get_type(void); +GstElement *gst_audiosink_new(gchar *name); +void gst_audiosink_chain(GstPad *pad,GstBuffer *buf); + +void gst_audiosink_sync_parms(GstAudioSink *audiosink); + +void gst_audiosink_set_format(GstAudioSink *audiosink,gint format); +void gst_audiosink_set_channels(GstAudioSink *audiosink,gint channels); +void gst_audiosink_set_frequency(GstAudioSink *audiosink,gint frequency); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_AUDIOSINK_H__ */ diff --git a/gst/elements/gstaudiosrc.c b/gst/elements/gstaudiosrc.c new file mode 100644 index 0000000000..2f06b4c74d --- /dev/null +++ b/gst/elements/gstaudiosrc.c @@ -0,0 +1,319 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +#include + + +GstElementDetails gst_audiosrc_details = { + "Audio (OSS) Source", + "Source/Audio", + "Read from the sound card", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* AudioSrc signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_LOCATION, + ARG_BYTESPERREAD, + ARG_CUROFFSET, + ARG_FORMAT, + ARG_CHANNELS, + ARG_FREQUENCY, +}; + + +static void gst_audiosrc_class_init(GstAudioSrcClass *klass); +static void gst_audiosrc_init(GstAudioSrc *audiosrc); +static void gst_audiosrc_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_audiosrc_get_arg(GtkObject *object,GtkArg *arg,guint id); +static gboolean gst_audiosrc_change_state(GstElement *element, + GstElementState state); +static void gst_audiosrc_close_audio(GstAudioSrc *src); +static gboolean gst_audiosrc_open_audio(GstAudioSrc *src); +void gst_audiosrc_sync_parms(GstAudioSrc *audiosrc); + + +static GstSrcClass *parent_class = NULL; +static guint gst_audiosrc_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_audiosrc_get_type(void) { + static GtkType audiosrc_type = 0; + + if (!audiosrc_type) { + static const GtkTypeInfo audiosrc_info = { + "GstAudioSrc", + sizeof(GstAudioSrc), + sizeof(GstAudioSrcClass), + (GtkClassInitFunc)gst_audiosrc_class_init, + (GtkObjectInitFunc)gst_audiosrc_init, + (GtkArgSetFunc)gst_audiosrc_set_arg, + (GtkArgGetFunc)gst_audiosrc_get_arg, + (GtkClassInitFunc)NULL, + }; + audiosrc_type = gtk_type_unique(GST_TYPE_SRC,&audiosrc_info); + } + return audiosrc_type; +} + +static void +gst_audiosrc_class_init(GstAudioSrcClass *klass) { + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + GstSrcClass *gstsrc_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + gstsrc_class = (GstSrcClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SRC); + + gtk_object_add_arg_type("GstAudioSrc::location", GTK_TYPE_STRING, + GTK_ARG_READWRITE, ARG_LOCATION); + gtk_object_add_arg_type("GstAudioSrc::bytes_per_read", GTK_TYPE_ULONG, + GTK_ARG_READWRITE, ARG_BYTESPERREAD); + gtk_object_add_arg_type("GstAudioSrc::curoffset", GTK_TYPE_ULONG, + GTK_ARG_READABLE, ARG_CUROFFSET); + gtk_object_add_arg_type("GstAudioSrc::format", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FORMAT); + gtk_object_add_arg_type("GstAudioSrc::channels", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_CHANNELS); + gtk_object_add_arg_type("GstAudioSrc::frequency", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FREQUENCY); + + gtkobject_class->set_arg = gst_audiosrc_set_arg; + gtkobject_class->get_arg = gst_audiosrc_get_arg; + + gstelement_class->change_state = gst_audiosrc_change_state; + + gstsrc_class->push = gst_audiosrc_push; +} + +static void gst_audiosrc_init(GstAudioSrc *audiosrc) { + audiosrc->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(audiosrc),audiosrc->srcpad); + + audiosrc->filename = g_strdup("/dev/dsp"); + audiosrc->fd = -1; + +// audiosrc->meta = (MetaAudioRaw *)gst_meta_new(); +// audiosrc->meta->format = AFMT_S16_LE; +// audiosrc->meta->channels = 2; +// audiosrc->meta->frequency = 44100; +// audiosrc->meta->bps = 4; + + audiosrc->bytes_per_read = 4096; + audiosrc->curoffset = 0; + audiosrc->seq = 0; +} + +GstElement *gst_audiosrc_new(gchar *name) { + GstElement *audiosrc = GST_ELEMENT(gtk_type_new(GST_TYPE_AUDIOSRC)); + gst_element_set_name(GST_ELEMENT(audiosrc),name); + return audiosrc; +} + +GstElement *gst_audiosrc_new_with_fd(gchar *name,gchar *filename) { + GstElement *audiosrc = gst_audiosrc_new(name); + gtk_object_set(GTK_OBJECT(audiosrc),"location",filename,NULL); + return audiosrc; +} + +void gst_audiosrc_push(GstSrc *src) { + GstAudioSrc *audiosrc; + GstBuffer *buf; + glong readbytes; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_AUDIOSRC(src)); + audiosrc = GST_AUDIOSRC(src); + +// g_print("attempting to read something from soundcard\n"); + + buf = gst_buffer_new(); + g_return_if_fail(buf); + GST_BUFFER_DATA(buf) = (gpointer)g_malloc(audiosrc->bytes_per_read); + readbytes = read(audiosrc->fd,GST_BUFFER_DATA(buf), + audiosrc->bytes_per_read); + if (readbytes == 0) { + gst_src_signal_eos(GST_SRC(audiosrc)); + return; + } + + GST_BUFFER_SIZE(buf) = readbytes; + GST_BUFFER_OFFSET(buf) = audiosrc->curoffset; + audiosrc->curoffset += readbytes; + +// gst_buffer_add_meta(buf,GST_META(newmeta)); + + gst_pad_push(audiosrc->srcpad,buf); +// g_print("pushed buffer from soundcard of %d bytes\n",readbytes); +} + +static void gst_audiosrc_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstAudioSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_AUDIOSRC(object)); + src = GST_AUDIOSRC(object); + + switch (id) { + case ARG_LOCATION: + if (src->filename) g_free(src->filename); + if (GTK_VALUE_STRING(*arg) == NULL) { + src->filename = NULL; + gst_element_set_state(GST_ELEMENT(object),~GST_STATE_COMPLETE); + } else { + src->filename = g_strdup(GTK_VALUE_STRING(*arg)); + gst_element_set_state(GST_ELEMENT(object),GST_STATE_COMPLETE); + } + break; + case ARG_BYTESPERREAD: + src->bytes_per_read = GTK_VALUE_INT(*arg); + break; + case ARG_FORMAT: + src->format = GTK_VALUE_INT(*arg); + break; + case ARG_CHANNELS: + src->channels = GTK_VALUE_INT(*arg); + break; + case ARG_FREQUENCY: + src->frequency = GTK_VALUE_INT(*arg); + break; + default: + break; + } +} + +static void gst_audiosrc_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstAudioSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_AUDIOSRC(object)); + src = GST_AUDIOSRC(object); + + switch (id) { + case ARG_LOCATION: + GTK_VALUE_STRING(*arg) = g_strdup(src->filename); + break; + case ARG_BYTESPERREAD: + GTK_VALUE_INT(*arg) = src->bytes_per_read; + break; + case ARG_FORMAT: + GTK_VALUE_INT(*arg) = src->format; + break; + case ARG_CHANNELS: + GTK_VALUE_INT(*arg) = src->channels; + break; + case ARG_FREQUENCY: + GTK_VALUE_INT(*arg) = src->frequency; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static gboolean gst_audiosrc_change_state(GstElement *element, + GstElementState state) { + g_return_if_fail(GST_IS_AUDIOSRC(element)); + + switch (state) { + case GST_STATE_RUNNING: + if (!gst_audiosrc_open_audio(GST_AUDIOSRC(element))) + return FALSE; + break; + case ~GST_STATE_RUNNING: + gst_audiosrc_close_audio(GST_AUDIOSRC(element)); + break; + default: + break; + } + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + return TRUE; +} + +static gboolean gst_audiosrc_open_audio(GstAudioSrc *src) { + g_return_if_fail(src->fd == -1); + + /* first try to open the sound card */ + src->fd = open("/dev/dsp",O_RDONLY); + + /* if we have it, set the default parameters and go have fun */ + if (src->fd > 0) { + int arg = 0x7fff0006; + + if (ioctl(src->fd, SNDCTL_DSP_SETFRAGMENT, &arg)) perror("uh"); + + /* set card state */ + gst_audiosrc_sync_parms(src); + DEBUG("opened audio\n"); + return TRUE; + } + + return FALSE; +} + +static void gst_audiosrc_close_audio(GstAudioSrc *src) { + g_return_if_fail(src->fd >= 0); + + close(src->fd); + src->fd = -1; +} + +void gst_audiosrc_sync_parms(GstAudioSrc *audiosrc) { + audio_buf_info ospace; + + g_return_if_fail(audiosrc != NULL); + g_return_if_fail(GST_IS_AUDIOSRC(audiosrc)); + g_return_if_fail(audiosrc->fd > 0); + + ioctl(audiosrc->fd,SNDCTL_DSP_RESET,0); + + ioctl(audiosrc->fd,SNDCTL_DSP_SETFMT,&audiosrc->format); + ioctl(audiosrc->fd,SNDCTL_DSP_CHANNELS,&audiosrc->channels); + ioctl(audiosrc->fd,SNDCTL_DSP_SPEED,&audiosrc->frequency); + + ioctl(audiosrc->fd,SNDCTL_DSP_GETOSPACE,&ospace); + + g_print("setting sound card to %dKHz %d bit %s (%d bytes buffer)\n", + audiosrc->frequency,audiosrc->format, + (audiosrc->channels == 2) ? "stereo" : "mono",ospace.bytes); + +// audiosrc->meta.format = audiosrc->format; +// audiosrc->meta.channels = audiosrc->channels; +// audiosrc->meta.frequency = audiosrc->frequency; +// audiosrc->sentmeta = FALSE; +} diff --git a/gst/elements/gstaudiosrc.h b/gst/elements/gstaudiosrc.h new file mode 100644 index 0000000000..bcaedcf4a3 --- /dev/null +++ b/gst/elements/gstaudiosrc.h @@ -0,0 +1,90 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_AUDIOSRC_H__ +#define __GST_AUDIOSRC_H__ + + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_audiosrc_details; + + +#define GST_TYPE_AUDIOSRC \ + (gst_audiosrc_get_type()) +#define GST_AUDIOSRC(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_AUDIOSRC,GstAudioSrc)) +#define GST_AUDIOSRC_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIOSRC,GstAudioSrcClass)) +#define GST_IS_AUDIOSRC(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_AUDIOSRC)) +#define GST_IS_AUDIOSRC_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIOSRC))) + +typedef struct _GstAudioSrc GstAudioSrc; +typedef struct _GstAudioSrcClass GstAudioSrcClass; + +struct _GstAudioSrc { + GstSrc src; + + /* pads */ + GstPad *srcpad; + + /* sound card */ + gchar *filename; + gint fd; + + /* audio parameters */ + gint format; + gint channels; + gint frequency; + + /* blocking */ + gulong curoffset; + gulong bytes_per_read; + + gulong seq; + + MetaAudioRaw *meta; +}; + +struct _GstAudioSrcClass { + GstSrcClass parent_class; +}; + +GtkType gst_audiosrc_get_type(void); +GstElement *gst_audiosrc_new(gchar *name); + +void gst_audiosrc_push(GstSrc *src); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_AUDIOSRC_H__ */ diff --git a/gst/elements/gstdisksrc.c b/gst/elements/gstdisksrc.c new file mode 100644 index 0000000000..9c0ff78ee7 --- /dev/null +++ b/gst/elements/gstdisksrc.c @@ -0,0 +1,267 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include + + +GstElementDetails gst_disksrc_details = { + "Disk Source", + "Source/File", + "Synchronous read from a file", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* DiskSrc signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_LOCATION, + ARG_BYTESPERREAD, + ARG_OFFSET, +}; + + +static void gst_disksrc_class_init(GstDiskSrcClass *klass); +static void gst_disksrc_init(GstDiskSrc *disksrc); +static void gst_disksrc_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_disksrc_get_arg(GtkObject *object,GtkArg *arg,guint id); + +static void gst_disksrc_push(GstSrc *src); +static void gst_disksrc_push_region(GstSrc *src,gulong offset,gulong size); +static gboolean gst_disksrc_change_state(GstElement *element, + GstElementState state); + + +static GstSrcClass *parent_class = NULL; +static guint gst_disksrc_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_disksrc_get_type(void) { + static GtkType disksrc_type = 0; + + if (!disksrc_type) { + static const GtkTypeInfo disksrc_info = { + "GstDiskSrc", + sizeof(GstDiskSrc), + sizeof(GstDiskSrcClass), + (GtkClassInitFunc)gst_disksrc_class_init, + (GtkObjectInitFunc)gst_disksrc_init, + (GtkArgSetFunc)gst_disksrc_set_arg, + (GtkArgGetFunc)gst_disksrc_get_arg, + (GtkClassInitFunc)NULL, + }; + disksrc_type = gtk_type_unique(GST_TYPE_SRC,&disksrc_info); + } + return disksrc_type; +} + +static void +gst_disksrc_class_init(GstDiskSrcClass *klass) { + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + GstSrcClass *gstsrc_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + gstsrc_class = (GstSrcClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SRC); + + gtk_object_add_arg_type("GstDiskSrc::location", GTK_TYPE_STRING, + GTK_ARG_READWRITE, ARG_LOCATION); + gtk_object_add_arg_type("GstDiskSrc::bytesperread", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_BYTESPERREAD); + gtk_object_add_arg_type("GstDiskSrc::offset", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_OFFSET); + + gtkobject_class->set_arg = gst_disksrc_set_arg; + gtkobject_class->get_arg = gst_disksrc_get_arg; + + gstelement_class->change_state = gst_disksrc_change_state; + + gstsrc_class->push = gst_disksrc_push; + /* we nominally can't (won't) do async */ + gstsrc_class->push_region = NULL; +} + +static void gst_disksrc_init(GstDiskSrc *disksrc) { + disksrc->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(disksrc),disksrc->srcpad); + + disksrc->filename = NULL; + disksrc->fd = 0; + disksrc->curoffset = 0; + disksrc->bytes_per_read = 4096; + disksrc->seq = 0; +} + + +static void gst_disksrc_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstDiskSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_DISKSRC(object)); + src = GST_DISKSRC(object); + + switch(id) { + case ARG_LOCATION: + /* the element must be stopped in order to do this */ +// g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING)); + + if (src->filename) g_free(src->filename); + /* clear the filename if we get a NULL (is that possible?) */ + if (GTK_VALUE_STRING(*arg) == NULL) { + src->filename = NULL; + gst_element_set_state(GST_ELEMENT(object),~GST_STATE_COMPLETE); + /* otherwise set the new filename */ + } else { + src->filename = g_strdup(GTK_VALUE_STRING(*arg)); + gst_element_set_state(GST_ELEMENT(object),GST_STATE_COMPLETE); + } + break; + case ARG_BYTESPERREAD: + src->bytes_per_read = GTK_VALUE_INT(*arg); + break; + default: + break; + } +} + +static void gst_disksrc_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstDiskSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_DISKSRC(object)); + src = GST_DISKSRC(object); + + switch (id) { + case ARG_LOCATION: + GTK_VALUE_STRING(*arg) = src->filename; + break; + case ARG_BYTESPERREAD: + GTK_VALUE_INT(*arg) = src->bytes_per_read; + break; + case ARG_OFFSET: + GTK_VALUE_INT(*arg) = src->curoffset; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +void gst_disksrc_push(GstSrc *src) { + GstDiskSrc *disksrc; + GstBuffer *buf; + glong readbytes; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_DISKSRC(src)); + g_return_if_fail(GST_FLAG_IS_SET(src,GST_DISKSRC_OPEN)); + disksrc = GST_DISKSRC(src); + + /* create the buffer */ + // FIXME: should eventually use a bufferpool for this + buf = gst_buffer_new(); + g_return_if_fail(buf); + + /* allocate the space for the buffer data */ + GST_BUFFER_DATA(buf) = g_malloc(disksrc->bytes_per_read); + g_return_if_fail(GST_BUFFER_DATA(buf) != NULL); + + /* read it in from the file */ + readbytes = read(disksrc->fd,GST_BUFFER_DATA(buf),disksrc->bytes_per_read); + if (readbytes == 0) { + gst_src_signal_eos(GST_SRC(disksrc)); + return; + } + + /* if we didn't get as many bytes as we asked for, we're at EOF */ + if (readbytes < disksrc->bytes_per_read) + GST_BUFFER_FLAG_SET(buf,GST_BUFFER_EOS); + GST_BUFFER_OFFSET(buf) = disksrc->curoffset; + GST_BUFFER_SIZE(buf) = readbytes; + disksrc->curoffset += readbytes; + + /* we're done, push the buffer off now */ + gst_pad_push(disksrc->srcpad,buf); +} + + +/* open the file, necessary to go to RUNNING state */ +static gboolean gst_disksrc_open_file(GstDiskSrc *src) { + g_return_if_fail(!GST_FLAG_IS_SET(src,GST_DISKSRC_OPEN)); + + /* open the file */ + src->fd = open(src->filename,O_RDONLY); + if (src->fd < 0) { + perror("open()"); + gst_element_error(GST_ELEMENT(src),"opening file"); + return FALSE; + } + GST_FLAG_SET(src,GST_DISKSRC_OPEN); + return TRUE; +} + +/* close the file */ +static void gst_disksrc_close_file(GstDiskSrc *src) { + g_return_if_fail(GST_FLAG_IS_SET(src,GST_DISKSRC_OPEN)); + + /* close the file */ + close(src->fd); + + /* zero out a lot of our state */ + src->fd = 0; + src->curoffset = 0; + src->seq = 0; + + GST_FLAG_UNSET(src,GST_DISKSRC_OPEN); +} + +static gboolean gst_disksrc_change_state(GstElement *element, + GstElementState state) { + g_return_if_fail(GST_IS_DISKSRC(element)); + + switch (state) { + case GST_STATE_RUNNING: + if (!gst_disksrc_open_file(GST_DISKSRC(element))) + return FALSE; + break; + case ~GST_STATE_RUNNING: + gst_disksrc_close_file(GST_DISKSRC(element)); + break; + default: + break; + } + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + return TRUE; +} diff --git a/gst/elements/gstdisksrc.h b/gst/elements/gstdisksrc.h new file mode 100644 index 0000000000..bdf2f9e2c5 --- /dev/null +++ b/gst/elements/gstdisksrc.h @@ -0,0 +1,83 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_DISKSRC_H__ +#define __GST_DISKSRC_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_disksrc_details; + + +#define GST_TYPE_DISKSRC \ + (gst_disksrc_get_type()) +#define GST_DISKSRC(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_DISKSRC,GstDiskSrc)) +#define GST_DISKSRC_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_DISKSRC,GstDiskSrcClass)) +#define GST_IS_DISKSRC(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_DISKSRC)) +#define GST_IS_DISKSRC_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_DISKSRC))) + +// NOTE: per-element flags start with 16 for now +typedef enum { + GST_DISKSRC_OPEN = (1 << 16), +} GstDiskSrcFlags; + +typedef struct _GstDiskSrc GstDiskSrc; +typedef struct _GstDiskSrcClass GstDiskSrcClass; + +struct _GstDiskSrc { + GstSrc src; + /* pads */ + GstPad *srcpad; + + /* filename */ + gchar *filename; + /* fd */ + gint fd; + + gulong curoffset; /* current offset in file */ + gulong bytes_per_read; /* bytes per read */ + + gulong seq; /* buffer sequence number */ +}; + +struct _GstDiskSrcClass { + GstSrcClass parent_class; +}; + +GtkType gst_disksrc_get_type(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_DISKSRC_H__ */ diff --git a/gst/elements/gstelements.c b/gst/elements/gstelements.c new file mode 100644 index 0000000000..a44418d20e --- /dev/null +++ b/gst/elements/gstelements.c @@ -0,0 +1,85 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +struct _elements_entry { + gchar *name; + GtkType (*type) (void); + GstElementDetails *details; +}; + +struct _elements_entry _elements[] = { + { "asyncdisksrc", gst_asyncdisksrc_get_type, &gst_asyncdisksrc_details }, + { "audiosink", gst_audiosink_get_type, &gst_audiosink_details }, + { "audiosrc", gst_audiosrc_get_type, &gst_audiosrc_details }, + { "disksrc", gst_disksrc_get_type, &gst_disksrc_details }, + { "identity", gst_identity_get_type, &gst_identity_details }, + { "fakesink", gst_fakesink_get_type, &gst_fakesink_details }, + { "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details }, + { "fdsink", gst_fdsink_get_type, &gst_fdsink_details }, + { "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details }, + { "httpsrc", gst_httpsrc_get_type, &gst_httpsrc_details }, + { "queue", gst_queue_get_type, &gst_queue_details }, + { "sinesrc", gst_sinesrc_get_type, &gst_sinesrc_details }, + { NULL, 0 }, +}; + +GstPlugin *plugin_init(GModule *module) { + GstPlugin *plugin; + GstElementFactory *factory; + int i = 0; + + if (gst_plugin_find("gstelements") != NULL) return NULL; + + plugin = gst_plugin_new("gstelements"); + g_return_val_if_fail(plugin != NULL,NULL); + + gst_plugin_set_longname(plugin,"Standard GST Elements"); + + while (_elements[i].name) { + factory = gst_elementfactory_new(_elements[i].name, + (_elements[i].type)(), + _elements[i].details); + if (factory != NULL) { + gst_plugin_add_factory(plugin,factory); +// DEBUG("added factory '%s'\n",_elements[i].name); + } + i++; + } + + gst_info("gstelements: loaded %d standard elements\n",i); + + return plugin; +} diff --git a/gst/elements/gstesdsink.c b/gst/elements/gstesdsink.c new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gst/elements/gstesdsink.h b/gst/elements/gstesdsink.h new file mode 100644 index 0000000000..97dce1e9bf --- /dev/null +++ b/gst/elements/gstesdsink.h @@ -0,0 +1,81 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_ESDSINK_H__ +#define __GST_ESDSINK_H__ + + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GST_TYPE_ESDSINK \ + (gst_esdsink_get_type()) +#define GST_ESDSINK(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_ESDSINK,GstEsdSink)) +#define GST_ESDSINK_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_ESDSINK,GstEsdSinkClass)) +#define GST_IS_ESDSINK(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_ESDSINK)) +#define GST_IS_ESDSINK_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_ESDSINK))) + +typedef struct _GstEsdSink GstEsdSink; +typedef struct _GstEsdSinkClass GstEsdSinkClass; + +struct _GstEsdSink { + GstFilter filter; + + GstPad *sinkpad; + + /* soundcard state */ + + int fd; + gint format; + gint channels; + gint frequency; +}; + +struct _GstEsdSinkClass { + GstFilterClass parent_class; + + /* signals */ + void (*handoff) (GstElement *element,GstPad *pad); +}; + +GtkType gst_esdsink_get_type(void); +GstElement *gst_esdsink_new(gchar *name); +void gst_esdsink_chain(GstPad *pad,GstBuffer *buf); + +void gst_esdsink_sync_parms(GstEsdSink *esdsink); + +void gst_esdsink_set_format(GstEsdSink *esdsink,gint format); +void gst_esdsink_set_channels(GstEsdSink *esdsink,gint channels); +void gst_esdsink_set_frequency(GstEsdSink *esdsink,gint frequency); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_ESDSINK_H__ */ diff --git a/gst/elements/gstfakesink.c b/gst/elements/gstfakesink.c new file mode 100644 index 0000000000..661cd4cc4d --- /dev/null +++ b/gst/elements/gstfakesink.c @@ -0,0 +1,109 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + + +GstElementDetails gst_fakesink_details = { + "Fake Sink", + "Sink", + "Black hole for data", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* FakeSink signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_fakesink_class_init(GstFakeSinkClass *klass); +static void gst_fakesink_init(GstFakeSink *fakesink); + + +static GstSinkClass *parent_class = NULL; +static guint gst_fakesink_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_fakesink_get_type(void) { + static GtkType fakesink_type = 0; + + if (!fakesink_type) { + static const GtkTypeInfo fakesink_info = { + "GstFakeSink", + sizeof(GstFakeSink), + sizeof(GstFakeSinkClass), + (GtkClassInitFunc)gst_fakesink_class_init, + (GtkObjectInitFunc)gst_fakesink_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + fakesink_type = gtk_type_unique(GST_TYPE_SINK,&fakesink_info); + } + return fakesink_type; +} + +static void +gst_fakesink_class_init(GstFakeSinkClass *klass) { + GstSinkClass *gstsink_class; + + gstsink_class = (GstSinkClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SINK); +} + +static void gst_fakesink_init(GstFakeSink *fakesink) { + fakesink->sinkpad = gst_pad_new("sink",GST_PAD_SINK); + gst_element_add_pad(GST_ELEMENT(fakesink),fakesink->sinkpad); + gst_pad_set_chain_function(fakesink->sinkpad,gst_fakesink_chain); + + // we're already complete, since we don't have any args... + gst_element_set_state(GST_ELEMENT(fakesink),GST_STATE_COMPLETE); +} + +GstElement *gst_fakesink_new(gchar *name) { + GstElement *fakesink = GST_ELEMENT(gtk_type_new(GST_TYPE_FAKESINK)); + gst_element_set_name(GST_ELEMENT(fakesink),name); + return fakesink; +} + +void gst_fakesink_chain(GstPad *pad,GstBuffer *buf) { + GstFakeSink *fakesink; + + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(buf != NULL); + + fakesink = GST_FAKESINK(pad->parent); +// g_print("gst_fakesink_chain: got buffer of %d bytes in '%s'\n", +// buf->datasize,gst_element_get_name(GST_ELEMENT(fakesink))); + g_print("<"); + gst_buffer_unref(buf); +} diff --git a/gst/elements/gstfakesink.h b/gst/elements/gstfakesink.h new file mode 100644 index 0000000000..e6617fc21b --- /dev/null +++ b/gst/elements/gstfakesink.h @@ -0,0 +1,71 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_FAKESINK_H__ +#define __GST_FAKESINK_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_fakesink_details; + + +#define GST_TYPE_FAKESINK \ + (gst_fakesink_get_type()) +#define GST_FAKESINK(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_FAKESINK,GstFakeSink)) +#define GST_FAKESINK_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_FAKESINK,GstFakeSinkClass)) +#define GST_IS_FAKESINK(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_FAKESINK)) +#define GST_IS_FAKESINK_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_FAKESINK))) + +typedef struct _GstFakeSink GstFakeSink; +typedef struct _GstFakeSinkClass GstFakeSinkClass; + +struct _GstFakeSink { + GstSink sink; + + GstPad *sinkpad; +}; + +struct _GstFakeSinkClass { + GstSinkClass parent_class; +}; + +GtkType gst_fakesink_get_type(void); +GstElement *gst_fakesink_new(gchar *name); +void gst_fakesink_chain(GstPad *pad,GstBuffer *buf); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_FAKESINK_H__ */ diff --git a/gst/elements/gstfakesrc.c b/gst/elements/gstfakesrc.c new file mode 100644 index 0000000000..6251f11f22 --- /dev/null +++ b/gst/elements/gstfakesrc.c @@ -0,0 +1,112 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + + +GstElementDetails gst_fakesrc_details = { + "Fake Source", + "Source", + "Push empty (no data) buffers around", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* FakeSrc signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_fakesrc_class_init(GstFakeSrcClass *klass); +static void gst_fakesrc_init(GstFakeSrc *fakesrc); + + +static GstSrcClass *parent_class = NULL; +static guint gst_fakesrc_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_fakesrc_get_type(void) { + static GtkType fakesrc_type = 0; + + if (!fakesrc_type) { + static const GtkTypeInfo fakesrc_info = { + "GstFakeSrc", + sizeof(GstFakeSrc), + sizeof(GstFakeSrcClass), + (GtkClassInitFunc)gst_fakesrc_class_init, + (GtkObjectInitFunc)gst_fakesrc_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + fakesrc_type = gtk_type_unique(GST_TYPE_SRC,&fakesrc_info); + } + return fakesrc_type; +} + +static void +gst_fakesrc_class_init(GstFakeSrcClass *klass) { + GstSrcClass *gstsrc_class; + + gstsrc_class = (GstSrcClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SRC); + + gstsrc_class->push = gst_fakesrc_push; + gstsrc_class->push_region = NULL; +} + +static void gst_fakesrc_init(GstFakeSrc *fakesrc) { + fakesrc->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(fakesrc),fakesrc->srcpad); + + // we're already complete, since we don't have any args... + gst_element_set_state(GST_ELEMENT(fakesrc),GST_STATE_COMPLETE); +} + +GstElement *gst_fakesrc_new(gchar *name) { + GstElement *fakesrc = GST_ELEMENT(gtk_type_new(GST_TYPE_FAKESRC)); + gst_element_set_name(GST_ELEMENT(fakesrc),name); + return fakesrc; +} + +void gst_fakesrc_push(GstSrc *src) { + GstFakeSrc *fakesrc; + GstBuffer *buf; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_FAKESRC(src)); + fakesrc = GST_FAKESRC(src); + +// g_print("gst_fakesrc_push(): pushing fake buffer from '%s'\n", +// gst_element_get_name(GST_ELEMENT(fakesrc))); + g_print(">"); + buf = gst_buffer_new(); + gst_pad_push(fakesrc->srcpad,buf); +} diff --git a/gst/elements/gstfakesrc.h b/gst/elements/gstfakesrc.h new file mode 100644 index 0000000000..946e0f154c --- /dev/null +++ b/gst/elements/gstfakesrc.h @@ -0,0 +1,70 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_FAKESRC_H__ +#define __GST_FAKESRC_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_fakesrc_details; + + +#define GST_TYPE_FAKESRC \ + (gst_fakesrc_get_type()) +#define GST_FAKESRC(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_FAKESRC,GstFakeSrc)) +#define GST_FAKESRC_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_FAKESRC,GstFakeSrcClass)) +#define GST_IS_FAKESRC(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_FAKESRC)) +#define GST_IS_FAKESRC_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_FAKESRC))) + +typedef struct _GstFakeSrc GstFakeSrc; +typedef struct _GstFakeSrcClass GstFakeSrcClass; + +struct _GstFakeSrc { + GstSrc src; + + GstPad *srcpad; +}; + +struct _GstFakeSrcClass { + GstSrcClass parent_class; +}; + +GtkType gst_fakesrc_get_type(void); +GstElement *gst_fakesrc_new(gchar *name); +void gst_fakesrc_push(GstSrc *src); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_FAKESRC_H__ */ diff --git a/gst/elements/gstfdsink.c b/gst/elements/gstfdsink.c new file mode 100644 index 0000000000..136f37c0b2 --- /dev/null +++ b/gst/elements/gstfdsink.c @@ -0,0 +1,155 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + + +GstElementDetails gst_fdsink_details = { + "Filedescriptor Sink", + "Sink", + "Write data to a file descriptor", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* FdSink signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_FD +}; + + +static void gst_fdsink_class_init(GstFdSinkClass *klass); +static void gst_fdsink_init(GstFdSink *fdsink); +static void gst_fdsink_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_fdsink_get_arg(GtkObject *object,GtkArg *arg,guint id); + + +static GstSinkClass *parent_class = NULL; +static guint gst_fdsink_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_fdsink_get_type(void) { + static GtkType fdsink_type = 0; + + if (!fdsink_type) { + static const GtkTypeInfo fdsink_info = { + "GstFdSink", + sizeof(GstFdSink), + sizeof(GstFdSinkClass), + (GtkClassInitFunc)gst_fdsink_class_init, + (GtkObjectInitFunc)gst_fdsink_init, + (GtkArgSetFunc)gst_fdsink_set_arg, + (GtkArgGetFunc)gst_fdsink_get_arg, + (GtkClassInitFunc)NULL, + }; + fdsink_type = gtk_type_unique(GST_TYPE_SINK,&fdsink_info); + } + return fdsink_type; +} + +static void +gst_fdsink_class_init(GstFdSinkClass *klass) { + GtkObjectClass *gtkobject_class; + GstSinkClass *gstsink_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstsink_class = (GstSinkClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SINK); + + gtk_object_add_arg_type("GstFdSink::fd", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FD); + + gtkobject_class->set_arg = gst_fdsink_set_arg; + gtkobject_class->get_arg = gst_fdsink_get_arg; +} + +static void gst_fdsink_init(GstFdSink *fdsink) { + fdsink->sinkpad = gst_pad_new("sink",GST_PAD_SINK); + gst_element_add_pad(GST_ELEMENT(fdsink),fdsink->sinkpad); + gst_pad_set_chain_function(fdsink->sinkpad,gst_fdsink_chain); + + fdsink->fd = 1; +} + +GstElement *gst_fdsink_new(gchar *name) { + GstElement *fdsink = GST_ELEMENT(gtk_type_new(GST_TYPE_FDSINK)); + gst_element_set_name(GST_ELEMENT(fdsink),name); + return fdsink; +} + +GstElement *gst_fdsink_new_with_fd(gchar *name,gint fd) { + GstElement *fdsink = gst_fdsink_new(name); + gtk_object_set(GTK_OBJECT(fdsink),"fd",fd,NULL); + return fdsink; +} + +void gst_fdsink_chain(GstPad *pad,GstBuffer *buf) { + GstFdSink *fdsink; + + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(buf != NULL); + + fdsink = GST_FDSINK(pad->parent); + g_return_if_fail(fdsink->fd >= 0); + if (GST_BUFFER_DATA(buf)) + write(fdsink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf)); + gst_buffer_unref(buf); +} + +static void gst_fdsink_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstFdSink *fdsink; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_FDSINK(object)); + fdsink = GST_FDSINK(object); + + switch(id) { + case ARG_FD: + fdsink->fd = GTK_VALUE_INT(*arg); + break; + default: + break; + } +} + +static void gst_fdsink_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstFdSink *fdsink; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_FDSINK(object)); + fdsink = GST_FDSINK(object); + + switch(id) { + case ARG_FD: + GTK_VALUE_INT(*arg) = fdsink->fd; + break; + default: + break; + } +} diff --git a/gst/elements/gstfdsink.h b/gst/elements/gstfdsink.h new file mode 100644 index 0000000000..8a7cba37bf --- /dev/null +++ b/gst/elements/gstfdsink.h @@ -0,0 +1,74 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_FDSINK_H__ +#define __GST_FDSINK_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_fdsink_details; + + +#define GST_TYPE_FDSINK \ + (gst_fdsink_get_type()) +#define GST_FDSINK(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_FDSINK,GstFdSink)) +#define GST_FDSINK_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_FDSINK,GstFdSinkClass)) +#define GST_IS_FDSINK(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_FDSINK)) +#define GST_IS_FDSINK_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_FDSINK))) + +typedef struct _GstFdSink GstFdSink; +typedef struct _GstFdSinkClass GstFdSinkClass; + +struct _GstFdSink { + GstSink sink; + + GstPad *sinkpad; + + int fd; +}; + +struct _GstFdSinkClass { + GstSinkClass parent_class; +}; + +GtkType gst_fdsink_get_type(void); +GstElement *gst_fdsink_new(gchar *name); +GstElement *gst_fdsink_new_with_fd(gchar *name,gint fd); +void gst_fdsink_chain(GstPad *pad,GstBuffer *buf); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_FDSINK_H__ */ diff --git a/gst/elements/gstfdsrc.c b/gst/elements/gstfdsrc.c new file mode 100644 index 0000000000..f24c06e2c4 --- /dev/null +++ b/gst/elements/gstfdsrc.c @@ -0,0 +1,206 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include + + +GstElementDetails gst_fdsrc_details = { + "Disk Source", + "Source/File", + "Synchronous read from a file", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* FdSrc signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_LOCATION, + ARG_BYTESPERREAD, + ARG_OFFSET, +}; + + +static void gst_fdsrc_class_init(GstFdSrcClass *klass); +static void gst_fdsrc_init(GstFdSrc *fdsrc); +static void gst_fdsrc_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_fdsrc_get_arg(GtkObject *object,GtkArg *arg,guint id); + +static void gst_fdsrc_push(GstSrc *src); +static void gst_fdsrc_push_region(GstSrc *src,gulong offset,gulong size); + + +static GstSrcClass *parent_class = NULL; +static guint gst_fdsrc_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_fdsrc_get_type(void) { + static GtkType fdsrc_type = 0; + + if (!fdsrc_type) { + static const GtkTypeInfo fdsrc_info = { + "GstFdSrc", + sizeof(GstFdSrc), + sizeof(GstFdSrcClass), + (GtkClassInitFunc)gst_fdsrc_class_init, + (GtkObjectInitFunc)gst_fdsrc_init, + (GtkArgSetFunc)gst_fdsrc_set_arg, + (GtkArgGetFunc)gst_fdsrc_get_arg, + (GtkClassInitFunc)NULL, + }; + fdsrc_type = gtk_type_unique(GST_TYPE_SRC,&fdsrc_info); + } + return fdsrc_type; +} + +static void +gst_fdsrc_class_init(GstFdSrcClass *klass) { + GtkObjectClass *gtkobject_class; + GstSrcClass *gstsrc_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstsrc_class = (GstSrcClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SRC); + + gtk_object_add_arg_type("GstFdSrc::location", GTK_TYPE_STRING, + GTK_ARG_WRITABLE, ARG_LOCATION); + gtk_object_add_arg_type("GstFdSrc::bytesperread", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_BYTESPERREAD); + gtk_object_add_arg_type("GstFdSrc::offset", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_OFFSET); + + gtkobject_class->set_arg = gst_fdsrc_set_arg; + gtkobject_class->get_arg = gst_fdsrc_get_arg; + + gstsrc_class->push = gst_fdsrc_push; + /* we nominally can't (won't) do async */ + gstsrc_class->push_region = NULL; +} + +static void gst_fdsrc_init(GstFdSrc *fdsrc) { + fdsrc->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(fdsrc),fdsrc->srcpad); + + fdsrc->fd = 0; + fdsrc->curoffset = 0; + fdsrc->bytes_per_read = 4096; + fdsrc->seq = 0; +} + + +static void gst_fdsrc_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstFdSrc *src; + int fd; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_FDSRC(object)); + src = GST_FDSRC(object); + + switch(id) { + case ARG_LOCATION: + /* the element must be stopped in order to do this */ + g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING)); + + /* if we get a NULL, consider it to be a fd of 0 */ + if (GTK_VALUE_STRING(*arg) == NULL) { + src->fd = 0; + gst_element_set_state(GST_ELEMENT(object),~GST_STATE_COMPLETE); + /* otherwise set the new filename */ + } else { + if (sscanf(GTK_VALUE_STRING(*arg),"%d",&fd)) + src->fd = fd; + gst_element_set_state(GST_ELEMENT(object),GST_STATE_COMPLETE); + } + break; + case ARG_BYTESPERREAD: + src->bytes_per_read = GTK_VALUE_INT(*arg); + break; + default: + break; + } +} + +static void gst_fdsrc_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstFdSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_FDSRC(object)); + src = GST_FDSRC(object); + + switch (id) { + case ARG_BYTESPERREAD: + GTK_VALUE_INT(*arg) = src->bytes_per_read; + break; + case ARG_OFFSET: + GTK_VALUE_INT(*arg) = src->curoffset; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +void gst_fdsrc_push(GstSrc *src) { + GstFdSrc *fdsrc; + GstBuffer *buf; + glong readbytes; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_FDSRC(src)); + fdsrc = GST_FDSRC(src); + + /* create the buffer */ + // FIXME: should eventually use a bufferpool for this + buf = gst_buffer_new(); + g_return_if_fail(buf); + + /* allocate the space for the buffer data */ + GST_BUFFER_DATA(buf) = g_malloc(fdsrc->bytes_per_read); + g_return_if_fail(GST_BUFFER_DATA(buf) != NULL); + + /* read it in from the file */ + readbytes = read(fdsrc->fd,GST_BUFFER_DATA(buf),fdsrc->bytes_per_read); + if (readbytes == 0) { + gst_src_signal_eos(GST_SRC(fdsrc)); + return; + } + + /* if we didn't get as many bytes as we asked for, we're at EOF */ + if (readbytes < fdsrc->bytes_per_read) { + // FIXME: set the buffer's EOF bit here + } + GST_BUFFER_OFFSET(buf) = fdsrc->curoffset; + GST_BUFFER_SIZE(buf) = readbytes; + fdsrc->curoffset += readbytes; + + /* we're done, push the buffer off now */ + gst_pad_push(fdsrc->srcpad,buf); +} diff --git a/gst/elements/gstfdsrc.h b/gst/elements/gstfdsrc.h new file mode 100644 index 0000000000..1b85e065fb --- /dev/null +++ b/gst/elements/gstfdsrc.h @@ -0,0 +1,77 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_FDSRC_H__ +#define __GST_FDSRC_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_fdsrc_details; + + +#define GST_TYPE_FDSRC \ + (gst_fdsrc_get_type()) +#define GST_FDSRC(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_FDSRC,GstFdSrc)) +#define GST_FDSRC_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_FDSRC,GstFdSrcClass)) +#define GST_IS_FDSRC(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_FDSRC)) +#define GST_IS_FDSRC_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_FDSRC))) + + +typedef struct _GstFdSrc GstFdSrc; +typedef struct _GstFdSrcClass GstFdSrcClass; + +struct _GstFdSrc { + GstSrc src; + /* pads */ + GstPad *srcpad; + + /* fd */ + gint fd; + + gulong curoffset; /* current offset in file */ + gulong bytes_per_read; /* bytes per read */ + + gulong seq; /* buffer sequence number */ +}; + +struct _GstFdSrcClass { + GstSrcClass parent_class; +}; + +GtkType gst_fdsrc_get_type(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_FDSRC_H__ */ diff --git a/gst/elements/gsthttpsrc.c b/gst/elements/gsthttpsrc.c new file mode 100644 index 0000000000..3b378ed620 --- /dev/null +++ b/gst/elements/gsthttpsrc.c @@ -0,0 +1,258 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include + + +GstElementDetails gst_httpsrc_details = { + "HTTP Source", + "Source/Network", + "Read data from an HTTP stream", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +static void gst_httpsrc_push(GstSrc *src); +static gboolean gst_httpsrc_open_url(GstHttpSrc *src); +static void gst_httpsrc_close_url(GstHttpSrc *src); +static gboolean gst_httpsrc_change_state(GstElement *element, + GstElementState state); + + +/* HttpSrc signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_LOCATION, + ARG_BYTESPERREAD, + ARG_OFFSET +}; + + +static void gst_httpsrc_class_init(GstHttpSrcClass *klass); +static void gst_httpsrc_init(GstHttpSrc *httpsrc); +static void gst_httpsrc_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_httpsrc_get_arg(GtkObject *object,GtkArg *arg,guint id); + + +static GstSrcClass *parent_class = NULL; +static guint gst_httpsrc_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_httpsrc_get_type(void) { + static GtkType httpsrc_type = 0; + + if (!httpsrc_type) { + static const GtkTypeInfo httpsrc_info = { + "GstHttpSrc", + sizeof(GstHttpSrc), + sizeof(GstHttpSrcClass), + (GtkClassInitFunc)gst_httpsrc_class_init, + (GtkObjectInitFunc)gst_httpsrc_init, + (GtkArgSetFunc)gst_httpsrc_set_arg, + (GtkArgGetFunc)gst_httpsrc_get_arg, + (GtkClassInitFunc)NULL, + }; + httpsrc_type = gtk_type_unique(GST_TYPE_SRC,&httpsrc_info); + } + return httpsrc_type; +} + +static void +gst_httpsrc_class_init(GstHttpSrcClass *klass) { + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + GstSrcClass *gstsrc_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + gstsrc_class = (GstSrcClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SRC); + + + gtk_object_add_arg_type("GstHttpSrc::location", GTK_TYPE_STRING, + GTK_ARG_READWRITE, ARG_LOCATION); + gtk_object_add_arg_type("GstHttpSrc::bytesperread", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_BYTESPERREAD); + + gtkobject_class->set_arg = gst_httpsrc_set_arg; + gtkobject_class->get_arg = gst_httpsrc_get_arg; + + gstelement_class->change_state = gst_httpsrc_change_state; + + gstsrc_class->push = gst_httpsrc_push; + gstsrc_class->push_region = NULL; +} + +static void gst_httpsrc_init(GstHttpSrc *httpsrc) { + httpsrc->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(httpsrc),httpsrc->srcpad); + + httpsrc->url = NULL; + httpsrc->request = NULL; + httpsrc->fd = 0; + httpsrc->curoffset = 0; + httpsrc->bytes_per_read = 4096; +} + +static void gst_httpsrc_push(GstSrc *src) { + GstHttpSrc *httpsrc; + GstBuffer *buf; + glong readbytes; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_HTTPSRC(src)); +// g_return_if_fail(GST_FLAG_IS_SET(src,GST_)); + httpsrc = GST_HTTPSRC(src); + + buf = gst_buffer_new(); + GST_BUFFER_DATA(buf) = (gpointer)malloc(httpsrc->bytes_per_read); + readbytes = read(httpsrc->fd,GST_BUFFER_DATA(buf),httpsrc->bytes_per_read); + if (readbytes == 0) { + gst_src_signal_eos(GST_SRC(httpsrc)); + return; + } + + if (readbytes < httpsrc->bytes_per_read) { + // FIXME: set the buffer's EOF bit here + } + GST_BUFFER_OFFSET(buf) = httpsrc->curoffset; + GST_BUFFER_SIZE(buf) = readbytes; + httpsrc->curoffset += readbytes; + + gst_pad_push(httpsrc->srcpad,buf); +} + +static gboolean gst_httpsrc_open_url(GstHttpSrc *httpsrc) { + gint status; + + g_return_if_fail(httpsrc != NULL); + g_return_if_fail(GST_IS_HTTPSRC(httpsrc)); + g_return_if_fail(httpsrc->url != NULL); + + httpsrc->request = ghttp_request_new(); + ghttp_set_uri(httpsrc->request,httpsrc->url); + ghttp_set_sync(httpsrc->request,ghttp_async); + ghttp_set_header(httpsrc->request,"User-Agent","GstHttpSrc"); + ghttp_prepare(httpsrc->request); + + /* process everything up to the actual data stream */ + /* FIXME: should be in preroll, but hey */ + status = 0; + while ((ghttp_get_status(httpsrc->request).proc != ghttp_proc_response) + && (status >= 0)) { + status = ghttp_process(httpsrc->request); + } + + /* get the fd so we can read data ourselves */ + httpsrc->fd = ghttp_get_socket(httpsrc->request); + return TRUE; +} + +/* unmap and close the file */ +static void gst_httpsrc_close_url(GstHttpSrc *src) { + g_return_if_fail(src->fd > 0); + + close(src->fd); + src->fd = 0; +} + +static void gst_httpsrc_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstHttpSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_HTTPSRC(object)); + src = GST_HTTPSRC(object); + + switch(id) { + case ARG_LOCATION: + /* the element must be stopped in order to do this */ + g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING)); + + if (src->url) g_free(src->url); + /* clear the url if we get a NULL (is that possible?) */ + if (GTK_VALUE_STRING(*arg) == NULL) { + src->url = NULL; + gst_element_set_state(GST_ELEMENT(object),~GST_STATE_COMPLETE); + /* otherwise set the new url */ + } else { + src->url = g_strdup(GTK_VALUE_STRING(*arg)); + gst_element_set_state(GST_ELEMENT(object),GST_STATE_COMPLETE); + } + break; + case ARG_BYTESPERREAD: + src->bytes_per_read = GTK_VALUE_INT(*arg); + break; + default: + break; + } +} + +static void gst_httpsrc_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstHttpSrc *httpsrc; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_HTTPSRC(object)); + httpsrc = GST_HTTPSRC(object); + + switch (id) { + case ARG_LOCATION: + GTK_VALUE_STRING(*arg) = httpsrc->url; + break; + case ARG_BYTESPERREAD: + GTK_VALUE_INT(*arg) = httpsrc->bytes_per_read; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static gboolean gst_httpsrc_change_state(GstElement *element, + GstElementState state) { + g_return_if_fail(GST_IS_HTTPSRC(element)); + + switch (state) { + case GST_STATE_RUNNING: + if (!gst_httpsrc_open_url(GST_HTTPSRC(element))) + return FALSE; + break; + case ~GST_STATE_RUNNING: + gst_httpsrc_close_url(GST_HTTPSRC(element)); + break; + default: + break; + } + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + return TRUE; +} + diff --git a/gst/elements/gsthttpsrc.h b/gst/elements/gsthttpsrc.h new file mode 100644 index 0000000000..ae55f293f2 --- /dev/null +++ b/gst/elements/gsthttpsrc.h @@ -0,0 +1,77 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_HTTPSRC_H__ +#define __GST_HTTPSRC_H__ + + +#include +#include + +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_httpsrc_details; + + +#define GST_TYPE_HTTPSRC \ + (gst_httpsrc_get_type()) +#define GST_HTTPSRC(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_HTTPSRC,GstHttpSrc)) +#define GST_HTTPSRC_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_HTTPSRC,GstHttpSrcClass)) +#define GST_IS_HTTPSRC(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_HTTPSRC)) +#define GST_IS_HTTPSRC_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_HTTPSRC))) + +typedef struct _GstHttpSrc GstHttpSrc; +typedef struct _GstHttpSrcClass GstHttpSrcClass; + +struct _GstHttpSrc { + GstSrc src; + /* pads */ + GstPad *srcpad; + + gchar *url; + ghttp_request *request; + int fd; + + gulong curoffset; /* current offset in file */ + gulong bytes_per_read; /* bytes per read */ +}; + +struct _GstHttpSrcClass { + GstSrcClass parent_class; +}; + +GtkType gst_httpsrc_get_type(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_HTTPSRC_H__ */ diff --git a/gst/elements/gstidentity.c b/gst/elements/gstidentity.c new file mode 100644 index 0000000000..4896f5de88 --- /dev/null +++ b/gst/elements/gstidentity.c @@ -0,0 +1,152 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + + +GstElementDetails gst_identity_details = { + "Identity", + "Filter", + "Pass data without modification", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* Identity signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_CONTROL +}; + + +static void gst_identity_class_init(GstIdentityClass *klass); +static void gst_identity_init(GstIdentity *identity); +static void gst_identity_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_identity_get_arg(GtkObject *object,GtkArg *arg,guint id); + + +static GstFilterClass *parent_class = NULL; +static guint gst_identity_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_identity_get_type(void) { + static GtkType identity_type = 0; + + if (!identity_type) { + static const GtkTypeInfo identity_info = { + "GstIdentity", + sizeof(GstIdentity), + sizeof(GstIdentityClass), + (GtkClassInitFunc)gst_identity_class_init, + (GtkObjectInitFunc)gst_identity_init, + (GtkArgSetFunc)gst_identity_set_arg, + (GtkArgGetFunc)gst_identity_get_arg, + (GtkClassInitFunc)NULL, + }; + identity_type = gtk_type_unique(GST_TYPE_FILTER,&identity_info); + } + return identity_type; +} + +static void gst_identity_class_init(GstIdentityClass *klass) { + GtkObjectClass *gtkobject_class; + GstFilterClass *gstfilter_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstfilter_class = (GstFilterClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_FILTER); + + gtk_object_add_arg_type("GstIdentity::control", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_CONTROL); + + gtkobject_class->set_arg = gst_identity_set_arg; + gtkobject_class->get_arg = gst_identity_get_arg; +} + +static void gst_identity_init(GstIdentity *identity) { + identity->sinkpad = gst_pad_new("sink",GST_PAD_SINK); + gst_element_add_pad(GST_ELEMENT(identity),identity->sinkpad); + gst_pad_set_chain_function(identity->sinkpad,gst_identity_chain); + identity->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(identity),identity->srcpad); + + identity->control = 0; +} + +GstElement *gst_identity_new(gchar *name) { + GstElement *identity = GST_ELEMENT(gtk_type_new(GST_TYPE_IDENTITY)); + gst_element_set_name(GST_ELEMENT(identity),name); + return identity; +} + +void gst_identity_chain(GstPad *pad,GstBuffer *buf) { + GstIdentity *identity; + + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(buf != NULL); + + identity = GST_IDENTITY(pad->parent); +// g_print("gst_identity_chain: got buffer in '%s'\n", +// gst_element_get_name(GST_ELEMENT(identity))); + g_print("i"); + gst_pad_push(identity->srcpad,buf); +} + +static void gst_identity_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstIdentity *identity; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_IDENTITY(object)); + identity = GST_IDENTITY(object); + + switch(id) { + case ARG_CONTROL: + identity->control = GTK_VALUE_INT(*arg); + break; + default: + break; + } +} + +static void gst_identity_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstIdentity *identity; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_IDENTITY(object)); + identity = GST_IDENTITY(object); + + switch (id) { + case ARG_CONTROL: + GTK_VALUE_INT(*arg) = identity->control; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} diff --git a/gst/elements/gstidentity.h b/gst/elements/gstidentity.h new file mode 100644 index 0000000000..f186a49847 --- /dev/null +++ b/gst/elements/gstidentity.h @@ -0,0 +1,74 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_IDENTITY_H__ +#define __GST_IDENTITY_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_identity_details; + + +#define GST_TYPE_IDENTITY \ + (gst_identity_get_type()) +#define GST_IDENTITY(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_IDENTITY,GstIdentity)) +#define GST_IDENTITY_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_IDENTITY,GstIdentityClass)) +#define GST_IS_IDENTITY(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_IDENTITY)) +#define GST_IS_IDENTITY_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_IDENTITY))) + +typedef struct _GstIdentity GstIdentity; +typedef struct _GstIdentityClass GstIdentityClass; + +struct _GstIdentity { + GstFilter filter; + + GstPad *sinkpad; + GstPad *srcpad; + + gint control; +}; + +struct _GstIdentityClass { + GstFilterClass parent_class; +}; + +GtkType gst_identity_get_type(void); +GstElement *gst_identity_new(gchar *name); +void gst_identity_chain(GstPad *pad,GstBuffer *buf); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_IDENTITY_H__ */ diff --git a/gst/elements/gstqueue.c b/gst/elements/gstqueue.c new file mode 100644 index 0000000000..2abf235a0d --- /dev/null +++ b/gst/elements/gstqueue.c @@ -0,0 +1,216 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + + +GstElementDetails gst_queue_details = { + "Queue", + "Connection", + "Simple data queue", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* Queue signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_LEVEL, +}; + + +static void gst_queue_class_init(GstQueueClass *klass); +static void gst_queue_init(GstQueue *queue); +static void gst_queue_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_queue_get_arg(GtkObject *object,GtkArg *arg,guint id); + + +static GstConnectionClass *parent_class = NULL; +static guint gst_queue_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_queue_get_type(void) { + static GtkType queue_type = 0; + + if (!queue_type) { + static const GtkTypeInfo queue_info = { + "GstQueue", + sizeof(GstQueue), + sizeof(GstQueueClass), + (GtkClassInitFunc)gst_queue_class_init, + (GtkObjectInitFunc)gst_queue_init, + (GtkArgSetFunc)gst_queue_set_arg, + (GtkArgGetFunc)gst_queue_get_arg, + (GtkClassInitFunc)NULL, + }; + queue_type = gtk_type_unique(GST_TYPE_CONNECTION,&queue_info); + } + return queue_type; +} + +static void gst_queue_class_init(GstQueueClass *klass) { + GtkObjectClass *gtkobject_class; + GstConnectionClass *gstconnection_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstconnection_class = (GstConnectionClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_CONNECTION); + + gtk_object_add_arg_type("GstQueue::level", GTK_TYPE_INT, + GTK_ARG_READABLE, ARG_LEVEL); + + gstconnection_class->push = gst_queue_push; + + gtkobject_class->set_arg = gst_queue_set_arg; + gtkobject_class->get_arg = gst_queue_get_arg; +} + +static void gst_queue_init(GstQueue *queue) { + queue->sinkpad = gst_pad_new("sink",GST_PAD_SINK); + gst_element_add_pad(GST_ELEMENT(queue),queue->sinkpad); + gst_pad_set_chain_function(queue->sinkpad,gst_queue_chain); + queue->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(queue),queue->srcpad); + + queue->queue = NULL; + queue->tail = NULL; + queue->level_buffers = 0; + queue->level_bytes = 0; + queue->size_buffers = 0; + queue->size_bytes = 0; + + queue->waiterlock = g_mutex_new(); + queue->waitercond = g_cond_new(); +} + +GstElement *gst_queue_new(gchar *name) { + GstElement *queue = GST_ELEMENT(gtk_type_new(GST_TYPE_QUEUE)); + gst_element_set_name(GST_ELEMENT(queue),name); + return queue; +} + +void gst_queue_chain(GstPad *pad,GstBuffer *buf) { + GstQueue *queue; + gboolean tosignal = FALSE; + + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(buf != NULL); + + queue = GST_QUEUE(pad->parent); + + /* we have to lock the queue since we span threads */ + GST_LOCK(queue); + + /* put the buffer on the head of the list */ + /* if the queue is NULL, start a new list and make this the tail */ + if (!queue->queue) { + queue->queue = g_list_prepend(queue->queue,buf); +// queue->tail = queue->queue; + /* otherwise append to the end of the list */ + } else { +// queue->tail = g_list_append(queue->tail,buf); +// queue->tail = g_list_next(queue->tail); + queue->queue = g_list_append(queue->queue,buf); + } +// g_print("+"); + + /* if we were empty, but aren't any more, signal a condition */ + tosignal = (queue->level_buffers++ == 0); + + /* we can unlock now */ + GST_UNLOCK(queue); + + if (tosignal) { + g_mutex_lock(queue->waiterlock); + g_cond_signal(queue->waitercond); + g_mutex_unlock(queue->waiterlock); +// g_print(">"); + } +} + +void gst_queue_push(GstConnection *connection) { + GstQueue *queue = GST_QUEUE(connection); + GstBuffer *buf = NULL; + GList *front; + + /* have to lock for thread-safety */ + GST_LOCK(queue); + + if (!queue->level_buffers) { + GST_UNLOCK(queue); + while (!queue->level_buffers) { + g_mutex_lock(queue->waiterlock); +// g_print("0"); + g_cond_wait(queue->waitercond,queue->waiterlock); + g_mutex_unlock(queue->waiterlock); + } + GST_LOCK(queue); + } + + front = queue->queue; + buf = (GstBuffer *)(front->data); + queue->queue = g_list_remove_link(queue->queue,front); + gst_pad_push(queue->srcpad,buf); + queue->level_buffers--; +// g_print("-"); + + /* unlock now */ + GST_UNLOCK(queue); +} + + +static void gst_queue_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstQueue *queue; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_QUEUE(object)); + queue = GST_QUEUE(object); + + switch(id) { + default: + break; + } +} + +static void gst_queue_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstQueue *queue; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_QUEUE(object)); + queue = GST_QUEUE(object); + + switch (id) { + case ARG_LEVEL: + GTK_VALUE_INT(*arg) = queue->level_buffers; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} diff --git a/gst/elements/gstqueue.h b/gst/elements/gstqueue.h new file mode 100644 index 0000000000..5ce8d6f57b --- /dev/null +++ b/gst/elements/gstqueue.h @@ -0,0 +1,84 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_QUEUE_H__ +#define __GST_QUEUE_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_queue_details; + + +#define GST_TYPE_QUEUE \ + (gst_queue_get_type()) +#define GST_QUEUE(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_QUEUE,GstQueue)) +#define GST_QUEUE_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_QUEUE,GstQueueClass)) +#define GST_IS_QUEUE(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_QUEUE)) +#define GST_IS_QUEUE_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_QUEUE))) + +typedef struct _GstQueue GstQueue; +typedef struct _GstQueueClass GstQueueClass; + +struct _GstQueue { + GstConnection Connection; + + GstPad *sinkpad; + GstPad *srcpad; + + /* the queue of buffers we're keeping our grubby hands on */ + GList *queue; + GList *tail; /* have to keep track of this myself */ + + gint level_buffers; /* number of buffers queued here */ + gint level_bytes; /* number of bytes queued here */ + gint size_buffers; /* size of queue in buffers */ + gint size_bytes; /* size of queue in bytes */ + + GMutex *waiterlock; /* used when the queue is empty */ + GCond *waitercond; +}; + +struct _GstQueueClass { + GstConnectionClass parent_class; +}; + +GtkType gst_queue_get_type(void); +GstElement *gst_queue_new(gchar *name); +void gst_queue_chain(GstPad *pad,GstBuffer *buf); +void gst_queue_push(GstConnection *connection); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_QUEUE_H__ */ diff --git a/gst/elements/gstsinesrc.c b/gst/elements/gstsinesrc.c new file mode 100644 index 0000000000..ede6f38edb --- /dev/null +++ b/gst/elements/gstsinesrc.c @@ -0,0 +1,269 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +#include + + +GstElementDetails gst_sinesrc_details = { + "Sine-wave src", + "Source/Audio", + "Create a sine wave of a given frequency and volume", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* SineSrc signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_VOLUME, + ARG_FREQ, + ARG_FORMAT, + ARG_CHANNELS, + ARG_FREQUENCY, +}; + + +static void gst_sinesrc_class_init(GstSineSrcClass *klass); +static void gst_sinesrc_init(GstSineSrc *sinesrc); +static void gst_sinesrc_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_sinesrc_get_arg(GtkObject *object,GtkArg *arg,guint id); +//static gboolean gst_sinesrc_change_state(GstElement *element, +// GstElementState state); +static void gst_sinesrc_close_audio(GstSineSrc *src); +static gboolean gst_sinesrc_open_audio(GstSineSrc *src); +void gst_sinesrc_sync_parms(GstSineSrc *sinesrc); + + +static GstSrcClass *parent_class = NULL; +static guint gst_sinesrc_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_sinesrc_get_type(void) { + static GtkType sinesrc_type = 0; + + if (!sinesrc_type) { + static const GtkTypeInfo sinesrc_info = { + "GstSineSrc", + sizeof(GstSineSrc), + sizeof(GstSineSrcClass), + (GtkClassInitFunc)gst_sinesrc_class_init, + (GtkObjectInitFunc)gst_sinesrc_init, + (GtkArgSetFunc)gst_sinesrc_set_arg, + (GtkArgGetFunc)gst_sinesrc_get_arg, + (GtkClassInitFunc)NULL, + }; + sinesrc_type = gtk_type_unique(GST_TYPE_SRC,&sinesrc_info); + } + return sinesrc_type; +} + +static void +gst_sinesrc_class_init(GstSineSrcClass *klass) { + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + GstSrcClass *gstsrc_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + gstsrc_class = (GstSrcClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SRC); + + gtk_object_add_arg_type("GstSineSrc::volume", GTK_TYPE_DOUBLE, + GTK_ARG_READWRITE, ARG_VOLUME); + gtk_object_add_arg_type("GstSineSrc::freq", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FREQ); + gtk_object_add_arg_type("GstSineSrc::format", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FORMAT); + gtk_object_add_arg_type("GstSineSrc::channels", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_CHANNELS); + gtk_object_add_arg_type("GstSineSrc::frequency", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FREQUENCY); + + gtkobject_class->set_arg = gst_sinesrc_set_arg; + gtkobject_class->get_arg = gst_sinesrc_get_arg; + +// gstelement_class->change_state = gst_sinesrc_change_state; + + gstsrc_class->push = gst_sinesrc_push; +} + +static void gst_sinesrc_init(GstSineSrc *sinesrc) { + sinesrc->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(sinesrc),sinesrc->srcpad); + + sinesrc->volume = 1.0; + sinesrc->freq = 512; + + sinesrc->format = AFMT_S16_LE; + sinesrc->channels = 2; + sinesrc->frequency = 44100; + + sinesrc->seq = 0; + + sinesrc->sentmeta = FALSE; +} + +GstElement *gst_sinesrc_new(gchar *name) { + GstElement *sinesrc = GST_ELEMENT(gtk_type_new(GST_TYPE_SINESRC)); + gst_element_set_name(GST_ELEMENT(sinesrc),name); + return sinesrc; +} + +GstElement *gst_sinesrc_new_with_fd(gchar *name,gchar *filename) { + GstElement *sinesrc = gst_sinesrc_new(name); + gtk_object_set(GTK_OBJECT(sinesrc),"location",filename,NULL); + return sinesrc; +} + +void gst_sinesrc_push(GstSrc *src) { + GstSineSrc *sinesrc; + GstBuffer *buf; + gint16 *samples; + gint i; + gint volume; + gdouble val; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_SINESRC(src)); + sinesrc = GST_SINESRC(src); + + buf = gst_buffer_new(); + g_return_if_fail(buf); + GST_BUFFER_DATA(buf) = (gpointer)malloc(4096); + samples = (gint16*)GST_BUFFER_DATA(buf); + GST_BUFFER_DATA(buf) = 4096; + + volume = 65535 * sinesrc->volume; + for (i=0;i<1024;i++) { + val = sin((gdouble)i/sinesrc->frequency); + samples[i] = val * volume; + samples[i+1] = samples[i]; + } + + if (!sinesrc->sentmeta) { + MetaAudioRaw *newmeta = g_new(MetaAudioRaw,1); + memcpy(newmeta,&sinesrc->meta,sizeof(MetaAudioRaw)); + gst_buffer_add_meta(buf,GST_META(newmeta)); + sinesrc->sentmeta = TRUE; + } + + gst_pad_push(sinesrc->srcpad,buf); + g_print(">"); +} + +static void gst_sinesrc_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstSineSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_SINESRC(object)); + src = GST_SINESRC(object); + + switch (id) { + case ARG_VOLUME: + src->volume = GTK_VALUE_DOUBLE(*arg); + break; + case ARG_FREQ: + src->freq = GTK_VALUE_INT(*arg); + break; + case ARG_FORMAT: + src->format = GTK_VALUE_INT(*arg); + break; + case ARG_CHANNELS: + src->channels = GTK_VALUE_INT(*arg); + break; + case ARG_FREQUENCY: + src->frequency = GTK_VALUE_INT(*arg); + break; + default: + break; + } +} + +static void gst_sinesrc_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstSineSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_SINESRC(object)); + src = GST_SINESRC(object); + + switch (id) { + case ARG_VOLUME: + GTK_VALUE_DOUBLE(*arg) = src->volume; + break; + case ARG_FREQ: + GTK_VALUE_INT(*arg) = src->freq; + break; + case ARG_FORMAT: + GTK_VALUE_INT(*arg) = src->format; + break; + case ARG_CHANNELS: + GTK_VALUE_INT(*arg) = src->channels; + break; + case ARG_FREQUENCY: + GTK_VALUE_INT(*arg) = src->frequency; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +/* +static gboolean gst_sinesrc_change_state(GstElement *element, + GstElementState state) { + g_return_if_fail(GST_IS_SINESRC(element)); + + switch (state) { + case GST_STATE_RUNNING: + if (!gst_sinesrc_open_audio(GST_SINESRC(element))) + return FALSE; + break; + case ~GST_STATE_RUNNING: + gst_sinesrc_close_audio(GST_SINESRC(element)); + break; + default: + break; + } + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + return TRUE; +} +*/ + +void gst_sinesrc_sync_parms(GstSineSrc *sinesrc) { + sinesrc->meta.format = sinesrc->format; + sinesrc->meta.channels = sinesrc->channels; + sinesrc->meta.frequency = sinesrc->frequency; + sinesrc->sentmeta = FALSE; +} diff --git a/gst/elements/gstsinesrc.h b/gst/elements/gstsinesrc.h new file mode 100644 index 0000000000..9964ff553f --- /dev/null +++ b/gst/elements/gstsinesrc.h @@ -0,0 +1,87 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_SINESRC_H__ +#define __GST_SINESRC_H__ + + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_sinesrc_details; + + +#define GST_TYPE_SINESRC \ + (gst_sinesrc_get_type()) +#define GST_SINESRC(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_SINESRC,GstSineSrc)) +#define GST_SINESRC_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_SINESRC,GstSineSrcClass)) +#define GST_IS_SINESRC(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_SINESRC)) +#define GST_IS_SINESRC_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_SINESRC))) + +typedef struct _GstSineSrc GstSineSrc; +typedef struct _GstSineSrcClass GstSineSrcClass; + +struct _GstSineSrc { + GstSrc src; + + /* pads */ + GstPad *srcpad; + + /* parameters */ + gdouble volume; + gint freq; + + /* audio parameters */ + gint format; + gint channels; + gint frequency; + + gulong seq; + + MetaAudioRaw meta; + gboolean sentmeta; +}; + +struct _GstSineSrcClass { + GstSrcClass parent_class; +}; + +GtkType gst_sinesrc_get_type(void); +GstElement *gst_sinesrc_new(gchar *name); + +void gst_sinesrc_push(GstSrc *src); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_SINESRC_H__ */ diff --git a/gst/gst.c b/gst/gst.c new file mode 100644 index 0000000000..3872136da9 --- /dev/null +++ b/gst/gst.c @@ -0,0 +1,60 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +extern gint _gst_trace_on; + +/** + * gst_init: + * @argc: pointer to application's argc + * @argv: pointer to application's argv + * + * Initializes the GStreamer system, setting up internal lists and loading + * standard plugins. + */ +void gst_init(int *argc,char **argv[]) { + GstTrace *gst_trace; + GstElementFactory *factory; + + gtk_init(argc,argv); + + if (!g_thread_supported()) g_thread_init (NULL); + + _gst_type_initialize(); + _gst_plugin_initialize(); + _gst_buffer_initialize(); + + /* register some standard builtin types */ + gst_elementfactory_register(gst_elementfactory_new( + "bin",gst_bin_get_type(),&gst_bin_details)); + gst_elementfactory_register(gst_elementfactory_new( + "pipeline",gst_pipeline_get_type(),&gst_pipeline_details)); + gst_elementfactory_register(gst_elementfactory_new( + "thread",gst_thread_get_type(),&gst_thread_details)); + + gst_plugin_load("libgsttypes.so"); + gst_plugin_load("libgstelements.so"); + + _gst_trace_on = 0; + if (_gst_trace_on) { + gst_trace = gst_trace_new("gst.trace",1024); + gst_trace_set_default(gst_trace); + } +} diff --git a/gst/gst.h b/gst/gst.h new file mode 100644 index 0000000000..d2e9669b3e --- /dev/null +++ b/gst/gst.h @@ -0,0 +1,60 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_H__ +#define __GST_H__ + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* initialize GST */ +void gst_init(int *argc,char **argv[]); + +/* debugging */ +#ifndef DEBUG +#ifdef DEBUG_ENABLED +#define DEBUG(format,args...) g_print("DEBUG: " format, ##args) +#else +#define DEBUG(format,args...) +#endif +#endif + +#endif /* __GST_H__ */ diff --git a/gst/gstbin.c b/gst/gstbin.c new file mode 100644 index 0000000000..0b7fe91bbd --- /dev/null +++ b/gst/gstbin.c @@ -0,0 +1,449 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +GstElementDetails gst_bin_details = { + "Generic bin", + "Bin", + "Simple container object", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +void gst_bin_real_destroy(GtkObject *object); + +static gboolean gst_bin_change_state(GstElement *element, + GstElementState state); +static gboolean gst_bin_change_state_type(GstBin *bin, + GstElementState state, + GtkType type); +static gboolean gst_bin_change_state_norecurse(GstElement *element, + GstElementState state); + +static void gst_bin_create_plan_func(GstBin *bin); +static void gst_bin_iterate_func(GstBin *bin); + +static xmlNodePtr gst_bin_save_thyself(GstElement *element,xmlNodePtr parent); + +/* Bin signals and args */ +enum { + OBJECT_ADDED, + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_bin_class_init(GstBinClass *klass); +static void gst_bin_init(GstBin *bin); + + +static GstElementClass *parent_class = NULL; +static guint gst_bin_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_bin_get_type(void) { + static GtkType bin_type = 0; + + if (!bin_type) { + static const GtkTypeInfo bin_info = { + "GstBin", + sizeof(GstBin), + sizeof(GstBinClass), + (GtkClassInitFunc)gst_bin_class_init, + (GtkObjectInitFunc)gst_bin_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + bin_type = gtk_type_unique(GST_TYPE_ELEMENT,&bin_info); + } + return bin_type; +} + +static void +gst_bin_class_init(GstBinClass *klass) { + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_ELEMENT); + + gst_bin_signals[OBJECT_ADDED] = + gtk_signal_new("object_added",GTK_RUN_FIRST,gtkobject_class->type, + GTK_SIGNAL_OFFSET(GstBinClass,object_added), + gtk_marshal_NONE__POINTER,GTK_TYPE_NONE,1, + GTK_TYPE_POINTER); + gtk_object_class_add_signals(gtkobject_class,gst_bin_signals,LAST_SIGNAL); + + klass->change_state_type = gst_bin_change_state_type; + klass->create_plan = gst_bin_create_plan_func; + klass->iterate = gst_bin_iterate_func; + + gstelement_class->change_state = gst_bin_change_state; + gstelement_class->save_thyself = gst_bin_save_thyself; + + gtkobject_class->destroy = gst_bin_real_destroy; +} + +static void gst_bin_init(GstBin *bin) { + bin->numchildren = 0; + bin->children = NULL; +} + +/** + * gst_bin_new: + * @name: name of new bin + * + * Create a new bin with given name. + * + * Returns: new bin + */ +GstElement *gst_bin_new(gchar *name) { + GstElement *bin = GST_ELEMENT(gtk_type_new(GST_TYPE_BIN)); + gst_element_set_name(GST_ELEMENT(bin),name); + return bin; +} + +/** + * gst_bin_add: + * @bin: #GstBin to add element to + * @element: #GstElement to add to bin + * + * Add the given element to the bin. Set the elements parent, and thus + * add a reference. + */ +void gst_bin_add(GstBin *bin,GstElement *element) { + g_return_if_fail(bin != NULL); + g_return_if_fail(GST_IS_BIN(bin)); + g_return_if_fail(element != NULL); + g_return_if_fail(GST_IS_ELEMENT(element)); + + bin->children = g_list_append(bin->children,element); + bin->numchildren++; + gst_object_set_parent(GST_OBJECT(element),GST_OBJECT(bin)); + + if (GST_STATE_IS_SET(element,GST_STATE_COMPLETE)) { + if (!GST_STATE_IS_SET(bin,GST_STATE_COMPLETE)) + gst_bin_change_state_norecurse(GST_ELEMENT(bin),GST_STATE_COMPLETE); + } else + gst_bin_change_state_norecurse(GST_ELEMENT(bin),~GST_STATE_COMPLETE); + + gtk_signal_emit(GTK_OBJECT(bin),gst_bin_signals[OBJECT_ADDED],element); +} + +/** + * gst_bin_remove: + * @bin: #Gstbin to remove element from + * @element: #GstElement to remove + * + * Remove the element from its associated bin, unparenting as well. + */ +void gst_bin_remove(GstBin *bin,GstElement *element) { + g_return_if_fail(bin != NULL); + g_return_if_fail(GST_IS_BIN(bin)); + g_return_if_fail(element != NULL); + g_return_if_fail(GST_IS_ELEMENT(element)); + g_return_if_fail(bin->children != NULL); + + gst_object_unparent(GST_OBJECT(element)); + bin->children = g_list_remove(bin->children,element); + bin->numchildren--; +} + + +static gboolean gst_bin_change_state(GstElement *element, + GstElementState state) { + GstBin *bin; + GList *children; + GstElement *child; + +// g_print("gst_bin_change_state(\"%s\",%d);\n", +// gst_object_get_name(GST_OBJECT(bin)),state); + + g_return_if_fail(GST_IS_BIN(element)); + bin = GST_BIN(element); + g_return_if_fail(bin->numchildren != 0); + +// g_print("-->\n"); + children = bin->children; + while (children) { + child = GST_ELEMENT(children->data); +// g_print("gst_bin_change_state setting state on \"%s\"\n", +// gst_object_get_name(GST_OBJECT(child))); + if (!gst_element_set_state(child,state)) { + g_print("child %p failed to set state 0x%08x\n",child,state); + return FALSE; + } +// g_print("\n"); + children = g_list_next(children); + } +// g_print("<-- \"%s\"\n",gst_object_get_name(GST_OBJECT(bin))); + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + return TRUE; +} + + +static gboolean gst_bin_change_state_norecurse(GstElement *element, + GstElementState state) { + GstBin *bin; + + g_return_if_fail(GST_IS_BIN(element)); + bin = GST_BIN(element); + g_return_if_fail(bin->numchildren != 0); + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + return TRUE; +} + +static gboolean gst_bin_change_state_type(GstBin *bin, + GstElementState state, + GtkType type) { + GList *children; + GstElement *child; + +// g_print("gst_bin_change_state_type(\"%s\",%d,%d);\n", +// gst_object_get_name(GST_OBJECT(bin)),state,type); + + g_return_if_fail(GST_IS_BIN(bin)); + g_return_if_fail(bin->numchildren != 0); + +// g_print("-->\n"); + children = bin->children; + while (children) { + child = GST_ELEMENT(children->data); + if (GST_IS_BIN(child)) { + if (!gst_bin_set_state_type(GST_BIN(child),state,type)) + return FALSE; + } else if (GTK_CHECK_TYPE(child,type)) { + if (!gst_element_set_state(child,state)) + return FALSE; + } +// g_print("\n"); + children = g_list_next(children); + } +// g_print("<-- \"%s\"\n",gst_object_get_name(GST_OBJECT(bin))); + if (type == GST_TYPE_BIN) + gst_element_change_state(GST_ELEMENT(bin),state); + + return TRUE; +} + + +gboolean gst_bin_set_state_type(GstBin *bin, + GstElementState state, + GtkType type) { + GstBinClass *oclass; + +// g_print("gst_bin_set_state_type(\"%s\",%d,%d)\n", +// gst_object_get_name(GST_OBJECT(bin)),state,type); + + g_return_if_fail(bin != NULL); + g_return_if_fail(GST_IS_BIN(bin)); + + oclass = GST_BIN_CLASS(GTK_OBJECT(bin)->klass); + + if (oclass->change_state_type) + (oclass->change_state_type)(bin,state,type); +} + +void gst_bin_real_destroy(GtkObject *object) { + GstBin *bin = GST_BIN(object); + GList *children; + GstElement *child; + +// g_print("in gst_bin_real_destroy()\n"); + + children = bin->children; + while (children) { + child = GST_ELEMENT(children->data); + gst_element_destroy(child); + children = g_list_next(children); + } + + g_list_free(bin->children); +} + +GstElement *gst_bin_get_by_name(GstBin *bin,gchar *name) { + GList *children; + GstElement *child; + + g_return_if_fail(bin != NULL); + g_return_if_fail(GST_IS_BIN(bin)); + g_return_if_fail(name != NULL); + + children = bin->children; + while (children) { + child = GST_ELEMENT(children->data); + if (!strcmp(child->name,name)) + return child; + children = g_list_next(children); + } + + return NULL; +} + +GList *gst_bin_get_list(GstBin *bin) { + g_return_if_fail(bin != NULL); + g_return_if_fail(GST_IS_BIN(bin)); + + return bin->children; +} + +static xmlNodePtr gst_bin_save_thyself(GstElement *element,xmlNodePtr parent) { + GstBin *bin = GST_BIN(element); + xmlNodePtr childlist; + GList *children; + GstElement *child; + + if (GST_ELEMENT_CLASS(parent_class)->save_thyself) + GST_ELEMENT_CLASS(parent_class)->save_thyself(GST_ELEMENT(bin),parent); + + childlist = xmlNewChild(parent,NULL,"children",NULL); + + children = bin->children; + while (children) { + child = GST_ELEMENT(children->data); + gst_element_save_thyself(child,childlist); + children = g_list_next(children); + } +} + +void gst_bin_iterate(GstBin *bin) { + GstBinClass *oclass; + + oclass = GST_BIN_CLASS(GTK_OBJECT(bin)->klass); + + if (oclass->iterate) + (oclass->iterate)(bin); +} + +void gst_bin_create_plan(GstBin *bin) { + GstBinClass *oclass; + + oclass = GST_BIN_CLASS(GTK_OBJECT(bin)->klass); + + if (oclass->create_plan) + (oclass->create_plan)(bin); +} + +static void gst_bin_create_plan_func(GstBin *bin) { + GList *elements; + GstElement *element; + GList *pads; + GstPad *pad, *peer; + GstElement *outside; + + bin->numentries = 0; + + g_print("attempting to create a plan for bin %p\n",bin); + + /* walk through all the elements to figure out all kinds of things */ + elements = GST_BIN(bin)->children; + while (elements) { + element = GST_ELEMENT(elements->data); + + // have to use cothreads if any elements use loop functions + if (element->loopfunc != NULL) { + if (bin->threadcontext == NULL) { + g_print("initializing cothread context\n"); + bin->threadcontext = cothread_init(); + } + if (element->threadstate == NULL) { + g_print("creating thread state for element\n"); + element->threadstate = cothread_create(bin->threadcontext); + cothread_setfunc(element->threadstate,gst_element_loopfunc_wrapper, + 0,element); + } + } + + /* we need to find all the entry points into the bin */ + if (GST_IS_SRC(element)) { + g_print("element '%s' is a source entry point for the bin\n", + gst_element_get_name(GST_ELEMENT(element))); + bin->entries = g_list_prepend(bin->entries,element); + bin->numentries++; + } else { + /* go through the list of pads to see if there's a Connection */ + pads = gst_element_get_pad_list(element); + while (pads) { + pad = GST_PAD(pads->data); + /* we only worry about sink pads */ + if (gst_pad_get_direction(pad) == GST_PAD_SINK) { + /* get the pad's peer */ + peer = gst_pad_get_peer(pad); + if (!peer) break; + /* get the parent of the peer of the pad */ + outside = GST_ELEMENT(gst_pad_get_parent(peer)); + if (!outside) break; + /* if it's a connection and it's not ours... */ + if (GST_IS_CONNECTION(outside) && + (gst_object_get_parent(GST_OBJECT(outside)) != GST_OBJECT(bin))) { + g_print("element '%s' is the external source Connection \ +for internal element '%s'\n", + gst_element_get_name(GST_ELEMENT(outside)), + gst_element_get_name(GST_ELEMENT(element))); + bin->entries = g_list_prepend(bin->entries,outside); + bin->numentries++; + } + } + pads = g_list_next(pads); + } + } + elements = g_list_next(elements); + } + g_print("have %d entries into bin\n",bin->numentries); +} + +void gst_bin_iterate_func(GstBin *bin) { + GList *entries; + GstElement *entry; + + g_return_if_fail(bin != NULL); + g_return_if_fail(GST_IS_BIN(bin)); +// g_return_if_fail(GST_FLAG_IS_SET(thread,GST_STATE_RUNNING)); + g_return_if_fail(bin->numentries > 0); + + entries = bin->entries; + + g_print("iterating\n"); + + while (entries) { + entry = GST_ELEMENT(entries->data); + if (GST_IS_SRC(entry)) + gst_src_push(GST_SRC(entry)); + else if (GST_IS_CONNECTION(entry)) + gst_connection_push(GST_CONNECTION(entry)); + else + g_assert_not_reached(); + entries = g_list_next(entries); + } +// g_print(","); +} diff --git a/gst/gstbin.h b/gst/gstbin.h new file mode 100644 index 0000000000..7f534ef8f0 --- /dev/null +++ b/gst/gstbin.h @@ -0,0 +1,106 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_BIN_H__ +#define __GST_BIN_H__ + + +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +GstElementDetails gst_bin_details; + + +#define GST_TYPE_BIN \ + (gst_bin_get_type()) +#define GST_BIN(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_BIN,GstBin)) +#define GST_BIN_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_BIN,GstBinClass)) +#define GST_IS_BIN(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_BIN)) +#define GST_IS_BIN_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_BIN))) + +typedef struct _GstBin GstBin; +typedef struct _GstBinClass GstBinClass; + +struct _GstBin { + GstElement element; + + gint numchildren; + GList *children; + + GList *entries; + gint numentries; + + cothread_context *threadcontext; +}; + +struct _GstBinClass { + GstElementClass parent_class; + + void (*object_added) (GstObject *object,GstObject *child); + + /* change the state of elements of the given type */ + gboolean (*change_state_type) (GstBin *bin, + GstElementState state, + GtkType type); + + /* create a plan for the execution of the bin */ + void (*create_plan) (GstBin *bin); + + /* run a full iteration of operation */ + void (*iterate) (GstBin *bin); +}; + +GtkType gst_bin_get_type(void); +GstElement *gst_bin_new(gchar *name); + +/* add and remove elements from the bin */ +void gst_bin_add(GstBin *bin,GstElement *element); +void gst_bin_remove(GstBin *bin,GstElement *element); + +/* retrieve a single element or the while list of children */ +GstElement *gst_bin_get_by_name(GstBin *bin,gchar *name); +GList *gst_bin_get_list(GstBin *bin); + +/* set the state for only elements of the given type */ +gboolean gst_bin_set_state_type(GstBin *bin, + GstElementState state, + GtkType type); + +void gst_bin_iterate(GstBin *bin); +void gst_bin_create_plan(GstBin *bin); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_BIN_H__ */ + diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c new file mode 100644 index 0000000000..4494f86c73 --- /dev/null +++ b/gst/gstbuffer.c @@ -0,0 +1,241 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + +//#define DEBUG(format,args...) g_print("DEBUG: " format, ##args) +#define DEBUG(format,args...) + + + +GMemChunk *_gst_buffer_chunk; + + +void _gst_buffer_initialize() { + _gst_buffer_chunk = g_mem_chunk_new("GstBuffer",sizeof(GstBuffer), + sizeof(GstBuffer)*16,G_ALLOC_AND_FREE); +} + + +/** + * gst_buffer_new: + * + * Create a new buffer. + * + * Returns: new buffer + */ +GstBuffer *gst_buffer_new() { + GstBuffer *buffer; + + buffer = g_mem_chunk_alloc(_gst_buffer_chunk); + DEBUG("BUF: allocating new buffer %p\n",buffer); + +// g_print("allocating new mutex\n"); + buffer->lock = g_mutex_new(); +#ifdef HAVE_ATOMIC_H + atomic_set(&buffer->refcount,1); +#else + buffer->refcount = 1; +#endif + buffer->flags = 0; + buffer->type = 0; + buffer->data = NULL; + buffer->size = 0; + buffer->maxsize = 0; + buffer->offset = 0; + buffer->timestamp = 0; + buffer->metas = NULL; + buffer->parent = NULL; + return buffer; +} + + +/** + * gst_buffer_create_sub: + * @parent: parent buffer + * @offset: offset into parent buffer + * @size: size of new subbuffer + * + * Creates a sub-buffer from the parent at a given offset. + * + * Returns: new buffer + */ +GstBuffer *gst_buffer_create_sub(GstBuffer *parent,guint32 offset,guint32 size) { + GstBuffer *buffer; + + g_return_if_fail(parent != NULL); + g_return_if_fail(size > 0); + g_return_if_fail((offset+size) <= parent->size); + + buffer = g_mem_chunk_alloc(_gst_buffer_chunk); + DEBUG("BUF: allocating new subbuffer %p, parent %p\n",buffer,parent); + + buffer->lock = g_mutex_new(); +#ifdef HAVE_ATOMIC_H + atomic_set(&buffer->refcount,1); +#else + buffer->refcount = 1; +#endif + + // copy flags and type from parent, for lack of better + buffer->flags = parent->flags; + buffer->type = parent->type; + + // set the data pointer, size, offset, and maxsize + buffer->data = parent->data + offset; + buffer->size = size; + buffer->offset = offset; + buffer->maxsize = parent->size - offset; + + // again, for lack of better, copy parent's timestamp + buffer->timestamp = parent->timestamp; + + // no metas, this is sane I think + buffer->metas = NULL; + + // set parentage and reference the parent + buffer->parent = parent; + gst_buffer_ref(parent); + + // return the new subbuffer + return buffer; +} + + +void gst_buffer_destroy(GstBuffer *buffer) { + GSList *metas; + + g_return_if_fail(buffer != NULL); + + if (buffer->parent != NULL) + DEBUG("BUF: freeing subbuffer %p\n",buffer); + else + DEBUG("BUF: freeing buffer %p\n",buffer); + + // free the data only if there is some, DONTFREE isn't set, and not sub + if (GST_BUFFER_DATA(buffer) && + !GST_BUFFER_FLAG_IS_SET(buffer,GST_BUFFER_DONTFREE) && + (buffer->parent == NULL)) { + g_free(GST_BUFFER_DATA(buffer)); +// g_print("freed data in buffer\n"); + } + + // unreference any metadata attached to this buffer + metas = buffer->metas; + while (metas) { + gst_meta_unref((GstMeta *)(metas->data)); + metas = g_slist_next(metas); + } + g_slist_free(buffer->metas); + + // unreference the parent if there is one + if (buffer->parent != NULL) + gst_buffer_unref(buffer->parent); + + g_mutex_free(buffer->lock); +// g_print("freed mutex\n"); + + // remove it entirely from memory + g_mem_chunk_free(_gst_buffer_chunk,buffer); +} + +void gst_buffer_ref(GstBuffer *buffer) { + g_return_if_fail(buffer != NULL); + + DEBUG("BUF: referencing buffer %p\n",buffer); + +#ifdef HAVE_ATOMIC_H + g_return_if_fail(atomic_read(&(buffer->refcount)) > 0); + atomic_inc(&(buffer->refcount)) +#else + g_return_if_fail(buffer->refcount > 0); + GST_BUFFER_LOCK(buffer); + buffer->refcount++; + GST_BUFFER_UNLOCK(buffer); +#endif +} + +void gst_buffer_ref_by_count(GstBuffer *buffer,int count) { + g_return_if_fail(buffer != NULL); + g_return_if_fail(count > 0); + +#ifdef HAVE_ATOMIC_H + g_return_if_fail(atomic_read(&(buffer->refcount)) > 0); + atomic_add(count,&(buffer->refcount)) +#else + g_return_if_fail(buffer->refcount > 0); + GST_BUFFER_LOCK(buffer); + buffer->refcount += count; + GST_BUFFER_UNLOCK(buffer); +#endif +} + +void gst_buffer_unref(GstBuffer *buffer) { + int zero; + + g_return_if_fail(buffer != NULL); + + DEBUG("BUF: unreferencing buffer %p\n",buffer); + +#ifdef HAVE_ATOMIC_H + g_return_if_fail(atomic_read(&(buffer->refcount)) > 0); + zero = atomic_dec_and_test(&(buffer->refcount)) +#else + g_return_if_fail(buffer->refcount > 0); + GST_BUFFER_LOCK(buffer); + buffer->refcount--; + zero = (buffer->refcount == 0); + GST_BUFFER_UNLOCK(buffer); +#endif + + /* if we ended up with the refcount at zero, destroy the buffer */ + if (zero) + gst_buffer_destroy(buffer); +} + +void gst_buffer_add_meta(GstBuffer *buffer,GstMeta *meta) { + g_return_if_fail(buffer != NULL); + g_return_if_fail(meta != NULL); + + gst_meta_ref(meta); + buffer->metas = g_slist_append(buffer->metas,meta); +} + +GSList *gst_buffer_get_metas(GstBuffer *buffer) { + g_return_if_fail(buffer != NULL); + + return buffer->metas; +} + +GstMeta *gst_buffer_get_first_meta(GstBuffer *buffer) { + g_return_if_fail(buffer != NULL); + + if (buffer->metas == NULL) + return NULL; + return GST_META(buffer->metas->data); +} + +void gst_buffer_remove_meta(GstBuffer *buffer,GstMeta *meta) { + g_return_if_fail(buffer != NULL); + g_return_if_fail(meta != NULL); + + buffer->metas = g_slist_remove(buffer->metas,meta); + gst_meta_unref(meta); +} diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h new file mode 100644 index 0000000000..bd412b4e09 --- /dev/null +++ b/gst/gstbuffer.h @@ -0,0 +1,128 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_BUFFER_H__ +#define __GST_BUFFER_H__ + +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GST_BUFFER(buf) ((GstBuffer *)(buf)) + + +#define GST_BUFFER_FLAGS(buf) \ + (GST_BUFFER(buf)->flags) +#define GST_BUFFER_FLAG_IS_SET(buf,flag) \ + (GST_BUFFER_FLAGS(buf) & (flag)) +#define GST_BUFFER_FLAG_SET(buf,flag) \ + G_STMT_START{ (GST_BUFFER_FLAGS(buf) |= (flag)); }G_STMT_END +#define GST_BUFFER_FLAG_UNSET(buf,flag) \ + G_STMT_START{ (GST_BUFFER_FLAGS(buf) &= ~(flag)); }G_STMT_END + + +#define GST_BUFFER_TYPE(buf) (GST_BUFFER(buf)->type) +#define GST_BUFFER_DATA(buf) (GST_BUFFER(buf)->data) +#define GST_BUFFER_SIZE(buf) (GST_BUFFER(buf)->size) +#define GST_BUFFER_OFFSET(buf) (GST_BUFFER(buf)->offset) +#define GST_BUFFER_MAXSIZE(buf) (GST_BUFFER(buf)->maxsize) +#define GST_BUFFER_TIMESTAMP(buf) (GST_BUFFER(buf)->timestamp) + + +#define GST_BUFFER_LOCK(buf) (g_mutex_lock(GST_BUFFER(buf)->lock)) +#define GST_BUFFER_TRYLOCK(buf) (g_mutex_trylock(GST_BUFFER(buf)->lock)) +#define GST_BUFFER_UNLOCK(buf) (g_mutex_unlock(GST_BUFFER(buf)->lock)) + + +typedef enum { + GST_BUFFER_READONLY = (1 << 0), + GST_BUFFER_EOS = (1 << 1), + GST_BUFFER_ORIGINAL = (1 << 2), + GST_BUFFER_DONTFREE = (1 << 3), +} GstBufferFlags; + + +typedef struct _GstBuffer GstBuffer; + +struct _GstBuffer { + /* locking */ + GMutex *lock; + + /* refcounting */ +#ifdef HAVE_ATOMIC_H + atomic_t refcount; +#else + int refcount; +#endif + + /* data type of this buffer */ + guint16 type; + /* flags */ + guint16 flags; + + /* pointer to data, its size, and offset in original source if known */ + guchar *data; + guint32 size; + guint32 maxsize; + guint32 offset; + + /* timestamp */ + guint64 timestamp; + /* max age */ + guint64 maxage; + + /* pointer to metadata, is really lame right now */ + GSList *metas; + + /* subbuffer support, who's my parent? */ + GstBuffer *parent; +}; + +/* creating a new buffer from scratch */ +GstBuffer *gst_buffer_new(); + +/* creating a subbuffer */ +GstBuffer *gst_buffer_create_sub(GstBuffer *parent,guint32 offset,guint32 size); + +/* refcounting */ +void gst_buffer_ref(GstBuffer *buffer); +void gst_buffer_ref_by_count(GstBuffer *buffer,int count); +void gst_buffer_unref(GstBuffer *buffer); + +/* destroying the buffer */ +void gst_buffer_destroy(GstBuffer *buffer); + +/* add, retrieve, and remove metadata from the buffer */ +void gst_buffer_add_meta(GstBuffer *buffer,GstMeta *meta); +GstMeta *gst_buffer_get_first_meta(GstBuffer *buffer); +GSList *gst_buffer_get_metas(GstBuffer *buffer); +void gst_buffer_remove_meta(GstBuffer *buffer,GstMeta *meta); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_BUFFER_H__ */ diff --git a/gst/gstconnection.c b/gst/gstconnection.c new file mode 100644 index 0000000000..4c1c491939 --- /dev/null +++ b/gst/gstconnection.c @@ -0,0 +1,99 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + + +/* Connection signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_connection_class_init(GstConnectionClass *klass); +static void gst_connection_init(GstConnection *connection); + + +static GstElementClass *parent_class = NULL; +static guint gst_connection_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_connection_get_type(void) { + static GtkType connection_type = 0; + + if (!connection_type) { + static const GtkTypeInfo connection_info = { + "GstConnection", + sizeof(GstConnection), + sizeof(GstConnectionClass), + (GtkClassInitFunc)gst_connection_class_init, + (GtkObjectInitFunc)gst_connection_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + connection_type = gtk_type_unique(GST_TYPE_ELEMENT,&connection_info); + } + return connection_type; +} + +static void +gst_connection_class_init(GstConnectionClass *klass) { + GtkObjectClass *gtkobject_class; + + gtkobject_class = (GtkObjectClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_ELEMENT); +} + +static void gst_connection_init(GstConnection *connection) { +} + +/** + * gst_connection_new: + * @name: name of new connection + * + * Create a new connection with given name. + * + * Returns: new connection + */ +GstElement *gst_connection_new(gchar *name) { + GstElement *connection = GST_ELEMENT(gtk_type_new(gst_connection_get_type())); + gst_element_set_name(GST_ELEMENT(connection),name); + return connection; +} + +void gst_connection_push(GstConnection *connection) { + GstConnectionClass *oclass; + + g_return_if_fail(connection != NULL); + g_return_if_fail(GST_IS_CONNECTION(connection)); + + oclass = (GstConnectionClass *)(GTK_OBJECT(connection)->klass); + + g_return_if_fail(oclass->push != NULL); + + (oclass->push)(connection); +} diff --git a/gst/gstconnection.h b/gst/gstconnection.h new file mode 100644 index 0000000000..a98ca1b04e --- /dev/null +++ b/gst/gstconnection.h @@ -0,0 +1,69 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_CONNECTION_H__ +#define __GST_CONNECTION_H__ + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GST_TYPE_CONNECTION \ + (gst_connection_get_type()) +#define GST_CONNECTION(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_CONNECTION,GstConnection)) +#define GST_CONNECTION_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_CONNECTION,GstConnectionClass)) +#define GST_IS_CONNECTION(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_CONNECTION)) +#define GST_IS_CONNECTION_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_CONNECTION))) + +typedef struct _GstConnection GstConnection; +typedef struct _GstConnectionClass GstConnectionClass; + +struct _GstConnection { + GstElement element; +}; + +struct _GstConnectionClass { + GstElementClass parent_class; + + /* push function */ + void (*push) (GstConnection *connection); +}; + +GtkType gst_connection_get_type(void); +GstElement *gst_connection_new(gchar *name); + +void gst_connection_push(GstConnection *connection); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_CONNECTION_H__ */ diff --git a/gst/gstelement.c b/gst/gstelement.c new file mode 100644 index 0000000000..941973d7b5 --- /dev/null +++ b/gst/gstelement.c @@ -0,0 +1,507 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + + +/* Element signals and args */ +enum { + STATE_CHANGE, + NEW_PAD, + NEW_GHOST_PAD, + ERROR, + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_element_class_init(GstElementClass *klass); +static void gst_element_init(GstElement *element); +static void gst_element_real_destroy(GtkObject *object); + + +static GstObjectClass *parent_class = NULL; +static guint gst_element_signals[LAST_SIGNAL] = { 0 }; + +GtkType gst_element_get_type(void) { + static GtkType element_type = 0; + + if (!element_type) { + static const GtkTypeInfo element_info = { + "GstElement", + sizeof(GstElement), + sizeof(GstElementClass), + (GtkClassInitFunc)gst_element_class_init, + (GtkObjectInitFunc)gst_element_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + element_type = gtk_type_unique(GST_TYPE_OBJECT,&element_info); + } + return element_type; +} + +static void gst_element_class_init(GstElementClass *klass) { + GtkObjectClass *gtkobject_class; + + gtkobject_class = (GtkObjectClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_OBJECT); + + gst_element_signals[STATE_CHANGE] = + gtk_signal_new("state_change",GTK_RUN_LAST,gtkobject_class->type, + GTK_SIGNAL_OFFSET(GstElementClass,state_change), + gtk_marshal_NONE__INT,GTK_TYPE_NONE,1, + GTK_TYPE_INT); + gst_element_signals[NEW_PAD] = + gtk_signal_new("new_pad",GTK_RUN_LAST,gtkobject_class->type, + GTK_SIGNAL_OFFSET(GstElementClass,new_pad), + gtk_marshal_NONE__POINTER,GTK_TYPE_NONE,1, + GTK_TYPE_POINTER); + gst_element_signals[NEW_GHOST_PAD] = + gtk_signal_new("new_ghost_pad",GTK_RUN_LAST,gtkobject_class->type, + GTK_SIGNAL_OFFSET(GstElementClass,new_ghost_pad), + gtk_marshal_NONE__POINTER,GTK_TYPE_NONE,1, + GTK_TYPE_POINTER); + gst_element_signals[ERROR] = + gtk_signal_new("error",GTK_RUN_LAST,gtkobject_class->type, + GTK_SIGNAL_OFFSET(GstElementClass,error), + gtk_marshal_NONE__POINTER,GTK_TYPE_NONE,1, + GTK_TYPE_POINTER); + + + gtk_object_class_add_signals(gtkobject_class,gst_element_signals,LAST_SIGNAL); + + klass->start = NULL; + klass->stop = NULL; + klass->change_state = gst_element_change_state; + + gtkobject_class->destroy = gst_element_real_destroy; +} + +static void gst_element_init(GstElement *element) { + element->state = 0; + element->numpads = 0; + element->pads = NULL; + element->loopfunc = NULL; +} + +/** + * gst_element_new: + * + * Create a new element. + * + * Returns: new element + */ +GstElement *gst_element_new() { + return GST_ELEMENT(gtk_type_new(GST_TYPE_ELEMENT)); +} + +/** + * gst_element_add_pad: + * @element: element to add pad to + * @pad: pad to add + * + * Add a pad (connection point) to the element, setting the parent of the + * pad to the element (and thus adding a reference). + */ +void gst_element_add_pad(GstElement *element,GstPad *pad) { + g_return_if_fail(element != NULL); + g_return_if_fail(GST_IS_ELEMENT(element)); + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + + /* set the pad's parent */ + gst_pad_set_parent(pad,GST_OBJECT(element)); + + /* add it to the list */ + element->pads = g_list_append(element->pads,pad); + element->numpads++; + + /* emit the NEW_PAD signal */ +// g_print("emitting NEW_PAD signal, \"%s\"!\n",gst_pad_get_name(pad)); + gtk_signal_emit(GTK_OBJECT(element),gst_element_signals[NEW_PAD],pad); +} + +/** + * gst_element_add_ghost_pad: + * @element: element to add ghost pad to + * @pad: ghost pad to add + * + * Add a ghost pad to the element, setting the ghost parent of the pad to + * the element (and thus adding a reference). + */ +void gst_element_add_ghost_pad(GstElement *element,GstPad *pad) { + g_return_if_fail(element != NULL); + g_return_if_fail(GST_IS_ELEMENT(element)); + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + + /* set the pad's parent */ + gst_pad_add_ghost_parent(pad,GST_OBJECT(element)); + + /* add it to the list */ + element->pads = g_list_append(element->pads,pad); + element->numpads++; + + /* emit the NEW_PAD signal */ + gtk_signal_emit(GTK_OBJECT(element),gst_element_signals[NEW_GHOST_PAD],pad); +} + +/** + * gst_element_get_pad: + * @element: element to find pad of + * @name: name of pad to retrieve + * + * Retrieve a pad from the element by name. + * + * Returns: requested pad if found, otherwise NULL. + */ +GstPad *gst_element_get_pad(GstElement *element,gchar *name) { + GList *walk; + + g_return_if_fail(element != NULL); + g_return_if_fail(GST_IS_ELEMENT(element)); + if (name == NULL) + return NULL; + if (!element->numpads) + return NULL; + + walk = element->pads; + while (walk) { + if (!strcmp(((GstPad *)(walk->data))->name,name)) + return (GstPad *)(walk->data); + walk = g_list_next(walk); + } + + return NULL; +} + +/** + * gst_element_get_pad_list: + * @element: element to get pads of + * + * Retrieve a list of the pads associated with the element. + * + * Returns: GList of pads + */ +GList *gst_element_get_pad_list(GstElement *element) { + g_return_if_fail(element != NULL); + g_return_if_fail(GST_IS_ELEMENT(element)); + + return element->pads; +} + +/** + * gst_element_connect: + * @src: element containing source pad + * @srcpadname: name of pad in source element + * @dest: element containing destination pad + * @destpadname: name of pad in destination element + * + * Connect the two named pads of the source and destination elements. + * Side effect is that if one of the pads has no parent, it becomes a + * child of the parent of the other element. If they have different + * parents, the connection fails. + */ +void gst_element_connect(GstElement *src,gchar *srcpadname, + GstElement *dest,gchar *destpadname) { + GstPad *srcpad,*destpad; + GstObject *srcparent,*destparent; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_ELEMENT(src)); + g_return_if_fail(srcpadname != NULL); + g_return_if_fail(dest != NULL); + g_return_if_fail(GST_IS_ELEMENT(dest)); + g_return_if_fail(destpadname != NULL); + + srcpad = gst_element_get_pad(src,srcpadname); + destpad = gst_element_get_pad(dest,destpadname); + + g_return_if_fail(srcpad != NULL); + g_return_if_fail(destpad != NULL); + + srcparent = gst_object_get_parent(GST_OBJECT(src)); + destparent = gst_object_get_parent(GST_OBJECT(dest)); + /* we can't do anything if neither have parents */ + if ((srcparent == NULL) && (destparent == NULL)) + return; + + /* and we have to make sure that they have the same parents... */ + if ((srcparent == NULL) && (destparent == NULL)) { + if (srcparent != destparent) + return; + } +} + +void gst_element_error(GstElement *element,gchar *error) { + g_error("error in element '%s': %s\n",element->name,error); + + gtk_signal_emit(GTK_OBJECT(element),gst_element_signals[ERROR],error); +} + + +/** + * gst_element_set_state: + * @element: element to change state of + * @state: new element state + * + * Sets the state of the element, but more importantly fires off a signal + * indicating the new state. You can clear state by simply prefixing the + * GstElementState value with ~, it will be detected and used to turn off + * that bit. + * + * Returns: whether or not the state was successfully set. + */ +gboolean gst_element_set_state(GstElement *element,GstElementState state) { + GstElementClass *oclass; + gboolean stateset = FALSE; + +// g_print("gst_element_set_state(\"%s\",%08lx)\n", +// element->name,state); + + g_return_if_fail(element != NULL); + g_return_if_fail(GST_IS_ELEMENT(element)); + + oclass = GST_ELEMENT_CLASS(GTK_OBJECT(element)->klass); + + if (oclass->change_state) + stateset = (oclass->change_state)(element,state); + + /* if a state *set* failed, unset it immediately */ +/* + if (!(state & GST_STATE_MAX) && !stateset) { + g_print("set state failed miserably, forcing unset\n"); + if (oclass->change_state) + stateset = (oclass->change_state)(element,~state); + return FALSE; + }*/ + + return stateset; +} + +/* class function to set the state of a simple element */ +gboolean gst_element_change_state(GstElement *element, + GstElementState state) { + g_return_if_fail(element != NULL); + g_return_if_fail(GST_IS_ELEMENT(element)); + +// g_print("gst_element_change_state(\"%s\",%d)\n", +// element->name,state); + + /* deal with the inverted state */ +// g_print("changing element state, was %08lx",GST_STATE(element)); + if (state & GST_STATE_MAX) + GST_STATE_UNSET(element,~state); + else + GST_STATE_SET(element,state); +// g_print(", is now %08lx\n",GST_STATE(element)); + gtk_signal_emit(GTK_OBJECT(element),gst_element_signals[STATE_CHANGE], + state); +} + +/** + * gst_element_set_name: + * @element: GstElement to set name of + * @name: new name of element + * + * Set the name of the element, getting rid of the old name if there was + * one. + */ +void gst_element_set_name(GstElement *element,gchar *name) { + g_return_if_fail(element != NULL); + g_return_if_fail(GST_IS_ELEMENT(element)); + g_return_if_fail(name != NULL); + + if (element->name != NULL) + g_free(element->name); + + element->name = g_strdup(name); +} + +/** + * gst_element_get_name: + * @element: GstElement to set name of + * + * Get the name of the element. + * + * Returns: name of the element + */ +gchar *gst_element_get_name(GstElement *element) { + g_return_if_fail(element != NULL); + g_return_if_fail(GST_IS_ELEMENT(element)); + + return element->name; +} + +static void gst_element_real_destroy(GtkObject *object) { + GstElement *element = GST_ELEMENT(object); + GList *pads; + GstPad *pad; + +// g_print("in gst_element_real_destroy()\n"); + + if (element->name) + g_free(element->name); + + pads = element->pads; + while (pads) { + pad = GST_PAD(pads->data); + gst_pad_destroy(pad); + pads = g_list_next(pads); + } + + g_list_free(element->pads); +} + + +static gchar *_gst_element_type_names[] = { + "invalid", + "none", + "char", + "uchar", + "bool", + "int", + "uint", + "long", + "ulong", + "float", + "double", + "string", +}; + +xmlNodePtr gst_element_save_thyself(GstElement *element,xmlNodePtr parent) { + xmlNodePtr self, arglist; + GList *pads; + GstPad *pad; + GstElementClass *oclass; + GstElementFactory *factory; + GtkType type; + + oclass = GST_ELEMENT_CLASS(GTK_OBJECT(element)->klass); + + self = xmlNewChild(parent,NULL,"element",NULL); + xmlNewChild(self,NULL,"name",element->name); + if (oclass->elementfactory != NULL) { + factory = (GstElementFactory *)oclass->elementfactory; + xmlNewChild(self,NULL,"type",factory->name); + xmlNewChild(self,NULL,"version",factory->details->version); + } + + pads = element->pads; + while (pads) { + pad = GST_PAD(pads->data); + // figure out if it's a direct pad or a ghostpad + if (pad->parent == element) + gst_pad_save_thyself(pad,self); + pads = g_list_next(pads); + } + + // output all args to the element + arglist = xmlNewChild(self,NULL,"args",NULL); + type = GTK_OBJECT_TYPE(element); + while (type != GTK_TYPE_INVALID) { + GtkArg *args; + guint32 *flags; + guint num_args,i; + + args = gtk_object_query_args(type,&flags,&num_args); + for (i=0;i GTK_TYPE_NONE) && + (args[i].type <= GTK_TYPE_STRING) && + (flags && GTK_ARG_READABLE)) { + xmlNodePtr arg; + gtk_object_getv(GTK_OBJECT(element),1,&args[i]); + arg = xmlNewChild(arglist,NULL,"arg",NULL); + xmlNewChild(arg,NULL,"name",args[i].name); + switch (args[i].type) { + case GTK_TYPE_CHAR: + xmlNewChild(arg,NULL,"value", + g_strdup_printf("%c",GTK_VALUE_CHAR(args[i]))); + break; + case GTK_TYPE_UCHAR: + xmlNewChild(arg,NULL,"value", + g_strdup_printf("%d",GTK_VALUE_UCHAR(args[i]))); + break; + case GTK_TYPE_BOOL: + xmlNewChild(arg,NULL,"value", + GTK_VALUE_BOOL(args[1])?"true":"false"); + break; + case GTK_TYPE_INT: + xmlNewChild(arg,NULL,"value", + g_strdup_printf("%d",GTK_VALUE_INT(args[i]))); + break; + case GTK_TYPE_LONG: + xmlNewChild(arg,NULL,"value", + g_strdup_printf("%ld",GTK_VALUE_LONG(args[i]))); + break; + case GTK_TYPE_ULONG: + xmlNewChild(arg,NULL,"value", + g_strdup_printf("%ld",GTK_VALUE_ULONG(args[i]))); + break; + case GTK_TYPE_FLOAT: + xmlNewChild(arg,NULL,"value", + g_strdup_printf("%f",GTK_VALUE_FLOAT(args[i]))); + break; + case GTK_TYPE_DOUBLE: + xmlNewChild(arg,NULL,"value", + g_strdup_printf("%lf",GTK_VALUE_DOUBLE(args[i]))); + break; + case GTK_TYPE_STRING: + xmlNewChild(arg,NULL,"value",GTK_VALUE_STRING(args[i])); + break; + } + } + } + type = gtk_type_parent(type); + } + + if (oclass->save_thyself) + (oclass->save_thyself)(element,self); + + return self; +} + +void gst_element_set_manager(GstElement *element,GstElement *manager) { + element->manager = manager; +} + +GstElement *gst_element_get_manager(GstElement *element) { + return element->manager; +} + +// note that this casts a char ** to a GstElement *. Ick. +int gst_element_loopfunc_wrapper(int argc,char **argv) { + GstElement *element = GST_ELEMENT(argv); + element->loopfunc(element); +} + +void gst_element_set_loop_function(GstElement *element, + GstElementLoopFunction loop) { + element->loopfunc = loop; + if (element->threadstate != NULL) + cothread_setfunc(element->threadstate,gst_element_loopfunc_wrapper, + 0,element); +} diff --git a/gst/gstelement.h b/gst/gstelement.h new file mode 100644 index 0000000000..8490ce1cc0 --- /dev/null +++ b/gst/gstelement.h @@ -0,0 +1,194 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_ELEMENT_H__ +#define __GST_ELEMENT_H__ + + +#include +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +typedef enum { + GST_STATE_COMPLETE = (1 << 0), + GST_STATE_RUNNING = (1 << 1), + GST_STATE_DISCOVERY = (1 << 2), + GST_STATE_PREROLL = (1 << 3), + + GST_STATE_PLAYING = (1 << 4), + GST_STATE_PAUSED = (1 << 5), + + GST_STATE_MAX = (1 << 15), +} GstElementState; + + +#define GST_STATE(obj) (GST_ELEMENT(obj)->state) +#define GST_STATE_IS_SET(obj,flag) (GST_STATE (obj) & (flag)) +#define GST_STATE_SET(obj,flag) \ +G_STMT_START{ (GST_STATE (obj) |= (flag)); \ +gst_info("set '%s' state %d\n",gst_element_get_name(obj),flag); \ +}G_STMT_END +#define GST_STATE_UNSET(obj,flag) \ +G_STMT_START{ (GST_STATE (obj) &= ~(flag)); \ +gst_info("unset '%s' state %d\n",gst_element_get_name(obj),flag); \ +}G_STMT_END + + +#define GST_TYPE_ELEMENT \ + (gst_element_get_type()) +#define GST_ELEMENT(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_ELEMENT,GstElement)) +#define GST_ELEMENT_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_ELEMENT,GstElementClass)) +#define GST_IS_ELEMENT(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_ELEMENT)) +#define GST_IS_ELEMENT_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_ELEMENT))) + +typedef struct _GstElement GstElement; +typedef struct _GstElementClass GstElementClass; +typedef struct _GstElementDetails GstElementDetails; +typedef struct _GstElementFactory GstElementFactory; + +typedef void (*GstElementLoopFunction) (GstElement *element); + +struct _GstElement { + GstObject object; + + gchar *name; + + guint16 state; + + GstElementLoopFunction loopfunc; + cothread_state *threadstate; + + guint16 numpads; + GList *pads; + + GstElement *manager; +}; + +struct _GstElementClass { + GstObjectClass parent_class; + + /* the elementfactory that created us */ + GstElementFactory *elementfactory; + + /* signal callbacks */ + void (*state_change) (GstElement *element,GstElementState state); + void (*new_pad) (GstElement *element,GstPad *pad); + void (*new_ghost_pad) (GstElement *element,GstPad *pad); + void (*error) (GstElement *element,gchar *error); + + /* events */ + gboolean (*start) (GstElement *element,GstElementState state); + gboolean (*stop) (GstElement *element); + + /* change the element state */ + gboolean (*change_state) (GstElement *element,GstElementState state); + + /* create or read XML representation of self */ + xmlNodePtr (*save_thyself)(GstElement *element,xmlNodePtr parent); + void (*restore_thyself)(GstElement *element,xmlNodePtr *self); +}; + +struct _GstElementDetails { + gchar *longname; /* long, english name */ + gchar *class; /* type of element, kinda */ + gchar *description; /* insights of one form or another */ + gchar *version; /* version of the element */ + gchar *author; /* who wrote this thing? */ + gchar *copyright; /* copyright details (year, etc.) */ +}; + +struct _GstElementFactory { + gchar *name; + GtkType type; + + GstElementDetails *details; +}; + + +GtkType gst_element_get_type(void); +GstElement *gst_element_new(void); + +void gst_element_set_loop_function(GstElement *element, + GstElementLoopFunction loop); + +void gst_element_set_name(GstElement *element,gchar *name); +gchar *gst_element_get_name(GstElement *element); + +void gst_element_set_manager(GstElement *element,GstElement *manager); +GstElement *gst_element_get_manager(GstElement *element); + +void gst_element_add_pad(GstElement *element,GstPad *pad); +void gst_element_add_ghost_pad(GstElement *element,GstPad *pad); +GstPad *gst_element_get_pad(GstElement *element,gchar *name); +GList *gst_element_get_pad_list(GstElement *element); + +void gst_element_connect(GstElement *src,gchar *srcpadname, + GstElement *dest,gchar *destpadname); + +/* called by the app to set the state of the element */ +gboolean gst_element_set_state(GstElement *element,GstElementState state); + +void gst_element_error(GstElement *element,gchar *error); + +/* callback to actually set the state */ +gboolean gst_element_change_state(GstElement *element, + GstElementState state); + +#define gst_element_destroy(element) gst_object_destroy(GST_OBJECT(element)) + +/* XML write and read */ +xmlNodePtr gst_element_save_thyself(GstElement *element,xmlNodePtr parent); + + +GstElementFactory *gst_elementfactory_new(gchar *name,GtkType type, + GstElementDetails *details); +void gst_elementfactory_register(GstElementFactory *elementfactory); + +GstElementFactory *gst_elementfactory_find(gchar *name); +GList *gst_elementfactory_get_list(); + +GstElement *gst_elementfactory_create(GstElementFactory *factory, + gchar *name); + +// FIXME this name is wrong, probably so is the one above it +GstElement *gst_elementfactory_make(gchar *factoryname,gchar *name); + +int gst_element_loopfunc_wrapper(int argc,char **argv); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_ELEMENT_H__ */ + diff --git a/gst/gstelementfactory.c b/gst/gstelementfactory.c new file mode 100644 index 0000000000..c6f185f1c9 --- /dev/null +++ b/gst/gstelementfactory.c @@ -0,0 +1,138 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + + +/* global list of registered elementfactories */ +GList* _gst_elementfactories; + +void _gst_elementfactory_initialize() { + _gst_elementfactories = NULL; +} + +/** + * gst_elementfactory_register: + * @elementfactory: factory to register + * + * Adds the elementfactory to the global list, so it can be retrieved by + * name. + */ +void gst_elementfactory_register(GstElementFactory *elementfactory) { + g_return_if_fail(elementfactory != NULL); + + _gst_elementfactories = g_list_prepend(_gst_elementfactories,elementfactory); +} + +/** + * gst_elementfactory_find: + * @name: name of factory to find + * + * Search for an elementfactory of the given name. + * + * Returns: #GstElementFactory if found, NULL otherwise + */ +GstElementFactory *gst_elementfactory_find(gchar *name) { + GList *walk = _gst_elementfactories; + GstElementFactory *factory; + + while (walk) { + factory = (GstElementFactory *)(walk->data); + if (!strcmp(name,factory->name)) + return factory; + walk = g_list_next(walk); + } + + return NULL; +} + +/** + * gst_elementfactory_get_list: + * + * Get the global list of elementfactories. + * + * Returns: GList of type #GstElementFactory + */ +GList *gst_elementfactory_get_list() { + return _gst_elementfactories; +} + + +/** + * gst_elementfactory_new: + * @name: name of new elementfactory + * @type: GtkType of new element + * @details: #GstElementDetails structure with element details + * + * Create a new elementfactory capable of insantiating objects of the + * given type. + * + * Returns: new elementfactory + */ +GstElementFactory *gst_elementfactory_new(gchar *name,GtkType type, + GstElementDetails *details) { + GstElementFactory *factory = g_new0(GstElementFactory, 1); + factory->name = g_strdup(name); + factory->type = type; + factory->details = details; + return factory; +} + +/** + * gst_elementfactory_create: + * @factory: factory to instantiate + * @name: name of new element + * + * Create a new element of the type defined by the given elementfactory. + * It wll be given the name supplied, since all elements require a name as + * their first argument. + * + * Returns: new #GstElement + */ +GstElement *gst_elementfactory_create(GstElementFactory *factory, + gchar *name) { + GstElement *element; + GstElementClass *oclass; + + g_return_if_fail(factory != NULL); + g_return_if_fail(factory->type != 0); + + // create an instance of the element + element = GST_ELEMENT(gtk_type_new(factory->type)); + g_assert(element != NULL); + + // attempt to set the elemenfactory class pointer if necessary + oclass = GST_ELEMENT_CLASS(GTK_OBJECT(element)->klass); + if (oclass->elementfactory == NULL) + oclass->elementfactory = factory; + + gst_element_set_name(GST_ELEMENT(element),name); + + return element; +} + +GstElement *gst_elementfactory_make(gchar *factoryname,gchar *name) { + GstElementFactory *factory; + GstElement *element; + + factory = gst_elementfactory_find(factoryname); + if (factory == NULL) return NULL; + element = gst_elementfactory_create(factory,name); + return element; +} diff --git a/gst/gstfilter.c b/gst/gstfilter.c new file mode 100644 index 0000000000..fc8fcd4672 --- /dev/null +++ b/gst/gstfilter.c @@ -0,0 +1,86 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + + +/* Filter signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_filter_class_init(GstFilterClass *klass); +static void gst_filter_init(GstFilter *filter); + + +static GstElementClass *parent_class = NULL; +static guint gst_filter_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_filter_get_type(void) { + static GtkType filter_type = 0; + + if (!filter_type) { + static const GtkTypeInfo filter_info = { + "GstFilter", + sizeof(GstFilter), + sizeof(GstFilterClass), + (GtkClassInitFunc)gst_filter_class_init, + (GtkObjectInitFunc)gst_filter_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + filter_type = gtk_type_unique(GST_TYPE_ELEMENT,&filter_info); + } + return filter_type; +} + +static void +gst_filter_class_init(GstFilterClass *klass) { + GtkObjectClass *gtkobject_class; + + gtkobject_class = (GtkObjectClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_ELEMENT); +} + +static void gst_filter_init(GstFilter *filter) { +} + +/** + * gst_filter_new: + * @name: name of new filter + * + * Create a new filter with given name. + * + * Returns: new filter + */ +GstElement *gst_filter_new(gchar *name) { + GstElement *filter = GST_ELEMENT(gtk_type_new(gst_filter_get_type())); + gst_element_set_name(GST_ELEMENT(filter),name); + return filter; +} diff --git a/gst/gstfilter.h b/gst/gstfilter.h new file mode 100644 index 0000000000..860cc4acbd --- /dev/null +++ b/gst/gstfilter.h @@ -0,0 +1,63 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_FILTER_H__ +#define __GST_FILTER_H__ + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GST_TYPE_FILTER \ + (gst_filter_get_type()) +#define GST_FILTER(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_FILTER,GstFilter)) +#define GST_FILTER_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_FILTER,GstFilterClass)) +#define GST_IS_FILTER(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_FILTER)) +#define GST_IS_FILTER_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_FILTER))) + +typedef struct _GstFilter GstFilter; +typedef struct _GstFilterClass GstFilterClass; + +struct _GstFilter { + GstElement element; +}; + +struct _GstFilterClass { + GstElementClass parent_class; +}; + +GtkType gst_filter_get_type(void); +GstElement *gst_filter_new(gchar *name); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_FILTER_H__ */ diff --git a/gst/gstlog.h b/gst/gstlog.h new file mode 100644 index 0000000000..e9b353ba9b --- /dev/null +++ b/gst/gstlog.h @@ -0,0 +1,31 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_LOG_H__ +#define __GST_LOG_H__ + +/* information messages */ +#define GST_SHOW_INFO +#ifdef GST_SHOW_INFO +#define gst_info(format,args...) fprintf(stderr,format,##args) +#else +#define gst_info(format,args...) +#endif + +#endif /* __GST_LOG_H__ */ diff --git a/gst/gstmeta.c b/gst/gstmeta.c new file mode 100644 index 0000000000..08208d501f --- /dev/null +++ b/gst/gstmeta.c @@ -0,0 +1,57 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include +#include + + +GstMeta *gst_meta_new_size(gint size) { + GstMeta *meta; + + meta = g_malloc(size); + gst_meta_ref(meta); + + return meta; +} + +void gst_meta_ref(GstMeta *meta) { + g_return_if_fail(meta != NULL); + + gst_trace_add_entry(NULL,0,meta,"ref meta"); + meta->refcount++; +} + +void gst_meta_unref(GstMeta *meta) { + g_return_if_fail(meta != NULL); + + gst_trace_add_entry(NULL,0,meta,"unref meta"); + meta->refcount--; + + if (meta->refcount == 0) { +// gst_trace_add_entry(NULL,0,meta,"destroy meta"); + g_free(meta); + g_print("freeing metadata\n"); + } +} + + +GstMeta *gst_meta_cow(GstMeta *meta) { + g_return_if_fail(meta != NULL); +} diff --git a/gst/gstmeta.h b/gst/gstmeta.h new file mode 100644 index 0000000000..2ba8998afd --- /dev/null +++ b/gst/gstmeta.h @@ -0,0 +1,85 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + + +#ifndef __GST_META_H__ +#define __GST_META_H__ + +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GST_META(meta) ((GstMeta *)(meta)) + + +#define GST_META_FLAGS(buf) \ + (GST_META(buf)->flags) +#define GST_META_FLAG_IS_SET(meta,flag) \ + (GST_META_FLAGS(meta) & (flag)) +#define GST_META_FLAG_SET(meta,flag) \ + G_STMT_START{ (GST_META_FLAGS(meta) |= (flag)); }G_STMT_END +#define GST_META_FLAG_UNSET(meta,flag) \ + G_STMT_START{ (GST_META_FLAGS(meta) &= ~(flag)); }G_STMT_END + + +typedef enum { + GST_META_FREEABLE = 1 << 0, +} GstMetaFlags; + + +typedef struct _GstMeta GstMeta; + +struct _GstMeta { + /* locking */ + GMutex *lock; + + /* refcounting */ +#ifdef HAVE_ATOMIC_H + atomic_t refcount; +#else + int refcount; +#endif + + guint16 type; + guint16 flags; + + void *data; + guint16 size; +}; + + +GstMeta *gst_meta_new_size(gint size); +#define gst_meta_new(type) (type *)gst_meta_new_size(sizeof(type)) + +/* refcounting */ +void gst_meta_ref(GstMeta *meta); +void gst_meta_unref(GstMeta *meta); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_BUFFER_H__ */ + diff --git a/gst/gstobject.c b/gst/gstobject.c new file mode 100644 index 0000000000..7754cc32e8 --- /dev/null +++ b/gst/gstobject.c @@ -0,0 +1,223 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include +#include + + +/* Object signals and args */ +enum { + PARENT_SET, + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_object_class_init(GstObjectClass *klass); +static void gst_object_init(GstObject *object); + + +static GtkObjectClass *parent_class = NULL; +static guint gst_object_signals[LAST_SIGNAL] = { 0 }; + +GtkType gst_object_get_type(void) { + static GtkType object_type = 0; + + if (!object_type) { + static const GtkTypeInfo object_info = { + "GstObject", + sizeof(GstObject), + sizeof(GstObjectClass), + (GtkClassInitFunc)gst_object_class_init, + (GtkObjectInitFunc)gst_object_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + object_type = gtk_type_unique(gtk_object_get_type(),&object_info); + } + return object_type; +} + +static void gst_object_class_init(GstObjectClass *klass) { + GtkObjectClass *gtkobject_class; + + gtkobject_class = (GtkObjectClass*)klass; + + parent_class = gtk_type_class(gtk_object_get_type()); + + gst_object_signals[PARENT_SET] = + gtk_signal_new("parent_set",GTK_RUN_LAST,gtkobject_class->type, + GTK_SIGNAL_OFFSET(GstObjectClass,parent_set), + gtk_marshal_NONE__POINTER,GTK_TYPE_NONE,1, + GTK_TYPE_POINTER); + gtk_object_class_add_signals(gtkobject_class,gst_object_signals,LAST_SIGNAL); +} + +static void gst_object_init(GstObject *object) { + object->lock = g_mutex_new(); +#ifdef HAVE_ATOMIC_H + atomic_set(&(object->refcount),1); +#else + object->refcount++; +#endif + object->parent = NULL; +} + +/** + * gst_object_new: + * + * Create a new object with + * + * Returns: new object + */ +GstObject *gst_object_new() { + return GST_OBJECT(gtk_type_new(gst_object_get_type())); +} + +/** + * gst_object_set_parent: + * @object: GstObject to set parent of + * @parent: new parent of object + * + * Set the parent of the object. The object's reference count is + * incremented. + */ +void gst_object_set_parent(GstObject *object,GstObject *parent) { + g_return_if_fail(object != NULL); + g_return_if_fail(GST_IS_OBJECT(object)); + g_return_if_fail(object->parent == NULL); + g_return_if_fail(parent != NULL); + g_return_if_fail(GST_IS_OBJECT(parent)); + g_return_if_fail(object != parent); + + gst_object_ref(object); + gst_object_sink(object); + object->parent = parent; + + gtk_signal_emit(GTK_OBJECT(object),gst_object_signals[PARENT_SET],parent); +} + +/** + * gst_object_get_parent: + * @object: GstObject to get parent of + * + * Return the parent of the object. + * + * Returns: parent of the object + */ +GstObject *gst_object_get_parent(GstObject *object) { + g_return_if_fail(object != NULL); + g_return_if_fail(GST_IS_OBJECT(object)); + + return object->parent; +} + +/** + * gst_object_unparent: + * @object: GstObject to unparent + * + * Clear the parent of the object, removing the associated reference. + */ +void gst_object_unparent(GstObject *object) { + g_return_if_fail(object != NULL); + g_return_if_fail(GST_IS_OBJECT(object)); + if (object->parent == NULL) + return; + + object->parent = NULL; + gst_object_unref(object); +} + +#ifndef gst_object_ref +void gst_object_ref (GstObject *object) { + g_return_if_fail(object != NULL); + g_return_if_fail(GST_IS_OBJECT(object)); + +#ifdef HAVE_ATOMIC_H + g_return_if_fail(atomic_read(&(object->refcount)) > 0); + atomic_inc(&(object->refcount)) +#else + g_return_if_fail(object->refcount > 0); + GST_LOCK(object); + object->refcount++; + GST_UNLOCK(object); +#endif +} +#endif /* gst_object_ref */ + +#ifndef gst_object_unref +void gst_object_unref (GstObject *object) { + int reftest; + + g_return_if_fail(object != NULL); + g_return_if_fail(GST_IS_OBJECT(object)); + +#ifdef HAVE_ATOMIC_H + g_return_if_fail(atomic_read(&(object->refcount)) > 0); + reftest = atomic_dec_and_test(&(object->refcount)) +#else + g_return_if_fail(object->refcount > 0); + GST_LOCK(object); + object->refcount--; + reftest = (object->refcount == 0); + GST_UNLOCK(object); +#endif + + /* if we ended up with the refcount at zero */ + if (reftest) { + /* get the count to 1 for gtk_object_destroy() */ +#ifdef HAVE_ATOMIC_T + atomic_set(&(object->refcount),1); +#else + object->refcount = 1; +#endif + /* destroy it */ + gtk_object_destroy(GTK_OBJECT(object)); + /* drop the refcount back to zero */ +#ifdef HAVE_ATOMIC_T + atomic_set(&(object->refcount),0); +#else + object->refcount = 0; +#endif + /* finalize the object */ + // FIXME this is an evil hack that should be killed +// FIXMEFIXMEFIXMEFIXME +// gtk_object_finalize(GTK_OBJECT(object)); + } +} +#endif /* gst_object_unref */ + +#ifndef gst_object_sink +void gst_object_sink(GstObject *object) { + g_return_if_fail(object != NULL); + g_return_if_fail(GST_IS_OBJECT(object)); + + if (GTK_OBJECT_FLOATING(object)) { + GTK_OBJECT_UNSET_FLAGS(object, GTK_FLOATING); + gst_object_unref(object); + } +} +#endif /* gst_object_sink */ + diff --git a/gst/gstobject.h b/gst/gstobject.h new file mode 100644 index 0000000000..060e94831a --- /dev/null +++ b/gst/gstobject.h @@ -0,0 +1,117 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_OBJECT_H__ +#define __GST_OBJECT_H__ + + +#include +#include +#include "config.h" + +#ifdef HAVE_ATOMIC_H +#include +#endif + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GST_TYPE_OBJECT \ + (gst_object_get_type()) +#define GST_OBJECT(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_OBJECT,GstObject)) +#define GST_OBJECT_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_OBJECT,GstObjectClass)) +#define GST_IS_OBJECT(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_OBJECT)) +#define GST_IS_OBJECT_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_OBJECT))) + +typedef struct _GstObject GstObject; +typedef struct _GstObjectClass GstObjectClass; + +struct _GstObject { + GtkObject object; + + /* have to have a refcount for the object */ +#ifdef HAVE_ATOMIC_H + atomic_t refcount; +#else + int refcount; +#endif + + /* locking for all sorts of things (like the refcount) */ + GMutex *lock; + + /* this objects parent */ + GstObject *parent; +}; + +struct _GstObjectClass { + GtkObjectClass parent_class; + + /* signals */ + void (*parent_set) (GstObject *object,GstObject *parent); + + /* functions go here */ +}; + + +#define GST_FLAGS(obj) GTK_OBJECT_FLAGS(obj) +#define GST_FLAG_IS_SET(obj,flag) (GST_FLAGS (obj) & (flag)) +#define GST_FLAG_SET(obj,flag) G_STMT_START{ (GST_FLAGS (obj) |= (flag)); }G_STMT_END +#define GST_FLAG_UNSET(obj,flag) G_STMT_START{ (GST_FLAGS (obj) &= ~(flag)); }G_STMT_END + +#define GST_LOCK(obj) (g_mutex_lock(GST_OBJECT(obj)->lock)) +#define GST_TRYLOCK(obj) (g_mutex_trylock(GST_OBJECT(obj)->lock)) +#define GST_UNLOCK(obj) (g_mutex_unlock(GST_OBJECT(obj)->lock)) + + +/* normal GtkObject stuff */ +GtkType gst_object_get_type(void); +GstObject* gst_object_new(void); + +/* parentage routines */ +void gst_object_set_parent(GstObject *object,GstObject *parent); +GstObject *gst_object_get_parent(GstObject *object); +void gst_object_unparent(GstObject *object); + +/* refcounting */ +//void gst_object_ref(GstObject *object); +#define gst_object_ref(obj) gtk_object_ref(GTK_OBJECT(obj)); +//void gst_object_unref(GstObject *object); +#define gst_object_unref(obj) gtk_object_unref(GTK_OBJECT(obj)); +//void gst_object_sink(GstObject *object); +#define gst_object_sink(obj) gtk_object_sink(GTK_OBJECT(obj)); + +/* destroying an object */ +#define gst_object_destroy(obj) gtk_object_destroy(GTK_OBJECT(obj)) + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_OBJECT_H__ */ + diff --git a/gst/gstpad.c b/gst/gstpad.c new file mode 100644 index 0000000000..8f21e1a082 --- /dev/null +++ b/gst/gstpad.c @@ -0,0 +1,340 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include +#include +#include + + +/* Pad signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_pad_class_init(GstPadClass *klass); +static void gst_pad_init(GstPad *pad); +static void gst_pad_real_destroy(GtkObject *object); + + +static GstObject *parent_class = NULL; +static guint gst_pad_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_pad_get_type(void) { + static GtkType pad_type = 0; + + if (!pad_type) { + static const GtkTypeInfo pad_info = { + "GstPad", + sizeof(GstPad), + sizeof(GstPadClass), + (GtkClassInitFunc)gst_pad_class_init, + (GtkObjectInitFunc)gst_pad_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + pad_type = gtk_type_unique(GST_TYPE_OBJECT,&pad_info); + } + return pad_type; +} + +static void +gst_pad_class_init(GstPadClass *klass) { + GtkObjectClass *gtkobject_class; + + gtkobject_class = (GtkObjectClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_OBJECT); + + gtkobject_class->destroy = gst_pad_real_destroy; +} + +static void gst_pad_init(GstPad *pad) { + pad->type = 0; + pad->direction = GST_PAD_UNKNOWN; + pad->peer = NULL; + pad->chain = NULL; + pad->parent = NULL; + pad->ghostparents = NULL; +} + +/** + * gst_pad_new: + * @name: name of new pad + * @direction: either GST_PAD_SRC or GST_PAD_SINK + * + * Create a new pad with given name. + * + * Returns: new pad + */ +GstPad *gst_pad_new(gchar *name,GstPadDirection direction) { + GstPad *pad; + + g_return_if_fail(name != NULL); + g_return_if_fail(direction != GST_PAD_UNKNOWN); + + pad = GST_PAD(gtk_type_new(gst_pad_get_type())); + pad->name = g_strdup(name); + pad->direction = direction; + return pad; +} + +GstPadDirection gst_pad_get_direction(GstPad *pad) { + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + + return pad->direction; +} + +void gst_pad_set_name(GstPad *pad,gchar *name) { + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + + if (pad->name != NULL) + g_free(pad->name); + + pad->name = g_strdup(name); +} + +gchar *gst_pad_get_name(GstPad *pad) { + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + + return pad->name; +} + +void gst_pad_set_chain_function(GstPad *pad,GstPadChainFunction chain) { + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + + pad->chain = chain; +} + +void gst_pad_push(GstPad *pad,GstBuffer *buffer) { + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(buffer != NULL); + + gst_trace_add_entry(NULL,0,buffer,"push buffer"); + // if the chain function exists for the pad, call it directly + if (pad->chain) + (pad->chain)(pad->peer,buffer); + // else we're likely going to have to coroutine it + else { + pad->peer->bufpen = buffer; + g_print("would switch to a coroutine here...\n"); + if (!GST_IS_ELEMENT(pad->peer->parent)) + g_print("eek, this isn't an element!\n"); + if (GST_ELEMENT(pad->peer->parent)->threadstate != NULL) + cothread_switch(GST_ELEMENT(pad->peer->parent)->threadstate); + } +} + +GstBuffer *gst_pad_pull(GstPad *pad) { + GstBuffer *buf; + GstElement *peerparent; + cothread_state *state; + + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + + if (pad->bufpen == NULL) { + g_print("no buffer available, will have to do something about it\n"); + peerparent = GST_ELEMENT(pad->peer->parent); + // if they're a cothread too, we can just switch to them + if (peerparent->threadstate != NULL) { + cothread_switch(peerparent->threadstate); + // otherwise we have to switch to the main thread + } else { + state = cothread_main(GST_ELEMENT(pad->parent)->threadstate->ctx); + g_print("switching to supposed 0th thread at %p\n",state); + cothread_switch(state); + } + } else { + g_print("buffer available, pulling\n"); + buf = pad->bufpen; + pad->bufpen = NULL; + return buf; + } +} + +void gst_pad_chain(GstPad *pad) { + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(pad->peer != NULL); + g_return_if_fail(pad->chain != NULL); + + if (pad->bufpen) + (pad->chain)(pad,pad->bufpen); +} + +void gst_pad_connect(GstPad *srcpad,GstPad *sinkpad) { + GstPad *temppad; + + /* generic checks */ + g_return_if_fail(srcpad != NULL); + g_return_if_fail(GST_IS_PAD(srcpad)); + g_return_if_fail(srcpad->peer == NULL); + g_return_if_fail(sinkpad != NULL); + g_return_if_fail(GST_IS_PAD(sinkpad)); + g_return_if_fail(sinkpad->peer == NULL); +// g_return_if_fail(sinkpad->chain != NULL); + + /* check for reversed directions and swap if necessary */ + if ((srcpad->direction == GST_PAD_SINK) && + (sinkpad->direction == GST_PAD_SRC)) { + temppad = srcpad; + srcpad = sinkpad; + sinkpad = temppad; + } + g_return_if_fail((srcpad->direction == GST_PAD_SRC) && + (sinkpad->direction == GST_PAD_SINK)); + + /* first set peers */ + srcpad->peer = sinkpad; + sinkpad->peer = srcpad; + + /* now copy the chain pointer from sink to src */ + srcpad->chain = sinkpad->chain; + + /* set the connected flag */ + /* FIXME: set connected flag */ +} + +void gst_pad_set_parent(GstPad *pad,GstObject *parent) { + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(pad->parent == NULL); + g_return_if_fail(parent != NULL); + g_return_if_fail(GTK_IS_OBJECT(parent)); + g_return_if_fail((gpointer)pad != (gpointer)parent); + + pad->parent = parent; +} + +void gst_pad_add_ghost_parent(GstPad *pad,GstObject *parent) { + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(parent != NULL); + g_return_if_fail(GTK_IS_OBJECT(parent)); + + pad->ghostparents = g_list_prepend(pad->ghostparents,parent); +} + + +void gst_pad_remove_ghost_parent(GstPad *pad,GstObject *parent) { + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(parent != NULL); + g_return_if_fail(GTK_IS_OBJECT(parent)); + + pad->ghostparents = g_list_remove(pad->ghostparents,parent); +} + +GstObject *gst_pad_get_parent(GstPad *pad) { + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + + return pad->parent; +} + +GList *gst_pad_get_ghost_parents(GstPad *pad) { + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + + return pad->ghostparents; +} + +guint32 gst_pad_get_type_id(GstPad *pad) { + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + + return pad->type; +} + +void gst_pad_set_type_id(GstPad *pad,guint16 id) { + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(gst_type_find_by_id(id) != NULL); + + pad->type = id; +} + +GstPad *gst_pad_get_peer(GstPad *pad) { + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + + return pad->peer; +} + +GstPadDirection gst_pad_get_directory(GstPad *pad) { + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + + return pad->direction; +} + +static void gst_pad_real_destroy(GtkObject *object) { + GstPad *pad = GST_PAD(object); + +// g_print("in gst_pad_real_destroy()\n"); + + if (pad->name) + g_free(pad->name); + g_list_free(pad->ghostparents); +} + +xmlNodePtr gst_pad_save_thyself(GstPad *pad,xmlNodePtr parent) { + xmlNodePtr self; + GstPad *peer; + + self = xmlNewChild(parent,NULL,"pad",NULL); + xmlNewChild(self,NULL,"name",pad->name); + if (pad->peer != NULL) { + peer = pad->peer; + // first check to see if the peer's parent's parent is the same + if (pad->parent->parent == peer->parent->parent) + // we just save it off + xmlNewChild(self,NULL,"peer",g_strdup_printf("%s.%s", + GST_ELEMENT(peer->parent)->name,peer->name)); + } else + xmlNewChild(self,NULL,"peer",""); + + return self; +} + +xmlNodePtr gst_pad_ghost_save_thyself(GstPad *pad,GstElement *bin,xmlNodePtr parent) { + xmlNodePtr self; + GstPad *peer; + + self = xmlNewChild(parent,NULL,"ghostpad",NULL); + xmlNewChild(self,NULL,"name",pad->name); + xmlNewChild(self,NULL,"parent",GST_ELEMENT(pad->parent)->name); + + return self; +} diff --git a/gst/gstpad.h b/gst/gstpad.h new file mode 100644 index 0000000000..f2deeed39a --- /dev/null +++ b/gst/gstpad.h @@ -0,0 +1,127 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_PAD_H__ +#define __GST_PAD_H__ + + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GST_TYPE_PAD \ + (gst_pad_get_type()) +#define GST_PAD(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_PAD,GstPad)) +#define GST_PAD_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_PAD,GstPadClass)) +#define GST_IS_PAD(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_PAD)) +#define GST_IS_PAD_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_PAD))) + +// quick test to see if the pad is connected +#define GST_PAD_CONNECTED(pad) ((pad)->peer != NULL) + +typedef struct _GstPad GstPad; +typedef struct _GstPadClass GstPadClass; + +/* this defines the functions used to chain buffers + * pad is the sink pad (so the same chain function can be used for N pads) + * buf is the buffer being passed */ +typedef void (*GstPadChainFunction) (GstPad *pad,GstBuffer *buf); +typedef void (*GstPadPushFunction) (GstPad *pad); + +typedef enum { + GST_PAD_UNKNOWN, + GST_PAD_SRC, + GST_PAD_SINK, +} GstPadDirection; + +//typedef enum { +//} GstPadFlags; + +struct _GstPad { + GstObject object; + + gchar *name; + guint16 type; + + GstPadDirection direction; + + GstPad *peer; + + GstBuffer *bufpen; + + GstPadChainFunction chain; + + GstObject *parent; + GList *ghostparents; +}; + +struct _GstPadClass { + GstObjectClass parent_class; +}; + +GtkType gst_pad_get_type(void); +GstPad *gst_pad_new(gchar *name,GstPadDirection direction); +void gst_pad_destroy(GstPad *pad); + +GstPadDirection gst_pad_get_direction(GstPad *pad); +void gst_pad_set_chain_function(GstPad *pad,GstPadChainFunction chain); + +guint32 gst_pad_get_type_id(GstPad *pad); +void gst_pad_set_type_id(GstPad *pad,guint16 id); + +void gst_pad_set_name(GstPad *pad,gchar *name); +gchar *gst_pad_get_name(GstPad *pad); +#define gst_pad_destroy(pad) gst_object_destroy(GST_OBJECT(pad)) + +GstPadDirection gst_pad_get_directory(GstPad *pad); + +void gst_pad_set_parent(GstPad *pad,GstObject *parent); +void gst_pad_add_ghost_parent(GstPad *pad,GstObject *parent); +void gst_pad_remove_ghost_parent(GstPad *pad,GstObject *parent); +GstObject *gst_pad_get_parent(GstPad *pad); +GList *gst_pad_get_ghost_parents(GstPad *pad); + +GstPad *gst_pad_get_peer(GstPad *pad); + +void gst_pad_connect(GstPad *srcpad,GstPad *sinkpad); + +void gst_pad_push(GstPad *pad,GstBuffer *buffer); +GstBuffer *gst_pad_pull(GstPad *pad); + +xmlNodePtr gst_pad_save_thyself(GstPad *pad,xmlNodePtr parent); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_PAD_H__ */ + diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c new file mode 100644 index 0000000000..54d9f6f45b --- /dev/null +++ b/gst/gstpipeline.c @@ -0,0 +1,134 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +GstElementDetails gst_pipeline_details = { + "Pipeline object", + "Bin", + "Complete pipeline object", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* Pipeline signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_pipeline_class_init(GstPipelineClass *klass); +static void gst_pipeline_init(GstPipeline *pipeline); + +static gboolean gst_pipeline_change_state(GstElement *element, + GstElementState state); + +static void gst_pipeline_prepare(GstPipeline *pipeline); + + +static GstBin *parent_class = NULL; +static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_pipeline_get_type(void) { + static GtkType pipeline_type = 0; + + if (!pipeline_type) { + static const GtkTypeInfo pipeline_info = { + "GstPipeline", + sizeof(GstPipeline), + sizeof(GstPipelineClass), + (GtkClassInitFunc)gst_pipeline_class_init, + (GtkObjectInitFunc)gst_pipeline_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + pipeline_type = gtk_type_unique(gst_bin_get_type(),&pipeline_info); + } + return pipeline_type; +} + +static void +gst_pipeline_class_init(GstPipelineClass *klass) { + GstElementClass *gstelement_class; + + gstelement_class = (GstElementClass*)klass; + + parent_class = gtk_type_class(gst_bin_get_type()); + + gstelement_class->change_state = gst_pipeline_change_state; +} + +static void gst_pipeline_init(GstPipeline *pipeline) { +} + +GstPipeline *gst_pipeline_new(guchar *name) { + GstPipeline *pipeline; + + pipeline = gtk_type_new(gst_pipeline_get_type()); + gst_element_set_name(GST_ELEMENT(pipeline),name); + return pipeline; +} + +static void gst_pipeline_prepare(GstPipeline *pipeline) { + g_print("preparing pipeline for playing\n"); +} + + +static gboolean gst_pipeline_change_state(GstElement *element, + GstElementState state) { + GstPipeline *pipeline; + + g_return_if_fail(GST_IS_PIPELINE(element)); + pipeline = GST_PIPELINE(element); + + switch (state) { + case GST_STATE_RUNNING: + /* we need to set up internal state */ + g_print("preparing pipeline \"%s\" for iterations:\n", + gst_element_get_name(GST_ELEMENT(element))); + gst_pipeline_prepare(pipeline); + break; + case ~GST_STATE_RUNNING: + /* tear down the internal state */ + g_print("tearing down pipelines's iteration state\n"); + break; + default: + break; + } + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + return TRUE; +} + + +void gst_pipeline_iterate(GstPipeline *pipeline) { + g_return_if_fail(pipeline != NULL); + g_return_if_fail(GST_IS_PIPELINE(pipeline)); +} diff --git a/gst/gstpipeline.h b/gst/gstpipeline.h new file mode 100644 index 0000000000..589d02be8f --- /dev/null +++ b/gst/gstpipeline.h @@ -0,0 +1,69 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_PIPELINE_H__ +#define __GST_PIPELINE_H__ + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +GstElementDetails gst_pipeline_details; + + +#define GST_TYPE_PIPELINE \ + (gst_pipeline_get_type()) +#define GST_PIPELINE(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_PIPELINE,GstPipeline)) +#define GST_PIPELINE_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_PIPELINE,GstPipelineClass)) +#define GST_IS_PIPELINE(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_PIPELINE)) +#define GST_IS_PIPELINE_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_PIPELINE))) + +typedef struct _GstPipeline GstPipeline; +typedef struct _GstPipelineClass GstPipelineClass; + +struct _GstPipeline { + GstBin bin; +}; + +struct _GstPipelineClass { + GstBinClass parent_class; +}; + +GtkType gst_pipeline_get_type(void); +GstPipeline *gst_pipeline_new(guchar *name); +#define gst_pipeline_destroy(pipeline) gst_object_destroy(GST_OBJECT(pipeline)) + +void gst_pipeline_iterate(GstPipeline *pipeline); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_PIPELINE_H__ */ + diff --git a/gst/gstplugin.c b/gst/gstplugin.c new file mode 100644 index 0000000000..c7ca3745af --- /dev/null +++ b/gst/gstplugin.c @@ -0,0 +1,297 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include +#include +#include +#include + +#include + + +/* list of loaded modules and its sequence number */ +GList *_gst_modules; +gint _gst_modules_seqno; +/* global list of plugins and its sequence number */ +GList *_gst_plugins; +gint _gst_plugins_seqno; +/* list of paths to check for plugins */ +GList *_gst_plugin_paths; + +/* whether or not to spew library load issues */ +gboolean _gst_plugin_spew = FALSE; + + +void _gst_plugin_initialize() { + _gst_modules = NULL; + _gst_modules_seqno = 0; + _gst_plugins = NULL; + _gst_plugins_seqno = 0; + _gst_plugin_paths = NULL; + + /* add the main (installed) library path */ + _gst_plugin_paths = g_list_prepend(_gst_plugin_paths,PLUGINS_DIR); + + /* if this is set, we add build-directory paths to the list */ +#ifdef PLUGINS_USE_SRCDIR + /* the catch-all plugins directory */ + _gst_plugin_paths = g_list_prepend(_gst_plugin_paths, + PLUGINS_SRCDIR "/plugins"); + /* location libgstelements.so */ + _gst_plugin_paths = g_list_prepend(_gst_plugin_paths, + PLUGINS_SRCDIR "/gst/elements"); + _gst_plugin_paths = g_list_prepend(_gst_plugin_paths, + PLUGINS_SRCDIR "/gst/types"); +#endif /* PLUGINS_USE_SRCDIR */ +} + +static gboolean gst_plugin_load_recurse(gchar *directory,gchar *name) { + DIR *dir; + struct dirent *dirent; + gboolean loaded = FALSE; + + dir = opendir(directory); + if (dir) { + while (dirent = readdir(dir)) { + /* don't want to recurse in place or backwards */ + if (strcmp(dirent->d_name,".") && strcmp(dirent->d_name,"..")) { + gst_plugin_load_recurse(g_strjoin("/",directory,dirent->d_name, + NULL),name); + } + } + closedir(dir); + } else { + if (strstr(directory,".so")) { + gchar *temp; + if (name) { + if ((temp = strstr(directory,name)) && + (!strcmp(temp,name))) { + gst_plugin_load_absolute(directory); + return TRUE; + } + } else if ((temp = strstr(directory,".so")) && + (!strcmp(temp,".so"))) { + gst_plugin_load_absolute(directory); + loaded = TRUE; + } + } + } + return loaded; +} + +/** + * gst_plugin_load_all: + * + * Load all plugins in the path. + */ +void gst_plugin_load_all() { + GList *path; + + path = _gst_plugin_paths; + while (path != NULL) { + gst_plugin_load_recurse(path->data,NULL); + path = g_list_next(path); + } +} + +/** + * gst_plugin_load: + * @name: name of plugin to load + * + * Load the named plugin. Name should be given as + * "libplugin.so". + * + * Returns: whether the plugin was loaded or not + */ +gboolean gst_plugin_load(gchar *name) { + GList *path; + gchar *libspath; + +// g_print("attempting to load plugin '%s'\n",name); + + path = _gst_plugin_paths; + while (path != NULL) { + if (gst_plugin_load_absolute(g_module_build_path(path->data,name))) + return TRUE; + libspath = g_strconcat(path->data,"/.libs",NULL); +// g_print("trying to load '%s'\n",g_module_build_path(libspath,name)); + if (gst_plugin_load_absolute(g_module_build_path(libspath,name))) { + g_free(libspath); + return TRUE; + } + g_free(libspath); +// g_print("trying to load '%s' from '%s'\n",name,path->data); + if (gst_plugin_load_recurse(path->data,name)) { + return TRUE; + } + path = g_list_next(path); + } + return FALSE; +} + +/** + * gst_plugin_load_absolute: + * @name: name of plugin to load + * + * Returns: whether or not the plugin loaded + */ +gboolean gst_plugin_load_absolute(gchar *name) { + GModule *module; + GstPluginInitFunc initfunc; + GstPlugin *plugin; + +// g_print("trying to load '%s\n",name); + + if (g_module_supported() == FALSE) { + g_print("wow, you built this on a platform without dynamic loading???\n"); + return; + } + + module = g_module_open(name,0); + if (module != NULL) { + if (g_module_symbol(module,"plugin_init",(gpointer *)&initfunc)) { + if (plugin = (initfunc)(module)) { + GList *factories; + plugin->filename = g_strdup(name); + _gst_modules = g_list_append(_gst_modules,module); + _gst_modules_seqno++; + _gst_plugins = g_list_append(_gst_plugins,plugin); + _gst_plugins_seqno++; + factories = plugin->elements; + while (factories) { + gst_elementfactory_register((GstElementFactory*)(factories->data)); + factories = g_list_next(factories); + } + return TRUE; + } + } + } else if (_gst_plugin_spew) { +// if (strstr(g_module_error(),"No such") == NULL) + gst_info("error loading plugin: %s\n",g_module_error()); + } + + return FALSE; +} + +/** + * gst_plugin_new: + * @name: name of new plugin + * + * Create a new plugin with given name. + * + * Returns: new plugin + */ +GstPlugin *gst_plugin_new(gchar *name) { + GstPlugin *plugin = (GstPlugin *)malloc(sizeof(GstPlugin)); + + plugin->name = g_strdup(name); + plugin->longname = NULL; + plugin->types = NULL; + plugin->elements = NULL; + + return plugin; +} + +/** + * gst_plugin_set_longname: + * @plugin: plugin to set long name of + * @longname: new long name + * + * Sets the long name (should be descriptive) of the plugin. + */ +void gst_plugin_set_longname(GstPlugin *plugin,gchar *longname) { + g_return_if_fail(plugin != NULL); + + if (plugin->longname) g_free(plugin->longname); + plugin->longname = g_strdup(longname); +} + +/** + * gst_plugin_find: + * @name: name of plugin to find + * + * Search the list of registered plugins for one of the given name + * + * Returns: pointer to the #GstPlugin if found, NULL otherwise + */ +GstPlugin *gst_plugin_find(gchar *name) { + GList *plugins = _gst_plugins; + + g_return_if_fail(name != NULL); + + while (plugins) { + GstPlugin *plugin = (GstPlugin *)plugins->data; +// g_print("plugin name is '%s'\n",plugin->name); + if (plugin->name) { + if (!strcmp(plugin->name,name)) + return plugin; + } + plugins = g_list_next(plugins); + } + return NULL; +} + +/** + * gst_plugin_find_elementfactory: + * @name: name of elementfactory to find + * + * Find a registered elementfactory by name. + * + * Returns: @GstElementFactory if found, NULL if not + */ +GstElementFactory *gst_plugin_find_elementfactory(gchar *name) { + GList *plugins, *factories; + GstElementFactory *factory; + + g_return_if_fail(name != NULL); + + plugins = _gst_plugins; + while (plugins) { + factories = ((GstPlugin *)(plugins->data))->elements; + while (factories) { + factory = (GstElementFactory*)(factories->data); + if (!strcmp(gst_element_get_name(GST_ELEMENT(factory)),name)) + return (GstElementFactory*)(factory); + factories = g_list_next(factories); + } + plugins = g_list_next(plugins); + } + + return NULL; +} + +/** + * gst_plugin_add_factory: + * @plugin: plugin to add factory to + * @factory: factory to add + * + * Add factory to the list of those provided by the element. + */ +void gst_plugin_add_factory(GstPlugin *plugin,GstElementFactory *factory) { + g_return_if_fail(plugin != NULL); + g_return_if_fail(factory != NULL); + +// g_print("adding factory to plugin\n"); + plugin->elements = g_list_append(plugin->elements,factory); +} + +GList *gst_plugin_get_list() { + return _gst_plugins; +} diff --git a/gst/gstplugin.h b/gst/gstplugin.h new file mode 100644 index 0000000000..164ca85b69 --- /dev/null +++ b/gst/gstplugin.h @@ -0,0 +1,63 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_PLUGIN_H__ +#define __GST_PLUGIN_H__ + + +#include + +#include +#include + +#include "config.h" + + +typedef struct _GstPlugin GstPlugin; +typedef struct _GstPluginElement GstPluginElement; + +struct _GstPlugin { + gchar *name; /* name of the plugin */ + gchar *longname; /* long name of plugin */ + gchar *filename; /* filename it came from */ + + GList *types; /* list of types provided */ + GList *elements; /* list of elements provided */ + GList *identifiers; /* list of identifiers */ +}; + + +typedef GstPlugin * (*GstPluginInitFunc) (GModule *module); + +GstPlugin *gst_plugin_new(gchar *name); +void gst_plugin_set_longname(GstPlugin *plugin,gchar *longname); + +void gst_plugin_init(); +void gst_plugin_load_all(); +gboolean gst_plugin_load(gchar *name); +gboolean gst_plugin_load_absolute(gchar *name); + +void gst_plugin_add_factory(GstPlugin *plugin,GstElementFactory *factory); + +GstPlugin *gst_plugin_find(gchar *name); +GList *gst_plugin_get_list(); +GstElementFactory *gst_plugin_find_elementfactory(gchar *name); + +#endif /* __GST_PLUGIN_H__ */ diff --git a/gst/gstsink.c b/gst/gstsink.c new file mode 100644 index 0000000000..26de07ee27 --- /dev/null +++ b/gst/gstsink.c @@ -0,0 +1,79 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + + +/* Sink signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_sink_class_init(GstSinkClass *klass); +static void gst_sink_init(GstSink *sink); + + +static GstElementClass *parent_class = NULL; +static guint gst_sink_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_sink_get_type(void) { + static GtkType sink_type = 0; + + if (!sink_type) { + static const GtkTypeInfo sink_info = { + "GstSink", + sizeof(GstSink), + sizeof(GstSinkClass), + (GtkClassInitFunc)gst_sink_class_init, + (GtkObjectInitFunc)gst_sink_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + sink_type = gtk_type_unique(GST_TYPE_ELEMENT,&sink_info); + } + return sink_type; +} + +static void +gst_sink_class_init(GstSinkClass *klass) { + GtkObjectClass *gtkobject_class; + + gtkobject_class = (GtkObjectClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_ELEMENT); +} + +static void gst_sink_init(GstSink *sink) { +} + +GstObject *gst_sink_new(gchar *name) { + GstObject *sink = GST_OBJECT(gtk_type_new(GST_TYPE_SINK)); + gst_element_set_name(GST_ELEMENT(sink),name); + return sink; +} diff --git a/gst/gstsink.h b/gst/gstsink.h new file mode 100644 index 0000000000..44c3f7ab35 --- /dev/null +++ b/gst/gstsink.h @@ -0,0 +1,64 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_SINK_H__ +#define __GST_SINK_H__ + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GST_TYPE_SINK \ + (gst_sink_get_type()) +#define GST_SINK(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_SINK,GstSink)) +#define GST_SINK_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_SINK,GstSinkClass)) +#define GST_IS_SINK(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_SINK)) +#define GST_IS_SINK_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_SINK))) + +typedef struct _GstSink GstSink; +typedef struct _GstSinkClass GstSinkClass; + +struct _GstSink { + GstElement element; +}; + +struct _GstSinkClass { + GstElementClass parent_class; +}; + +GtkType gst_sink_get_type(void); +GstObject *gst_sink_new(gchar *name); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_SINK_H__ */ diff --git a/gst/gstsrc.c b/gst/gstsrc.c new file mode 100644 index 0000000000..472cd29be0 --- /dev/null +++ b/gst/gstsrc.c @@ -0,0 +1,122 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + + +/* Src signals and args */ +enum { + EOS, + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_src_class_init(GstSrcClass *klass); +static void gst_src_init(GstSrc *src); + + +static GstElementClass *parent_class = NULL; +static guint gst_src_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_src_get_type(void) { + static GtkType src_type = 0; + + if (!src_type) { + static const GtkTypeInfo src_info = { + "GstSrc", + sizeof(GstSrc), + sizeof(GstSrcClass), + (GtkClassInitFunc)gst_src_class_init, + (GtkObjectInitFunc)gst_src_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + src_type = gtk_type_unique(GST_TYPE_ELEMENT,&src_info); + } + return src_type; +} + +static void +gst_src_class_init(GstSrcClass *klass) { + GtkObjectClass *gtkobject_class; + + gtkobject_class = (GtkObjectClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_ELEMENT); + + gst_src_signals[EOS] = + gtk_signal_new("eos",GTK_RUN_LAST,gtkobject_class->type, + GTK_SIGNAL_OFFSET(GstSrcClass,eos), + gtk_marshal_NONE__POINTER,GTK_TYPE_NONE,1, + GTK_TYPE_POINTER); + gtk_object_class_add_signals(gtkobject_class,gst_src_signals,LAST_SIGNAL); +} + +static void gst_src_init(GstSrc *src) { + src->flags = 0; +} + +void gst_src_signal_eos(GstSrc *src) { + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_SRC(src)); + + gtk_signal_emit(GTK_OBJECT(src),gst_src_signals[EOS],src); +} + +void gst_src_push(GstSrc *src) { + GstSrcClass *oclass; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_SRC(src)); + + oclass = (GstSrcClass *)(GTK_OBJECT(src)->klass); + + g_return_if_fail(oclass->push != NULL); + + (oclass->push)(src); +} + +/** + * gst_src_push_region: + * @src: source to trigger the push of + * @offset: offset in source + * @size: number of bytes to push + * + * Push a buffer of a given size from the source. + */ +void gst_src_push_region(GstSrc *src,gulong offset,gulong size) { + GstSrcClass *oclass; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_SRC(src)); + + oclass = (GstSrcClass *)(GTK_OBJECT(src)->klass); + + g_return_if_fail(oclass->push_region != NULL); + + (oclass->push_region)(src,offset,size); +} + diff --git a/gst/gstsrc.h b/gst/gstsrc.h new file mode 100644 index 0000000000..75405efd0d --- /dev/null +++ b/gst/gstsrc.h @@ -0,0 +1,86 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_SRC_H__ +#define __GST_SRC_H__ + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GST_TYPE_SRC \ + (gst_src_get_type()) +#define GST_SRC(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_SRC,GstSrc)) +#define GST_SRC_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_SRC,GstSrcClass)) +#define GST_IS_SRC(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_SRC)) +#define GST_IS_SRC_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_SRC))) + +typedef enum { + GST_SRC_ASYNC = 1 << 0, +} GstSrcFlags; + +#define GST_SRC_FLAGS(obj) (GST_SRC(obj)->flags) +#define GST_SRC_ASYNC(obj) ((GST_SRC_FLAGS(obj) & GST_SRC_ASYNC) + +typedef struct _GstSrc GstSrc; +typedef struct _GstSrcClass GstSrcClass; + +struct _GstSrc { + GstElement element; + gint32 flags; +}; + +struct _GstSrcClass { + GstElementClass parent_class; + + /* subclass functions */ + void (*push) (GstSrc *src); + void (*push_region) (GstSrc *src,gulong offset,gulong size); + + /* signals */ + void (*eos) (GstSrc *src); +}; + +#define GST_SRC_SET_FLAGS(src,flag) G_STMT_START{ (GST_SRC_FLAGS (src) |= (flag)); }G_STMT_END +#define GST_SRC_UNSET_FLAGS(src,flag) G_STMT_START{ (GST_SRC_FLAGS (src) &= ~(flag)); }G_STMT_END + + +GtkType gst_src_get_type(void); + +void gst_src_signal_eos(GstSrc *src); + +void gst_src_push(GstSrc *src); +void gst_src_push_region(GstSrc *src,gulong offset,gulong size); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_SRC_H__ */ diff --git a/gst/gsttee.c b/gst/gsttee.c new file mode 100644 index 0000000000..13ceaefa62 --- /dev/null +++ b/gst/gsttee.c @@ -0,0 +1,130 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + + +GstElementDetails gst_tee_details = { + "Tee pipe fitting", + "Tee", + "1ot-N pipe fitting", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + +/* Tee signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_tee_class_init(GstTeeClass *klass); +static void gst_tee_init(GstTee *tee); + +static xmlNodePtr gst_tee_save_thyself(GstElement *element,xmlNodePtr parent); + + +static GstFilterClass *parent_class = NULL; +static guint gst_tee_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_tee_get_type(void) { + static GtkType tee_type = 0; + + if (!tee_type) { + static const GtkTypeInfo tee_info = { + "GstTee", + sizeof(GstTee), + sizeof(GstTeeClass), + (GtkClassInitFunc)gst_tee_class_init, + (GtkObjectInitFunc)gst_tee_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + tee_type = gtk_type_unique(GST_TYPE_FILTER,&tee_info); + } + return tee_type; +} + +static void +gst_tee_class_init(GstTeeClass *klass) { + GstFilterClass *gstfilter_class; + + gstfilter_class = (GstFilterClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_FILTER); +} + +static void gst_tee_init(GstTee *tee) { + tee->sinkpad = gst_pad_new("sink",GST_PAD_SINK); + gst_element_add_pad(GST_ELEMENT(tee),tee->sinkpad); + gst_pad_set_chain_function(tee->sinkpad,gst_tee_chain); + + tee->numsrcpads = 0; + tee->srcpads = NULL; +} + +GstElement *gst_tee_new(gchar *name) { + GstElement *tee = GST_ELEMENT(gtk_type_new(GST_TYPE_TEE)); + gst_element_set_name(GST_ELEMENT(tee),name); + return tee; +} + +gchar *gst_tee_new_pad(GstTee *tee) { + gchar *name; + GstPad *srcpad; + + g_return_if_fail(tee != NULL); + g_return_if_fail(GST_IS_TEE(tee)); + + name = g_strdup_printf("src%d",tee->numsrcpads); + srcpad = gst_pad_new(name,GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(tee),srcpad); + tee->srcpads = g_slist_prepend(tee->srcpads,srcpad); + tee->numsrcpads++; + return name; +} + +void gst_tee_chain(GstPad *pad,GstBuffer *buf) { + GstTee *tee; + GSList *srcpads; + int i; + + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(buf != NULL); + + tee = GST_TEE(pad->parent); + gst_trace_add_entry(NULL,0,buf,"tee buffer"); + for (i=0;inumsrcpads-1;i++) + gst_buffer_ref(buf); + srcpads = tee->srcpads; + while (srcpads) { + gst_pad_push(GST_PAD(srcpads->data),buf); + srcpads = g_slist_next(srcpads); + } +} diff --git a/gst/gsttee.h b/gst/gsttee.h new file mode 100644 index 0000000000..1953325bb3 --- /dev/null +++ b/gst/gsttee.h @@ -0,0 +1,70 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_TEE_H__ +#define __GST_TEE_H__ + + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GST_TYPE_TEE \ + (gst_tee_get_type()) +#define GST_TEE(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_TEE,GstTee)) +#define GST_TEE_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_TEE,GstTeeClass)) +#define GST_IS_TEE(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_TEE)) +#define GST_IS_TEE_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_TEE))) + +typedef struct _GstTee GstTee; +typedef struct _GstTeeClass GstTeeClass; + +struct _GstTee { + GstFilter filter; + + GstPad *sinkpad; + + gint numsrcpads; + GSList *srcpads; +}; + +struct _GstTeeClass { + GstFilterClass parent_class; +}; + +GtkType gst_tee_get_type(void); +GstElement *gst_tee_new(gchar *name); +void gst_tee_chain(GstPad *pad,GstBuffer *buf); +gchar *gst_tee_new_pad(GstTee *tee); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_TEE_H__ */ diff --git a/gst/gstthread.c b/gst/gstthread.c new file mode 100644 index 0000000000..001dd684f5 --- /dev/null +++ b/gst/gstthread.c @@ -0,0 +1,332 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +GstElementDetails gst_thread_details = { + "Threaded container", + "Bin", + "Container that creates/manages a thread", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* Thread signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_CREATE_THREAD, +}; + + +static void gst_thread_class_init(GstThreadClass *klass); +static void gst_thread_init(GstThread *thread); + +static void gst_thread_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_thread_get_arg(GtkObject *object,GtkArg *arg,guint id); +static gboolean gst_thread_change_state(GstElement *element, + GstElementState state); + +static xmlNodePtr gst_thread_save_thyself(GstElement *element,xmlNodePtr parent); + +static void gst_thread_prepare(GstThread *thread); +static void gst_thread_signal_thread(GstThread *thread); + + +static GstBin *parent_class = NULL; +static guint gst_thread_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_thread_get_type(void) { + static GtkType thread_type = 0; + + if (!thread_type) { + static const GtkTypeInfo thread_info = { + "GstThread", + sizeof(GstThread), + sizeof(GstThreadClass), + (GtkClassInitFunc)gst_thread_class_init, + (GtkObjectInitFunc)gst_thread_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + thread_type = gtk_type_unique(gst_bin_get_type(),&thread_info); + } + return thread_type; +} + +static void +gst_thread_class_init(GstThreadClass *klass) { + GtkObjectClass *gtkobject_class; + GstObjectClass *gstobject_class; + GstElementClass *gstelement_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstobject_class = (GstObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + + parent_class = gtk_type_class(gst_bin_get_type()); + + gtk_object_add_arg_type("GstThread::create_thread", GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_CREATE_THREAD); + + gstelement_class->change_state = gst_thread_change_state; +// gstelement_class->save_thyself = gst_thread_save_thyself; + + gtkobject_class->set_arg = gst_thread_set_arg; + gtkobject_class->get_arg = gst_thread_get_arg; +} + +static void gst_thread_init(GstThread *thread) { + GST_FLAG_SET(thread,GST_THREAD_CREATE); + + thread->entries = NULL; + thread->numentries = 0; + + thread->lock = g_mutex_new(); + thread->cond = g_cond_new(); +} + +static void gst_thread_set_arg(GtkObject *object,GtkArg *arg,guint id) { + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_THREAD(object)); + + switch(id) { + case ARG_CREATE_THREAD: + if (GTK_VALUE_BOOL(*arg)) { + gst_info("turning ON the creation of the thread\n"); + GST_FLAG_SET(object,GST_THREAD_CREATE); + gst_info("flags are 0x%08x\n",GST_FLAGS(object)); + } else { + gst_info("turning OFF the creation of the thread\n"); + GST_FLAG_UNSET(object,GST_THREAD_CREATE); + gst_info("flags are 0x%08x\n",GST_FLAGS(object)); + } + break; + default: + break; + } +} + +static void gst_thread_get_arg(GtkObject *object,GtkArg *arg,guint id) { + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_THREAD(object)); + + switch(id) { + case ARG_CREATE_THREAD: + GTK_VALUE_BOOL(*arg) = GST_FLAG_IS_SET(object,GST_THREAD_CREATE); + break; + default: + break; + } +} + + +GstElement *gst_thread_new(guchar *name) { + GstThread *thread; + + thread = gtk_type_new(gst_thread_get_type()); + gst_element_set_name(GST_ELEMENT(thread),name); + return GST_ELEMENT(thread); +} + + +static void gst_thread_prepare(GstThread *thread) { + GList *elements; + GstElement *element; + GList *pads; + GstPad *pad, *peer; + GstElement *outside; + + thread->numentries = 0; + + /* first we need to find all the entry points into the thread */ + elements = GST_BIN(thread)->children; + while (elements) { + element = GST_ELEMENT(elements->data); + if (GST_IS_SRC(element)) { + gst_info("element \"%s\" is a source entry point for the thread\n", + gst_element_get_name(GST_ELEMENT(element))); + thread->entries = g_list_prepend(thread->entries,element); + thread->numentries++; + } else { + /* go through the list of pads to see if there's a Connection */ + pads = gst_element_get_pad_list(element); + while (pads) { + pad = GST_PAD(pads->data); + /* we only worry about sink pads */ + if (gst_pad_get_direction(pad) == GST_PAD_SINK) { + /* get the pad's peer */ + peer = gst_pad_get_peer(pad); + if (!peer) break; + /* get the parent of the peer of the pad */ + outside = GST_ELEMENT(gst_pad_get_parent(peer)); + if (!outside) break; + /* if it's a connection and it's not ours... */ + if (GST_IS_CONNECTION(outside) && + (gst_object_get_parent(GST_OBJECT(outside)) != GST_OBJECT(thread))) { + gst_info("element \"%s\" is the external source Connection \ +for internal element \"%s\"\n", + gst_element_get_name(GST_ELEMENT(outside)), + gst_element_get_name(GST_ELEMENT(element))); + thread->entries = g_list_prepend(thread->entries,outside); + thread->numentries++; + } + } + pads = g_list_next(pads); + } + } + elements = g_list_next(elements); + } + gst_info("have %d entries into thread\n",thread->numentries); +} + + +static gboolean gst_thread_change_state(GstElement *element, + GstElementState state) { + GstThread *thread; + gboolean stateset = TRUE; + + g_return_if_fail(GST_IS_THREAD(element)); + thread = GST_THREAD(element); + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + stateset = GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + + switch (state) { + case GST_STATE_RUNNING: + if (!stateset) return FALSE; + /* we want to prepare our internal state for doing the iterations */ + gst_info("preparing thread \"%s\" for iterations:\n", + gst_element_get_name(GST_ELEMENT(element))); + gst_thread_prepare(thread); + if (thread->numentries == 0) + return FALSE; + /* set the state to idle */ + GST_FLAG_UNSET(thread,GST_THREAD_STATE_SPINNING); + /* create the thread if that's what we're supposed to do */ + gst_info("flags are 0x%08x\n",GST_FLAGS(thread)); + if (GST_FLAG_IS_SET(thread,GST_THREAD_CREATE)) { + gst_info("starting thread \"%s\"\n", + gst_element_get_name(GST_ELEMENT(element))); + pthread_create(&thread->thread_id,NULL, + gst_thread_main_loop,thread); + } else { + gst_info("NOT starting thread \"%s\"\n", + gst_element_get_name(GST_ELEMENT(element))); + } + return TRUE; + break; + case ~GST_STATE_RUNNING: + /* stop, reap, and join the thread */ + GST_FLAG_UNSET(thread,GST_THREAD_STATE_SPINNING); + GST_FLAG_SET(thread,GST_THREAD_STATE_REAPING); + gst_thread_signal_thread(thread); + pthread_join(thread->thread_id,0); + /* tear down the internal state */ + gst_info("tearing down thread's iteration state\n"); + /* FIXME do stuff */ + break; + case GST_STATE_PLAYING: + if (!stateset) return FALSE; + gst_info("starting thread \"%s\"\n", + gst_element_get_name(GST_ELEMENT(element))); + GST_FLAG_SET(thread,GST_THREAD_STATE_SPINNING); + gst_thread_signal_thread(thread); + return TRUE; + break; + case ~GST_STATE_PLAYING: + gst_info("stopping thread \"%s\"\n", + gst_element_get_name(GST_ELEMENT(element))); + GST_FLAG_UNSET(thread,GST_THREAD_STATE_SPINNING); + gst_thread_signal_thread(thread); + break; + default: + break; + } + + return stateset; +} + + +void *gst_thread_main_loop(void *arg) { + GstThread *thread = GST_THREAD(arg); + + gst_info("HI, IN MAIN THREAD LOOP!\n"); + + while(!GST_FLAG_IS_SET(thread,GST_THREAD_STATE_REAPING)) { + if (GST_FLAG_IS_SET(thread,GST_THREAD_STATE_SPINNING)) + gst_thread_iterate(thread); + else { + g_mutex_lock(thread->lock); + g_cond_wait(thread->cond,thread->lock); + g_mutex_unlock(thread->lock); + } + } + + GST_FLAG_UNSET(thread,GST_THREAD_STATE_REAPING); + + gst_info("GOODBYE, LEAVING MAIN THREAD LOOP!\n"); + return NULL; +} + +void gst_thread_iterate(GstThread *thread) { + GList *entries; + GstElement *entry; + + g_return_if_fail(thread != NULL); + g_return_if_fail(GST_IS_THREAD(thread)); +// g_return_if_fail(GST_FLAG_IS_SET(thread,GST_STATE_RUNNING)); + g_return_if_fail(thread->numentries > 0); + + entries = thread->entries; + + while (entries) { + entry = GST_ELEMENT(entries->data); + if (GST_IS_SRC(entry)) + gst_src_push(GST_SRC(entry)); + else if (GST_IS_CONNECTION(entry)) + gst_connection_push(GST_CONNECTION(entry)); + else + g_assert_not_reached(); + entries = g_list_next(entries); + } +// g_print(","); +} + +static void gst_thread_signal_thread(GstThread *thread) { + g_mutex_lock(thread->lock); + g_cond_signal(thread->cond); + g_mutex_unlock(thread->lock); +} + +static xmlNodePtr gst_thread_save_thyself(GstElement *element,xmlNodePtr parent) { + GstThread *thread = GST_THREAD(element); + xmlNewChild(parent,NULL,"type","thread"); + + if (GST_ELEMENT_CLASS(parent_class)->save_thyself) + GST_ELEMENT_CLASS(parent_class)->save_thyself(element,parent); +} diff --git a/gst/gstthread.h b/gst/gstthread.h new file mode 100644 index 0000000000..fffd6f5f92 --- /dev/null +++ b/gst/gstthread.h @@ -0,0 +1,84 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_THREAD_H__ +#define __GST_THREAD_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +GstElementDetails gst_thread_details; + + +typedef enum { + GST_THREAD_CREATE = (1 << 16), + GST_THREAD_STATE_SPINNING = (1 << 17), + GST_THREAD_STATE_REAPING = (1 << 18), +} GstThreadState; + + +#define GST_TYPE_THREAD \ + (gst_thread_get_type()) +#define GST_THREAD(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_THREAD,GstThread)) +#define GST_THREAD_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_THREAD,GstThreadClass)) +#define GST_IS_THREAD(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_THREAD)) +#define GST_IS_THREAD_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_THREAD))) + +typedef struct _GstThread GstThread; +typedef struct _GstThreadClass GstThreadClass; + +struct _GstThread { + GstBin bin; + + GList *entries; /* used to determine iterate behavior */ + gint numentries; /* number of above entry points */ + + pthread_t thread_id; /* id of the thread, if any */ + GMutex *lock; /* thread lock/condititon pair... */ + GCond *cond; /* used to control the thread */ +}; + +struct _GstThreadClass { + GstBinClass parent_class; +}; + +GtkType gst_thread_get_type(void); +GstElement *gst_thread_new(guchar *name); + +void *gst_thread_main_loop(void *arg); +void gst_thread_iterate(GstThread *thread); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_THREAD_H__ */ + diff --git a/gst/gsttrace.c b/gst/gsttrace.c new file mode 100644 index 0000000000..cbb5dcb033 --- /dev/null +++ b/gst/gsttrace.c @@ -0,0 +1,103 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +__inline__ void read_tsc(guint64 *dst) { + __asm__ __volatile__ + ("rdtsc" + : "=a" (*(guint32 *)dst), "=d" (*(((guint32 *)dst) + 1)) + : + : "eax", "edx"); +} + +void gst_trace_read_tsc(guint64 *dst) { + read_tsc(dst); +} + +GstTrace *_gst_trace_default = NULL; +gint _gst_trace_on = 1; + +GstTrace *gst_trace_new(guchar *filename,gint size) { + GstTrace *trace = g_malloc(sizeof(GstTrace)); + + g_return_val_if_fail(trace != NULL,NULL); + trace->filename = g_strdup(filename); + g_print("opening '%s'\n",trace->filename); + trace->fd = open(trace->filename,O_RDWR|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR); + perror("opening trace file"); + g_return_val_if_fail(trace->fd > 0,NULL); + trace->buf = g_malloc(size * sizeof(GstTraceEntry)); + g_return_val_if_fail(trace->buf != NULL,NULL); + trace->bufsize = size; + trace->bufoffset = 0; + + return trace; +} + +void gst_trace_destroy(GstTrace *trace) { + g_return_if_fail(trace != NULL); + g_return_if_fail(trace->buf != NULL); + + if (gst_trace_get_remaining(trace) > 0) + gst_trace_flush(trace); + close(trace->fd); + g_free(trace->buf); + g_free(trace); +} + +void gst_trace_flush(GstTrace *trace) { + if (!trace) { + trace = _gst_trace_default; + if (!trace ) return; + } + + write(trace->fd,trace->buf,trace->bufoffset * sizeof(GstTraceEntry)); + trace->bufoffset = 0; +} + +void gst_trace_set_default(GstTrace *trace) { + g_return_if_fail(trace != NULL); + _gst_trace_default = trace; +} + +void _gst_trace_add_entry(GstTrace *trace,guint32 seq,guint32 data,gchar *msg) { + GstTraceEntry *entry; + if (!trace) { + trace = _gst_trace_default; + if (!trace ) return; + } + + entry = trace->buf + trace->bufoffset; + read_tsc(&(entry->timestamp)); + entry->sequence = seq; + entry->data = data; + strncpy(entry->message,msg,112); + trace->bufoffset++; + + gst_trace_flush(trace); +} diff --git a/gst/gsttrace.h b/gst/gsttrace.h new file mode 100644 index 0000000000..0fdbabf4c5 --- /dev/null +++ b/gst/gsttrace.h @@ -0,0 +1,69 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_TRACE_H__ +#define __GST_TRACE_H__ + +void gst_trace_read_tsc(guint64 *dst); + +typedef struct _GstTrace GstTrace; +typedef struct _GstTraceEntry GstTraceEntry; + +struct _GstTrace { + /* where this trace is going */ + gchar *filename; + int fd; + + /* current buffer, size, head offset */ + GstTraceEntry *buf; + gint bufsize; + gint bufoffset; +}; + +struct _GstTraceEntry { + guint64 timestamp; + guint32 sequence; + guint32 data; + gchar message[112]; +}; + +GstTrace *gst_trace_new(guchar *filename,gint size); +void gst_trace_destroy(GstTrace *trace); +void gst_trace_flush(GstTrace *trace); +#define gst_trace_get_size(trace) ((trace)->bufsize) +#define gst_trace_get_offset(trace) ((trace)->bufoffset) +#define gst_trace_get_remaining(trace) ((trace)->bufsize - (trace)->bufoffset) +void gst_trace_set_default(GstTrace *trace); + +void _gst_trace_add_entry(GstTrace *trace,guint32 seq,guint32 data,gchar *msg); + +#define TRACE_ENABLE + +#ifdef TRACE_ENABLE +extern gint _gst_trace_on; +#define gst_trace_add_entry(trace,seq,data,msg) \ + if (_gst_trace_on) { \ + _gst_trace_add_entry(trace,(guint32)seq,(guint32)data,msg); \ + } +#else +#define gst_trace_add_entry(trace,seq,data,msg) +#endif + +#endif /* __GST_TRACE_H__ */ diff --git a/gst/gsttype.c b/gst/gsttype.c new file mode 100644 index 0000000000..7c0bcf9c94 --- /dev/null +++ b/gst/gsttype.c @@ -0,0 +1,160 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* TODO: + * probably should set up a hash table for the type id's, since currently + * it's a rather pathetic linear search. Eventually there may be dozens + * of id's, but in reality there are only so many instances of lookup, so + * I'm not overly worried yet... + */ + + +#include + + +/* global list of registered types */ +GList *_gst_types; +guint16 _gst_maxtype; + + +void _gst_type_initialize() { + _gst_types = NULL; + _gst_maxtype = 1; /* type 0 is undefined */ + +// gst_type_audio_register(); +} + +guint16 gst_type_register(GstTypeFactory *factory) { + guint16 id; + GstType *type; + + g_return_if_fail(factory != NULL); + +// id = gst_type_find_by_mime(factory->mime); + id = 0; + if (!id) { + type = (GstType *)malloc(sizeof(GstType)); + + type->id = _gst_maxtype++; + type->mime = factory->mime; + type->exts = factory->exts; + type->typefindfunc = factory->typefindfunc; + type->srcs = NULL; + type->sinks = NULL; + _gst_types = g_list_prepend(_gst_types,type); + + id = type->id; + } else { + type = gst_type_find_by_id(id); + /* now we want to try to merge the types and return the original */ + + /* FIXME: do extension merging here, not that easy */ + + /* if there is no existing typefind function, try to use new one */ + if (!type->typefindfunc && factory->typefindfunc) + type->typefindfunc = factory->typefindfunc; + } + + return id; +} + +guint16 gst_type_find_by_mime(gchar *mime) { + GList *walk = _gst_types; + GstType *type; + gint typelen,mimelen; + gchar *search, *found; + +// DEBUG("searching for '%s'\n",mime); + mimelen = strlen(mime); + while (walk) { + type = (GstType *)walk->data; + search = type->mime; +// DEBUG("checking against '%s'\n",search); + typelen = strlen(search); + while ((search - type->mime) < typelen) { + found = strstr(search,mime); + /* if the requested mime is in the list */ + if (found) { + if ((*(found + mimelen) == ' ') || + (*(found + mimelen) == ',') || + (*(found + mimelen) == '\0')) { + return type->id; + } else { + search = found + mimelen; + } + } else + search += mimelen; + } + walk = g_list_next(walk); + } + + return 0; +} + +GstType *gst_type_find_by_id(guint16 id) { + GList *walk = _gst_types; + GstType *type; + + while (walk) { + type = (GstType *)walk->data; + if (type->id == id) + return type; + walk = g_list_next(walk); + } + + return NULL; +} + +void gst_type_add_src(guint16 id,GstElementFactory *src) { + GstType *type = gst_type_find_by_id(id); + + g_return_if_fail(type != NULL); + g_return_if_fail(src != NULL); + + type->srcs = g_list_prepend(type->srcs,src); +} + +void gst_type_add_sink(guint16 id,GstElementFactory *sink) { + GstType *type = gst_type_find_by_id(id); + + g_return_if_fail(type != NULL); + g_return_if_fail(sink != NULL); + + type->sinks = g_list_prepend(type->sinks,sink); +} + +GList *gst_type_get_srcs(guint16 id) { + GstType *type = gst_type_find_by_id(id); + + g_return_if_fail(type != NULL); + + return type->srcs; +} + +GList *gst_type_get_sinks(guint16 id) { + GstType *type = gst_type_find_by_id(id); + + g_return_if_fail(type != 0); + + return type->sinks; +} + +GList *gst_type_get_list() { + return _gst_types; +} diff --git a/gst/gsttype.h b/gst/gsttype.h new file mode 100644 index 0000000000..fa96bf8733 --- /dev/null +++ b/gst/gsttype.h @@ -0,0 +1,76 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_TYPE_H__ +#define __GST_TYPE_H__ + + +#include +#include + + +/* type of function used to check a stream for equality with type */ +typedef gboolean (*GstTypeFindFunc) (GstBuffer *buf,gpointer *private); + +typedef struct _GstType GstType; +typedef struct _GstTypeFactory GstTypeFactory; + +struct _GstType { + guint16 id; /* type id (assigned) */ + + gchar *mime; /* MIME type */ + gchar *exts; /* space-delimited list of extensions */ + + GstTypeFindFunc typefindfunc; /* typefind function */ + + GList *srcs; /* list of src objects for this type */ + GList *sinks; /* list of sink objects for type */ +}; + +struct _GstTypeFactory { + gchar *mime; + gchar *exts; + GstTypeFindFunc typefindfunc; +}; + + +/* initialize the subsystem */ +void gst_type_initialize(); + +/* create a new type, or find/merge an existing one */ +guint16 gst_type_register(GstTypeFactory *factory); + +/* look up a type by mime or extension */ +guint16 gst_type_find_by_mime(gchar *mime); +guint16 gst_type_find_by_ext(gchar *ext); + +/* add src or sink object */ +void gst_type_add_src(guint16 id,GstElementFactory *src); +void gst_type_add_sink(guint16 id,GstElementFactory *sink); +/* get list of src or sink objects */ +GList *gst_type_get_srcs(guint16 id); +GList *gst_type_get_sinks(guint16 id); + +/* get GstType by id */ +GstType *gst_type_find_by_id(guint16 id); +/* get the list of registered types (returns list of GstType!) */ +GList *gst_type_get_list(); + +#endif /* __GST_TYPE_H__ */ diff --git a/gst/gsttypefind.c b/gst/gsttypefind.c new file mode 100644 index 0000000000..473fa68340 --- /dev/null +++ b/gst/gsttypefind.c @@ -0,0 +1,79 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + + +/* TypeFind signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_typefind_class_init(GstTypeFindClass *klass); +static void gst_typefind_init(GstTypeFind *typefind); + + +static GstElementClass *parent_class = NULL; +static guint gst_typefind_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_typefind_get_type(void) { + static GtkType typefind_type = 0; + + if (!typefind_type) { + static const GtkTypeInfo typefind_info = { + "GstTypeFind", + sizeof(GstTypeFind), + sizeof(GstTypeFindClass), + (GtkClassInitFunc)gst_typefind_class_init, + (GtkObjectInitFunc)gst_typefind_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + typefind_type = gtk_type_unique(GST_TYPE_ELEMENT,&typefind_info); + } + return typefind_type; +} + +static void +gst_typefind_class_init(GstTypeFindClass *klass) { + GtkObjectClass *gtkobject_class; + + gtkobject_class = (GtkObjectClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_ELEMENT); +} + +static void gst_typefind_init(GstTypeFind *typefind) { +} + +GstObject *gst_typefind_new(gchar *name) { + GstObject *typefind = GST_OBJECT(gtk_type_new(GST_TYPE_TYPEFIND)); + gst_element_set_name(GST_ELEMENT(typefind),name); + return typefind; +} diff --git a/gst/gsttypefind.h b/gst/gsttypefind.h new file mode 100644 index 0000000000..34bd714b7f --- /dev/null +++ b/gst/gsttypefind.h @@ -0,0 +1,68 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_TYPEFIND_H__ +#define __GST_TYPEFIND_H__ + + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GST_TYPE_TYPEFIND \ + (gst_typefind_get_type()) +#define GST_TYPEFIND(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_TYPEFIND,GstTypeFind)) +#define GST_TYPEFIND_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_TYPEFIND,GstTypeFindClass)) +#define GST_IS_TYPEFIND(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_TYPEFIND)) +#define GST_IS_TYPEFIND_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_TYPEFIND))) + +typedef struct _GstTypeFind GstTypeFind; +typedef struct _GstTypeFindClass GstTypeFindClass; + +struct _GstTypeFind { + GstElement element; + + GstPad *sinkpad; +}; + +struct _GstTypeFindClass { + GstElementClass parent_class; +}; + +GtkType gst_typefind_get_type(void); +GstObject *gst_typefind_new(gchar *name); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_TYPEFIND_H__ */ diff --git a/gst/gstutils.c b/gst/gstutils.c new file mode 100644 index 0000000000..d659fd5f46 --- /dev/null +++ b/gst/gstutils.c @@ -0,0 +1,77 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + +gint gst_util_get_int_arg(GtkObject *object,guchar *argname) { + GtkArg arg; + + arg.name = argname; + gtk_object_getv(GTK_OBJECT(object),1,&arg); + return GTK_VALUE_INT(arg); +} + +glong gst_util_get_long_arg(GtkObject *object,guchar *argname) { + GtkArg arg; + + arg.name = argname; + gtk_object_getv(GTK_OBJECT(object),1,&arg); + return GTK_VALUE_LONG(arg); +} + +gfloat gst_util_get_float_arg(GtkObject *object,guchar *argname) { + GtkArg arg; + + arg.name = argname; + gtk_object_getv(GTK_OBJECT(object),1,&arg); + return GTK_VALUE_FLOAT(arg); +} + +gdouble gst_util_get_double_arg(GtkObject *object,guchar *argname) { + GtkArg arg; + + arg.name = argname; + gtk_object_getv(GTK_OBJECT(object),1,&arg); + return GTK_VALUE_DOUBLE(arg); +} + +guchar *gst_util_get_string_arg(GtkObject *object,guchar *argname) { + GtkArg arg; + + arg.name = argname; + gtk_object_getv(GTK_OBJECT(object),1,&arg); + return GTK_VALUE_STRING(arg); +} + +gpointer gst_util_get_pointer_arg(GtkObject *object,guchar *argname) { + GtkArg arg; + + arg.name = argname; + gtk_object_getv(GTK_OBJECT(object),1,&arg); + return GTK_VALUE_POINTER(arg); +} + +GtkWidget *gst_util_get_widget_arg(GtkObject *object,guchar *argname) { + GtkArg arg; + + arg.name = argname; + gtk_object_getv(GTK_OBJECT(object),1,&arg); + return GTK_WIDGET(GTK_VALUE_OBJECT(arg)); +} diff --git a/gst/gstutils.h b/gst/gstutils.h new file mode 100644 index 0000000000..f196c5a8fd --- /dev/null +++ b/gst/gstutils.h @@ -0,0 +1,35 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_UTILS_H__ +#define __GST_UTILS_H__ + +#include + +gint gst_util_get_int_arg(GtkObject *object,guchar *argname); +glong gst_util_get_long_arg(GtkObject *object,guchar *argname); +gfloat gst_util_get_float_arg(GtkObject *object,guchar *argname); +gdouble gst_util_get_double_arg(GtkObject *object,guchar *argname); +guchar *gst_util_get_string_arg(GtkObject *object,guchar *argname); +gpointer gst_util_get_pointer_arg(GtkObject *object,guchar *argname); +GtkWidget *gst_util_get_widget_arg(GtkObject *object,guchar *argname); + + +#endif /* __GST_UTILS_H__ */ diff --git a/gst/gstxml.c b/gst/gstxml.c new file mode 100644 index 0000000000..cfcd6dca70 --- /dev/null +++ b/gst/gstxml.c @@ -0,0 +1,31 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +xmlDocPtr gst_xml_write(GstElement *element) { + xmlDocPtr doc; + + doc = xmlNewDoc("1.0"); + doc->root = xmlNewDocNode(doc,NULL,"GST-Pipeline",NULL); + + gst_element_save_thyself(element,doc->root); + + return doc; +} diff --git a/gst/gstxml.h b/gst/gstxml.h new file mode 100644 index 0000000000..e2538810e3 --- /dev/null +++ b/gst/gstxml.h @@ -0,0 +1,30 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_XML_H__ +#define __GST_XML_H__ + +#include +#include + +/* create an XML document out of a pipeline */ +xmlDocPtr gst_xml_write(GstElement *element); + +#endif /* __GST_XML_H__ */ diff --git a/gst/meta/Makefile.am b/gst/meta/Makefile.am new file mode 100644 index 0000000000..adc27ce0f5 --- /dev/null +++ b/gst/meta/Makefile.am @@ -0,0 +1,3 @@ +metaincludedir = $(includedir)/gst/meta +metainclude_HEADERS = \ + audioraw.h diff --git a/gst/meta/audioraw.h b/gst/meta/audioraw.h new file mode 100644 index 0000000000..7c8d52d237 --- /dev/null +++ b/gst/meta/audioraw.h @@ -0,0 +1,40 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_META_AUDIORAW_H__ +#define __GST_META_AUDIORAW_H__ + +#include +#include + +typedef struct _MetaAudioRaw MetaAudioRaw; + +struct _MetaAudioRaw { + GstMeta meta; + + /* formatting information */ + gint format; + gint channels; + gint frequency; + gint bps; +}; + +#endif /* __GST_META_AUDIORAW_H__ */ + diff --git a/gst/meta/spectrum.h b/gst/meta/spectrum.h new file mode 100644 index 0000000000..c8e1637e98 --- /dev/null +++ b/gst/meta/spectrum.h @@ -0,0 +1,38 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + +typedef struct _MetaAudioSpectrum MetaAudioSpectrum; + +struct _MetaAudioSpectrum { + GstMeta meta; + + /* data representation */ + gint16 bands; /* how many bands are represented */ + gint8 channels; /* how many audio channels are there? */ + gboolean interleaved; /* are the channels interleaved? */ + + /* spectrum details */ + gint16 lowfreq; + gint16 highfreq; + gint16 steps; +}; + diff --git a/gst/plugin.c b/gst/plugin.c new file mode 100644 index 0000000000..996e3f81f8 --- /dev/null +++ b/gst/plugin.c @@ -0,0 +1,139 @@ +#include +#include +#include +#include + +/* list of paths to check for plugins */ +GList *_plugin_paths; + +/* whether or not to spew library load issues */ +gboolean _plugin_spew = FALSE; + + +void plugin_initialize() { + _plugin_paths = NULL; + + /* add the main (installed) library path */ + _plugin_paths = g_list_prepend(_plugin_paths,PLUGINS_DIR); + + /* if this is set, we add build-directory paths to the list */ +#ifdef PLUGINS_USE_SRCDIR + _plugin_paths = g_list_prepend(_plugin_paths,PLUGINS_SRCDIR); +#endif /* PLUGINS_USE_SRCDIR */ +} + +static GModule *plugin_load_recurse(gchar *directory,gchar *name) { + DIR *dir; + struct dirent *dirent; + GModule *mod; + + dir = opendir(directory); + if (dir) { + while (dirent = readdir(dir)) { + /* don't want to recurse in place or backwards */ + if (strcmp(dirent->d_name,".") && strcmp(dirent->d_name,"..")) { + mod = plugin_load_recurse(g_strjoin("/",directory,dirent->d_name, + NULL),name); + if (mod != NULL) { + closedir(dir); + return mod; + } + } + } + closedir(dir); + } else { + if (strstr(directory,".so")) { + gchar *temp; + if (name) { + if ((temp = strstr(directory,name)) && + (!strcmp(temp,name))) { + mod = plugin_load_absolute(directory); + if (mod != NULL) return mod; + } + } else if ((temp = strstr(directory,".so")) && + (!strcmp(temp,".so"))) { + mod = plugin_load_absolute(directory); + if (mod != NULL) return mod; + } + } + } + return NULL; +} + +/** + * plugin_load_all: + * + * Load all plugins in the path. + */ +void plugin_load_all() { + GList *path; + + path = _plugin_paths; + while (path != NULL) { + plugin_load_recurse(path->data,NULL); + path = g_list_next(path); + } +} + +/** + * plugin_load: + * @name: name of plugin to load + * + * Load the named plugin. Name should be given as + * "libplugin.so". + * + * Returns: whether the plugin was loaded or not + */ +GModule *plugin_load(gchar *name) { + GList *path; + gchar *libspath; + GModule *mod; + +// g_print("attempting to load plugin '%s'\n",name); + + path = _plugin_paths; + while (path != NULL) { + mod = plugin_load_absolute(g_module_build_path(path->data,name)); + if (mod != NULL) return mod; + libspath = g_strconcat(path->data,"/.libs",NULL); +// g_print("trying to load '%s'\n",g_module_build_path(libspath,name)); + mod = plugin_load_absolute(g_module_build_path(libspath,name)); + if (mod != NULL) { + g_free(libspath); + return mod; + } + g_free(libspath); +// g_print("trying to load '%s' from '%s'\n",name,path->data); + mod = plugin_load_recurse(path->data,name); + if (mod != NULL) return mod; + path = g_list_next(path); + } + return NULL; +} + +/** + * plugin_load_absolute: + * @name: name of plugin to load + * + * Returns: whether or not the plugin loaded + */ +GModule *plugin_load_absolute(gchar *name) { + GModule *mod; + +// g_print("trying to load '%s\n",name); + + if (g_module_supported() == FALSE) { + g_print("wow, you built this on a platform without dynamic loading???\n"); + return; + } + + mod = g_module_open(name,0); + if (mod != NULL) { + return mod; + } else if (_gst_plugin_spew) { +// if (strstr(g_module_error(),"No such") == NULL) + g_print("error loading plugin: %s\n",g_module_error()); + } + + return NULL; +} diff --git a/gst/plugin.h b/gst/plugin.h new file mode 100644 index 0000000000..d98d65f0b9 --- /dev/null +++ b/gst/plugin.h @@ -0,0 +1,4 @@ +void plugin_initialize(); +void plugin_load_all(); +GModule *plugin_load(gchar *name); +GModule *plugin_load_absolute(gchar *name); diff --git a/gst/types/Makefile.am b/gst/types/Makefile.am new file mode 100644 index 0000000000..2dec2600ef --- /dev/null +++ b/gst/types/Makefile.am @@ -0,0 +1,10 @@ +lib_LTLIBRARIES = libgsttypes.la + +libgsttypes_la_DEPENDENCIES = ../libgst.la +libgsttypes_la_SOURCES = \ + gsttypes.c + +#noinst_HEADERS = + +libgsttypes_la_LIBADD = $(GLIB_LIBS) $(GTK_LIBS) $(top_srcdir)/gst/libgst.la +libgsttypes_la_LDFLAGS = -version-info $(STREAMER_CURRENT):$(STREAMER_REVISION):$(STREAMER_AGE) diff --git a/gst/types/gsttypes.c b/gst/types/gsttypes.c new file mode 100644 index 0000000000..3d49f24be0 --- /dev/null +++ b/gst/types/gsttypes.c @@ -0,0 +1,85 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include +#include + +gint mp3_typefind(GstBuffer *buf,gpointer *private); +gint wav_typefind(GstBuffer *buf,gpointer *private); + +GstTypeFactory _factories[] = { + { "audio/raw", ".raw", NULL }, + { "audio/mpeg audio/mp3", ".mp2 .mp3 .mpa .mpega", mp3_typefind }, + { "audio/wav", ".wav", wav_typefind }, + { "audio/ac3", ".ac3", NULL }, + { NULL, NULL, NULL }, +}; + + +/* check to see if a buffer indicates the presence of an mp3 frame + * NOTE that this only checks for a potentially valid mp3 frame header + * and doesn't guarantee that it's a fully valid mp3 audio stream */ +gboolean mp3_typefind(GstBuffer *buf,gpointer *private) { + gulong head = GULONG_FROM_BE(*((gulong *)GST_BUFFER_DATA(buf))); + + if ((head & 0xffe00000) != 0xffe00000) + return FALSE; + if (!((head >> 17) & 3)) + return FALSE; + if (((head >> 12) & 0xf) == 0xf) + return FALSE; + if (!((head >> 12) & 0xf)) + return FALSE; + if (((head >> 10) & 0x3) == 0x3) + return FALSE; + + return TRUE; +} + +gboolean wav_typefind(GstBuffer *buf,gpointer *private) { + gulong *data = (gulong *)GST_BUFFER_DATA(buf); + + if (data[0] != "RIFF") return FALSE; + if (data[2] != "WAVE") return FALSE; + + return TRUE; +} + + +GstPlugin *plugin_init(GModule *module) { + GstPlugin *plugin; + int i = 0; + + if (gst_plugin_find("gsttypes") != NULL) + return NULL; + + plugin = gst_plugin_new("gsttypes"); + g_return_val_if_fail(plugin != NULL,NULL); + + while (_factories[i].mime) { + gst_type_register(&_factories[i]); +// DEBUG("added factory #%d '%s'\n",i,_factories[i].mime); + i++; + } + + gst_info("gsttypes: loaded %d standard types\n",i); + + return plugin; +} diff --git a/install-sh b/install-sh new file mode 100755 index 0000000000..e9de23842d --- /dev/null +++ b/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/missing b/missing new file mode 100755 index 0000000000..7789652e87 --- /dev/null +++ b/missing @@ -0,0 +1,190 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright (C) 1996, 1997 Free Software Foundation, Inc. +# Franc,ois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing - GNU libit 0.0" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`configure.in'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`configure.in'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`configure.in'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100755 index 0000000000..6b3b5fc5d4 --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id$ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/plugins/elements/Makefile.am b/plugins/elements/Makefile.am new file mode 100644 index 0000000000..d035695115 --- /dev/null +++ b/plugins/elements/Makefile.am @@ -0,0 +1,35 @@ +lib_LTLIBRARIES = libgstelements.la + +libgstelements_la_DEPENDENCIES = ../libgst.la +libgstelements_la_SOURCES = \ + gstelements.c \ + gstfakesrc.c \ + gstidentity.c \ + gstfakesink.c \ + gstdisksrc.c \ + gstasyncdisksrc.c \ + gstfdsrc.c \ + gsthttpsrc.c \ + gstaudiosink.c \ + gstaudiosrc.c \ + gstfdsink.c \ + gstqueue.c \ + gstsinesrc.c + +noinst_HEADERS = \ + gstfakesrc.h \ + gstidentity.h \ + gstfakesink.h \ + gstdisksrc.h \ + gstasyncdisksrc.h \ + gstfdsrc.h \ + gsthttpsrc.h \ + gstaudiosink.h \ + gstaudiosrc.h \ + gstfdsink.h \ + gstqueue.h \ + gstsinesrc.h + +libgstelements_la_LIBADD = $(GLIB_LIBS) $(GTK_LIBS) \ + $(top_srcdir)/gst/libgst.la +libgstelements_la_LDFLAGS = -version-info $(STREAMER_CURRENT):$(STREAMER_REVISION):$(STREAMER_AGE) diff --git a/plugins/elements/gstasyncdisksrc.c b/plugins/elements/gstasyncdisksrc.c new file mode 100644 index 0000000000..8587fa53be --- /dev/null +++ b/plugins/elements/gstasyncdisksrc.c @@ -0,0 +1,346 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +#include + + +GstElementDetails gst_asyncdisksrc_details = { + "Asynchronous Disk Source", + "Source/File", + "Read from arbitrary point in a file", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* AsyncDiskSrc signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_LOCATION, + ARG_BYTESPERREAD, + ARG_LENGTH, + ARG_OFFSET, +}; + + +static void gst_asyncdisksrc_class_init(GstAsyncDiskSrcClass *klass); +static void gst_asyncdisksrc_init(GstAsyncDiskSrc *asyncdisksrc); +static void gst_asyncdisksrc_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_asyncdisksrc_get_arg(GtkObject *object,GtkArg *arg,guint id); + +static void gst_asyncdisksrc_push(GstSrc *src); +static void gst_asyncdisksrc_push_region(GstSrc *src,gulong offset, + gulong size); +static gboolean gst_asyncdisksrc_change_state(GstElement *element, + GstElementState state); + + +static GstSrcClass *parent_class = NULL; +static guint gst_asyncdisksrc_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_asyncdisksrc_get_type(void) { + static GtkType asyncdisksrc_type = 0; + + if (!asyncdisksrc_type) { + static const GtkTypeInfo asyncdisksrc_info = { + "GstAsyncDiskSrc", + sizeof(GstAsyncDiskSrc), + sizeof(GstAsyncDiskSrcClass), + (GtkClassInitFunc)gst_asyncdisksrc_class_init, + (GtkObjectInitFunc)gst_asyncdisksrc_init, + (GtkArgSetFunc)gst_asyncdisksrc_set_arg, + (GtkArgGetFunc)gst_asyncdisksrc_get_arg, + (GtkClassInitFunc)NULL, + }; + asyncdisksrc_type = gtk_type_unique(GST_TYPE_SRC,&asyncdisksrc_info); + } + return asyncdisksrc_type; +} + +static void +gst_asyncdisksrc_class_init(GstAsyncDiskSrcClass *klass) { + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + GstSrcClass *gstsrc_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + gstsrc_class = (GstSrcClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SRC); + + gtk_object_add_arg_type("GstAsyncDiskSrc::location", GTK_TYPE_STRING, + GTK_ARG_READWRITE, ARG_LOCATION); + gtk_object_add_arg_type("GstAsyncDiskSrc::bytesperread", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_BYTESPERREAD); + gtk_object_add_arg_type("GstAsyncDiskSrc::length", GTK_TYPE_LONG, + GTK_ARG_READABLE, ARG_LENGTH); + gtk_object_add_arg_type("GstAsyncDiskSrc::offset", GTK_TYPE_LONG, + GTK_ARG_READWRITE, ARG_OFFSET); + + gtkobject_class->set_arg = gst_asyncdisksrc_set_arg; + gtkobject_class->get_arg = gst_asyncdisksrc_get_arg; + + gstelement_class->change_state = gst_asyncdisksrc_change_state; + + gstsrc_class->push = gst_asyncdisksrc_push; + gstsrc_class->push_region = gst_asyncdisksrc_push_region; +} + +static void gst_asyncdisksrc_init(GstAsyncDiskSrc *asyncdisksrc) { + GST_SRC_SET_FLAGS(asyncdisksrc,GST_SRC_ASYNC); + + asyncdisksrc->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(asyncdisksrc),asyncdisksrc->srcpad); + + asyncdisksrc->filename = NULL; + asyncdisksrc->fd = 0; + asyncdisksrc->size = 0; + asyncdisksrc->map = NULL; + asyncdisksrc->curoffset = 0; + asyncdisksrc->bytes_per_read = 4096; + asyncdisksrc->seq = 0; +} + + +static void gst_asyncdisksrc_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstAsyncDiskSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_ASYNCDISKSRC(object)); + src = GST_ASYNCDISKSRC(object); + + switch(id) { + case ARG_LOCATION: + /* the element must be stopped in order to do this */ + g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING)); + + if (src->filename) g_free(src->filename); + /* clear the filename if we get a NULL (is that possible?) */ + if (GTK_VALUE_STRING(*arg) == NULL) { + src->filename = NULL; + gst_element_set_state(GST_ELEMENT(object),~GST_STATE_COMPLETE); + /* otherwise set the new filename */ + } else { + src->filename = g_strdup(GTK_VALUE_STRING(*arg)); + gst_element_set_state(GST_ELEMENT(object),GST_STATE_COMPLETE); + } + break; + case ARG_BYTESPERREAD: + src->bytes_per_read = GTK_VALUE_INT(*arg); + break; + case ARG_OFFSET: + src->curoffset = GTK_VALUE_LONG(*arg); + break; + default: + break; + } +} + +static void gst_asyncdisksrc_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstAsyncDiskSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_ASYNCDISKSRC(object)); + src = GST_ASYNCDISKSRC(object); + + switch (id) { + case ARG_LOCATION: + GTK_VALUE_STRING(*arg) = src->filename; + break; + case ARG_BYTESPERREAD: + GTK_VALUE_INT(*arg) = src->bytes_per_read; + break; + case ARG_LENGTH: + GTK_VALUE_LONG(*arg) = src->size; + break; + case ARG_OFFSET: + GTK_VALUE_LONG(*arg) = src->curoffset; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +/** + * gst_asyncdisksrc_push: + * @src: #GstSrc to push a buffer from + * + * Push a new buffer from the asyncdisksrc at the current offset. + */ +void gst_asyncdisksrc_push(GstSrc *src) { + GstAsyncDiskSrc *asyncdisksrc; + GstBuffer *buf; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_ASYNCDISKSRC(src)); + g_return_if_fail(GST_FLAG_IS_SET(src,GST_ASYNCDISKSRC_OPEN)); + asyncdisksrc = GST_ASYNCDISKSRC(src); + + /* deal with EOF state */ + if (asyncdisksrc->curoffset >= asyncdisksrc->size) { + gst_src_signal_eos(GST_SRC(asyncdisksrc)); + return; + } + + /* create the buffer */ + // FIXME: should eventually use a bufferpool for this + buf = GST_BUFFER(gst_buffer_new()); + g_return_if_fail(buf != NULL); + + /* simply set the buffer to point to the correct region of the file */ + GST_BUFFER_DATA(buf) = asyncdisksrc->map + asyncdisksrc->curoffset; + GST_BUFFER_OFFSET(buf) = asyncdisksrc->curoffset; + + if ((asyncdisksrc->curoffset + asyncdisksrc->bytes_per_read) > + asyncdisksrc->size) { + GST_BUFFER_SIZE(buf) = asyncdisksrc->size - asyncdisksrc->curoffset; + // FIXME: set the buffer's EOF bit here + } else + GST_BUFFER_SIZE(buf) = asyncdisksrc->bytes_per_read; + asyncdisksrc->curoffset += GST_BUFFER_SIZE(buf); + + /* we're done, push the buffer off now */ + gst_pad_push(asyncdisksrc->srcpad,buf); +} + +/** + * gst_asyncdisksrc_push_region: + * @src: #GstSrc to push a buffer from + * @offset: offset in file + * @size: number of bytes + * + * Push a new buffer from the asyncdisksrc of given size at given offset. + */ +void gst_asyncdisksrc_push_region(GstSrc *src,gulong offset,gulong size) { + GstAsyncDiskSrc *asyncdisksrc; + GstBuffer *buf; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_ASYNCDISKSRC(src)); + g_return_if_fail(GST_FLAG_IS_SET(src,GST_STATE_RUNNING)); + asyncdisksrc = GST_ASYNCDISKSRC(src); + + /* deal with EOF state */ + if (offset >= asyncdisksrc->size) { + gst_src_signal_eos(GST_SRC(asyncdisksrc)); + return; + } + + /* create the buffer */ + // FIXME: should eventually use a bufferpool for this + buf = gst_buffer_new(); + g_return_if_fail(buf); + + /* simply set the buffer to point to the correct region of the file */ + GST_BUFFER_DATA(buf) = asyncdisksrc->map + offset; + GST_BUFFER_OFFSET(buf) = asyncdisksrc->curoffset; + + if ((offset + size) > asyncdisksrc->size) { + GST_BUFFER_SIZE(buf) = asyncdisksrc->size - offset; + // FIXME: set the buffer's EOF bit here + } else + GST_BUFFER_SIZE(buf) = size; + asyncdisksrc->curoffset += GST_BUFFER_SIZE(buf); + + /* we're done, push the buffer off now */ + gst_pad_push(asyncdisksrc->srcpad,buf); +} + + +/* open the file and mmap it, necessary to go to RUNNING state */ +static gboolean gst_asyncdisksrc_open_file(GstAsyncDiskSrc *src) { + g_return_if_fail(!GST_FLAG_IS_SET(src,GST_ASYNCDISKSRC_OPEN)); + + /* open the file */ + src->fd = open(src->filename,O_RDONLY); + if (src->fd < 0) { + gst_element_error(GST_ELEMENT(src),"opening file"); + return FALSE; + } else { + /* find the file length */ + src->size = lseek(src->fd,0,SEEK_END); + lseek(src->fd,0,SEEK_SET); + /* map the file into memory */ + src->map = mmap(NULL,src->size,PROT_READ,MAP_SHARED,src->fd,0); + /* collapse state if that failed */ + if (src->map == NULL) { + close(src->fd); + gst_element_error(GST_ELEMENT(src),"mmapping file"); + return FALSE; + } + GST_FLAG_SET(src,GST_ASYNCDISKSRC_OPEN); + } + return TRUE; +} + +/* unmap and close the file */ +static void gst_asyncdisksrc_close_file(GstAsyncDiskSrc *src) { + g_return_if_fail(GST_FLAG_IS_SET(src,GST_ASYNCDISKSRC_OPEN)); + + /* unmap the file from memory */ + munmap(src->map,src->size); + /* close the file */ + close(src->fd); + + /* zero out a lot of our state */ + src->fd = 0; + src->size = 0; + src->map = NULL; + src->curoffset = 0; + src->seq = 0; + + GST_FLAG_UNSET(src,GST_ASYNCDISKSRC_OPEN); +} + + +static gboolean gst_asyncdisksrc_change_state(GstElement *element, + GstElementState state) { + g_return_if_fail(GST_IS_ASYNCDISKSRC(element)); + + switch (state) { + case GST_STATE_RUNNING: + if (!gst_asyncdisksrc_open_file(GST_ASYNCDISKSRC(element))) + return FALSE; + break; + case ~GST_STATE_RUNNING: + gst_asyncdisksrc_close_file(GST_ASYNCDISKSRC(element)); + break; + default: + break; + } + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + return TRUE; +} diff --git a/plugins/elements/gstasyncdisksrc.h b/plugins/elements/gstasyncdisksrc.h new file mode 100644 index 0000000000..5c50d6ef5b --- /dev/null +++ b/plugins/elements/gstasyncdisksrc.h @@ -0,0 +1,88 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_ASYNCDISKSRC_H__ +#define __GST_ASYNCDISKSRC_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_asyncdisksrc_details; + + +#define GST_TYPE_ASYNCDISKSRC \ + (gst_asyncdisksrc_get_type()) +#define GST_ASYNCDISKSRC(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_ASYNCDISKSRC,GstAsyncDiskSrc)) +#define GST_ASYNCDISKSRC_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_ASYNCDISKSRC,GstAsyncDiskSrcClass)) +#define GST_IS_ASYNCDISKSRC(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_ASYNCDISKSRC)) +#define GST_IS_ASYNCDISKSRC_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_ASYNCDISKSRC))) + +// NOTE: per-element flags start with 16 for now +typedef enum { + GST_ASYNCDISKSRC_OPEN = (1 << 16), +} GstAsyncDiskSrcFlags; + +typedef struct _GstAsyncDiskSrc GstAsyncDiskSrc; +typedef struct _GstAsyncDiskSrcClass GstAsyncDiskSrcClass; + +struct _GstAsyncDiskSrc { + GstSrc src; + /* pads */ + GstPad *srcpad; + + /* filename */ + gchar *filename; + /* fd */ + gint fd; + + /* mapping parameters */ + gulong size; /* how long is the file? */ + guchar *map; /* where the file is mapped to */ + + /* details for fallback synchronous read */ + gulong curoffset; /* current offset in file */ + gulong bytes_per_read; /* bytes per read */ + + gulong seq; /* buffer sequence number */ +}; + +struct _GstAsyncDiskSrcClass { + GstSrcClass parent_class; +}; + +GtkType gst_asyncdisksrc_get_type(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_ASYNCDISKSRC_H__ */ diff --git a/plugins/elements/gstaudiosink.c b/plugins/elements/gstaudiosink.c new file mode 100644 index 0000000000..56523cbc56 --- /dev/null +++ b/plugins/elements/gstaudiosink.c @@ -0,0 +1,291 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include +#include +#include +#include + +#include +#include + + +GstElementDetails gst_audiosink_details = { + "Audio Sink (OSS)", + "Sink/Audio", + "Output to a sound card via OSS", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +static gboolean gst_audiosink_open_audio(GstAudioSink *sink); +static void gst_audiosink_close_audio(GstAudioSink *sink); +static gboolean gst_audiosink_start(GstElement *element, + GstElementState state); +static gboolean gst_audiosink_stop(GstElement *element); +static gboolean gst_audiosink_change_state(GstElement *element, + GstElementState state); + + +/* AudioSink signals and args */ +enum { + HANDOFF, + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_audiosink_class_init(GstAudioSinkClass *klass); +static void gst_audiosink_init(GstAudioSink *audiosink); + + +static GstFilterClass *parent_class = NULL; +static guint gst_audiosink_signals[LAST_SIGNAL] = { 0 }; + +static guint16 gst_audiosink_type_audio = 0; + +GtkType +gst_audiosink_get_type(void) { + static GtkType audiosink_type = 0; + + if (!audiosink_type) { + static const GtkTypeInfo audiosink_info = { + "GstAudioSink", + sizeof(GstAudioSink), + sizeof(GstAudioSinkClass), + (GtkClassInitFunc)gst_audiosink_class_init, + (GtkObjectInitFunc)gst_audiosink_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + audiosink_type = gtk_type_unique(GST_TYPE_FILTER,&audiosink_info); + } + + if (!gst_audiosink_type_audio) + gst_audiosink_type_audio = gst_type_find_by_mime("audio/raw"); + + return audiosink_type; +} + +static void +gst_audiosink_class_init(GstAudioSinkClass *klass) { + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_FILTER); + + gst_audiosink_signals[HANDOFF] = + gtk_signal_new("handoff",GTK_RUN_LAST,gtkobject_class->type, + GTK_SIGNAL_OFFSET(GstAudioSinkClass,handoff), + gtk_marshal_NONE__POINTER_POINTER,GTK_TYPE_NONE,2, + GTK_TYPE_POINTER,GTK_TYPE_POINTER); + gtk_object_class_add_signals(gtkobject_class,gst_audiosink_signals, + LAST_SIGNAL); + + gstelement_class->start = gst_audiosink_start; + gstelement_class->stop = gst_audiosink_stop; + gstelement_class->change_state = gst_audiosink_change_state; +} + +static void gst_audiosink_init(GstAudioSink *audiosink) { + audiosink->sinkpad = gst_pad_new("sink",GST_PAD_SINK); + gst_element_add_pad(GST_ELEMENT(audiosink),audiosink->sinkpad); + if (!gst_audiosink_type_audio) + gst_audiosink_type_audio = gst_type_find_by_mime("audio/raw"); + gst_pad_set_type_id(audiosink->sinkpad,gst_audiosink_type_audio); + gst_pad_set_chain_function(audiosink->sinkpad,gst_audiosink_chain); + + audiosink->fd = -1; + + gst_element_set_state(GST_ELEMENT(audiosink),GST_STATE_COMPLETE); +} + +void gst_audiosink_sync_parms(GstAudioSink *audiosink) { + audio_buf_info ospace; + + g_return_if_fail(audiosink != NULL); + g_return_if_fail(GST_IS_AUDIOSINK(audiosink)); + g_return_if_fail(audiosink->fd > 0); + + ioctl(audiosink->fd,SNDCTL_DSP_RESET,0); + + ioctl(audiosink->fd,SNDCTL_DSP_SETFMT,&audiosink->format); + ioctl(audiosink->fd,SNDCTL_DSP_CHANNELS,&audiosink->channels); + ioctl(audiosink->fd,SNDCTL_DSP_SPEED,&audiosink->frequency); + + ioctl(audiosink->fd,SNDCTL_DSP_GETOSPACE,&ospace); + + g_print("setting sound card to %dKHz %d bit %s (%d bytes buffer)\n", + audiosink->frequency,audiosink->format, + (audiosink->channels == 2) ? "stereo" : "mono",ospace.bytes); +} + +GstElement *gst_audiosink_new(gchar *name) { + GstElement *audiosink = GST_ELEMENT(gtk_type_new(GST_TYPE_AUDIOSINK)); + gst_element_set_name(GST_ELEMENT(audiosink),name); + return audiosink; +} + +void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) { + GstAudioSink *audiosink; + MetaAudioRaw *meta; + + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(buf != NULL); + + /* this has to be an audio buffer */ +// g_return_if_fail(((GstMeta *)buf->meta)->type != +//gst_audiosink_type_audio); + audiosink = GST_AUDIOSINK(pad->parent); +// g_return_if_fail(GST_FLAG_IS_SET(audiosink,GST_STATE_RUNNING)); + + meta = (MetaAudioRaw *)gst_buffer_get_first_meta(buf); + if (meta != NULL) { + if ((meta->format != audiosink->format) || + (meta->channels != audiosink->channels) || + (meta->frequency != audiosink->frequency)) { + audiosink->format = meta->format; + audiosink->channels = meta->channels; + audiosink->frequency = meta->frequency; + gst_audiosink_sync_parms(audiosink); + g_print("sound device set to format %d, %d channels, %dHz\n", + audiosink->format,audiosink->channels,audiosink->frequency); + } + } + + gtk_signal_emit(GTK_OBJECT(audiosink),gst_audiosink_signals[HANDOFF], + audiosink); + if (GST_BUFFER_DATA(buf) != NULL) { + gst_trace_add_entry(NULL,0,buf,"audiosink: writing to soundcard"); + if (audiosink->fd > 2) + write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf)); + } + + gst_buffer_unref(buf); +// g_print("a"); +} + +void gst_audiosink_set_format(GstAudioSink *audiosink,gint format) { + g_return_if_fail(audiosink != NULL); + g_return_if_fail(GST_IS_AUDIOSINK(audiosink)); + + audiosink->format = format; + + gst_audiosink_sync_parms(audiosink); +} + +void gst_audiosink_set_channels(GstAudioSink *audiosink,gint channels) { + g_return_if_fail(audiosink != NULL); + g_return_if_fail(GST_IS_AUDIOSINK(audiosink)); + + audiosink->channels = channels; + + gst_audiosink_sync_parms(audiosink); +} + +void gst_audiosink_set_frequency(GstAudioSink *audiosink,gint frequency) { + g_return_if_fail(audiosink != NULL); + g_return_if_fail(GST_IS_AUDIOSINK(audiosink)); + + audiosink->frequency = frequency; + + gst_audiosink_sync_parms(audiosink); +} + +static gboolean gst_audiosink_open_audio(GstAudioSink *sink) { + g_return_if_fail(sink->fd == -1); + + g_print("attempting to open sound device\n"); + + /* first try to open the sound card */ + sink->fd = open("/dev/dsp",O_RDWR); + + /* if we have it, set the default parameters and go have fun */ + if (sink->fd > 0) { + /* set card state */ + sink->format = AFMT_S16_LE; + sink->channels = 2; /* stereo */ + sink->frequency = 44100; + gst_audiosink_sync_parms(sink); + g_print("opened audio\n"); + return TRUE; + } + + return FALSE; +} + +static void gst_audiosink_close_audio(GstAudioSink *sink) { + if (sink->fd < 0) return; + + close(sink->fd); + sink->fd = -1; + g_print("closed sound device\n"); +} + +static gboolean gst_audiosink_start(GstElement *element, + GstElementState state) { + g_return_if_fail(GST_IS_AUDIOSINK(element)); + + if (gst_audiosink_open_audio(GST_AUDIOSINK(element)) == TRUE) { + gst_element_set_state(element,GST_STATE_RUNNING | state); + return TRUE; + } + return FALSE; +} + +static gboolean gst_audiosink_stop(GstElement *element) { + g_return_if_fail(GST_IS_AUDIOSINK(element)); + + gst_audiosink_close_audio(GST_AUDIOSINK(element)); + gst_element_set_state(element,~GST_STATE_RUNNING); + return TRUE; +} + +static gboolean gst_audiosink_change_state(GstElement *element, + GstElementState state) { + g_return_if_fail(GST_IS_AUDIOSINK(element)); + + switch (state) { + case GST_STATE_RUNNING: + if (!gst_audiosink_open_audio(GST_AUDIOSINK(element))) + return FALSE; + break; + case ~GST_STATE_RUNNING: + gst_audiosink_close_audio(GST_AUDIOSINK(element)); + break; + default: + break; + } + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + return TRUE; +} diff --git a/plugins/elements/gstaudiosink.h b/plugins/elements/gstaudiosink.h new file mode 100644 index 0000000000..5159eb0a95 --- /dev/null +++ b/plugins/elements/gstaudiosink.h @@ -0,0 +1,85 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_AUDIOSINK_H__ +#define __GST_AUDIOSINK_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_audiosink_details; + + +#define GST_TYPE_AUDIOSINK \ + (gst_audiosink_get_type()) +#define GST_AUDIOSINK(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_AUDIOSINK,GstAudioSink)) +#define GST_AUDIOSINK_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIOSINK,GstAudioSinkClass)) +#define GST_IS_AUDIOSINK(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_AUDIOSINK)) +#define GST_IS_AUDIOSINK_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIOSINK))) + +typedef struct _GstAudioSink GstAudioSink; +typedef struct _GstAudioSinkClass GstAudioSinkClass; + +struct _GstAudioSink { + GstFilter filter; + + GstPad *sinkpad; + + /* soundcard state */ + int fd; + gint format; + gint channels; + gint frequency; +}; + +struct _GstAudioSinkClass { + GstFilterClass parent_class; + + /* signals */ + void (*handoff) (GstElement *element,GstPad *pad); +}; + +GtkType gst_audiosink_get_type(void); +GstElement *gst_audiosink_new(gchar *name); +void gst_audiosink_chain(GstPad *pad,GstBuffer *buf); + +void gst_audiosink_sync_parms(GstAudioSink *audiosink); + +void gst_audiosink_set_format(GstAudioSink *audiosink,gint format); +void gst_audiosink_set_channels(GstAudioSink *audiosink,gint channels); +void gst_audiosink_set_frequency(GstAudioSink *audiosink,gint frequency); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_AUDIOSINK_H__ */ diff --git a/plugins/elements/gstaudiosrc.c b/plugins/elements/gstaudiosrc.c new file mode 100644 index 0000000000..2f06b4c74d --- /dev/null +++ b/plugins/elements/gstaudiosrc.c @@ -0,0 +1,319 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +#include + + +GstElementDetails gst_audiosrc_details = { + "Audio (OSS) Source", + "Source/Audio", + "Read from the sound card", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* AudioSrc signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_LOCATION, + ARG_BYTESPERREAD, + ARG_CUROFFSET, + ARG_FORMAT, + ARG_CHANNELS, + ARG_FREQUENCY, +}; + + +static void gst_audiosrc_class_init(GstAudioSrcClass *klass); +static void gst_audiosrc_init(GstAudioSrc *audiosrc); +static void gst_audiosrc_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_audiosrc_get_arg(GtkObject *object,GtkArg *arg,guint id); +static gboolean gst_audiosrc_change_state(GstElement *element, + GstElementState state); +static void gst_audiosrc_close_audio(GstAudioSrc *src); +static gboolean gst_audiosrc_open_audio(GstAudioSrc *src); +void gst_audiosrc_sync_parms(GstAudioSrc *audiosrc); + + +static GstSrcClass *parent_class = NULL; +static guint gst_audiosrc_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_audiosrc_get_type(void) { + static GtkType audiosrc_type = 0; + + if (!audiosrc_type) { + static const GtkTypeInfo audiosrc_info = { + "GstAudioSrc", + sizeof(GstAudioSrc), + sizeof(GstAudioSrcClass), + (GtkClassInitFunc)gst_audiosrc_class_init, + (GtkObjectInitFunc)gst_audiosrc_init, + (GtkArgSetFunc)gst_audiosrc_set_arg, + (GtkArgGetFunc)gst_audiosrc_get_arg, + (GtkClassInitFunc)NULL, + }; + audiosrc_type = gtk_type_unique(GST_TYPE_SRC,&audiosrc_info); + } + return audiosrc_type; +} + +static void +gst_audiosrc_class_init(GstAudioSrcClass *klass) { + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + GstSrcClass *gstsrc_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + gstsrc_class = (GstSrcClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SRC); + + gtk_object_add_arg_type("GstAudioSrc::location", GTK_TYPE_STRING, + GTK_ARG_READWRITE, ARG_LOCATION); + gtk_object_add_arg_type("GstAudioSrc::bytes_per_read", GTK_TYPE_ULONG, + GTK_ARG_READWRITE, ARG_BYTESPERREAD); + gtk_object_add_arg_type("GstAudioSrc::curoffset", GTK_TYPE_ULONG, + GTK_ARG_READABLE, ARG_CUROFFSET); + gtk_object_add_arg_type("GstAudioSrc::format", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FORMAT); + gtk_object_add_arg_type("GstAudioSrc::channels", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_CHANNELS); + gtk_object_add_arg_type("GstAudioSrc::frequency", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FREQUENCY); + + gtkobject_class->set_arg = gst_audiosrc_set_arg; + gtkobject_class->get_arg = gst_audiosrc_get_arg; + + gstelement_class->change_state = gst_audiosrc_change_state; + + gstsrc_class->push = gst_audiosrc_push; +} + +static void gst_audiosrc_init(GstAudioSrc *audiosrc) { + audiosrc->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(audiosrc),audiosrc->srcpad); + + audiosrc->filename = g_strdup("/dev/dsp"); + audiosrc->fd = -1; + +// audiosrc->meta = (MetaAudioRaw *)gst_meta_new(); +// audiosrc->meta->format = AFMT_S16_LE; +// audiosrc->meta->channels = 2; +// audiosrc->meta->frequency = 44100; +// audiosrc->meta->bps = 4; + + audiosrc->bytes_per_read = 4096; + audiosrc->curoffset = 0; + audiosrc->seq = 0; +} + +GstElement *gst_audiosrc_new(gchar *name) { + GstElement *audiosrc = GST_ELEMENT(gtk_type_new(GST_TYPE_AUDIOSRC)); + gst_element_set_name(GST_ELEMENT(audiosrc),name); + return audiosrc; +} + +GstElement *gst_audiosrc_new_with_fd(gchar *name,gchar *filename) { + GstElement *audiosrc = gst_audiosrc_new(name); + gtk_object_set(GTK_OBJECT(audiosrc),"location",filename,NULL); + return audiosrc; +} + +void gst_audiosrc_push(GstSrc *src) { + GstAudioSrc *audiosrc; + GstBuffer *buf; + glong readbytes; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_AUDIOSRC(src)); + audiosrc = GST_AUDIOSRC(src); + +// g_print("attempting to read something from soundcard\n"); + + buf = gst_buffer_new(); + g_return_if_fail(buf); + GST_BUFFER_DATA(buf) = (gpointer)g_malloc(audiosrc->bytes_per_read); + readbytes = read(audiosrc->fd,GST_BUFFER_DATA(buf), + audiosrc->bytes_per_read); + if (readbytes == 0) { + gst_src_signal_eos(GST_SRC(audiosrc)); + return; + } + + GST_BUFFER_SIZE(buf) = readbytes; + GST_BUFFER_OFFSET(buf) = audiosrc->curoffset; + audiosrc->curoffset += readbytes; + +// gst_buffer_add_meta(buf,GST_META(newmeta)); + + gst_pad_push(audiosrc->srcpad,buf); +// g_print("pushed buffer from soundcard of %d bytes\n",readbytes); +} + +static void gst_audiosrc_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstAudioSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_AUDIOSRC(object)); + src = GST_AUDIOSRC(object); + + switch (id) { + case ARG_LOCATION: + if (src->filename) g_free(src->filename); + if (GTK_VALUE_STRING(*arg) == NULL) { + src->filename = NULL; + gst_element_set_state(GST_ELEMENT(object),~GST_STATE_COMPLETE); + } else { + src->filename = g_strdup(GTK_VALUE_STRING(*arg)); + gst_element_set_state(GST_ELEMENT(object),GST_STATE_COMPLETE); + } + break; + case ARG_BYTESPERREAD: + src->bytes_per_read = GTK_VALUE_INT(*arg); + break; + case ARG_FORMAT: + src->format = GTK_VALUE_INT(*arg); + break; + case ARG_CHANNELS: + src->channels = GTK_VALUE_INT(*arg); + break; + case ARG_FREQUENCY: + src->frequency = GTK_VALUE_INT(*arg); + break; + default: + break; + } +} + +static void gst_audiosrc_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstAudioSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_AUDIOSRC(object)); + src = GST_AUDIOSRC(object); + + switch (id) { + case ARG_LOCATION: + GTK_VALUE_STRING(*arg) = g_strdup(src->filename); + break; + case ARG_BYTESPERREAD: + GTK_VALUE_INT(*arg) = src->bytes_per_read; + break; + case ARG_FORMAT: + GTK_VALUE_INT(*arg) = src->format; + break; + case ARG_CHANNELS: + GTK_VALUE_INT(*arg) = src->channels; + break; + case ARG_FREQUENCY: + GTK_VALUE_INT(*arg) = src->frequency; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static gboolean gst_audiosrc_change_state(GstElement *element, + GstElementState state) { + g_return_if_fail(GST_IS_AUDIOSRC(element)); + + switch (state) { + case GST_STATE_RUNNING: + if (!gst_audiosrc_open_audio(GST_AUDIOSRC(element))) + return FALSE; + break; + case ~GST_STATE_RUNNING: + gst_audiosrc_close_audio(GST_AUDIOSRC(element)); + break; + default: + break; + } + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + return TRUE; +} + +static gboolean gst_audiosrc_open_audio(GstAudioSrc *src) { + g_return_if_fail(src->fd == -1); + + /* first try to open the sound card */ + src->fd = open("/dev/dsp",O_RDONLY); + + /* if we have it, set the default parameters and go have fun */ + if (src->fd > 0) { + int arg = 0x7fff0006; + + if (ioctl(src->fd, SNDCTL_DSP_SETFRAGMENT, &arg)) perror("uh"); + + /* set card state */ + gst_audiosrc_sync_parms(src); + DEBUG("opened audio\n"); + return TRUE; + } + + return FALSE; +} + +static void gst_audiosrc_close_audio(GstAudioSrc *src) { + g_return_if_fail(src->fd >= 0); + + close(src->fd); + src->fd = -1; +} + +void gst_audiosrc_sync_parms(GstAudioSrc *audiosrc) { + audio_buf_info ospace; + + g_return_if_fail(audiosrc != NULL); + g_return_if_fail(GST_IS_AUDIOSRC(audiosrc)); + g_return_if_fail(audiosrc->fd > 0); + + ioctl(audiosrc->fd,SNDCTL_DSP_RESET,0); + + ioctl(audiosrc->fd,SNDCTL_DSP_SETFMT,&audiosrc->format); + ioctl(audiosrc->fd,SNDCTL_DSP_CHANNELS,&audiosrc->channels); + ioctl(audiosrc->fd,SNDCTL_DSP_SPEED,&audiosrc->frequency); + + ioctl(audiosrc->fd,SNDCTL_DSP_GETOSPACE,&ospace); + + g_print("setting sound card to %dKHz %d bit %s (%d bytes buffer)\n", + audiosrc->frequency,audiosrc->format, + (audiosrc->channels == 2) ? "stereo" : "mono",ospace.bytes); + +// audiosrc->meta.format = audiosrc->format; +// audiosrc->meta.channels = audiosrc->channels; +// audiosrc->meta.frequency = audiosrc->frequency; +// audiosrc->sentmeta = FALSE; +} diff --git a/plugins/elements/gstaudiosrc.h b/plugins/elements/gstaudiosrc.h new file mode 100644 index 0000000000..bcaedcf4a3 --- /dev/null +++ b/plugins/elements/gstaudiosrc.h @@ -0,0 +1,90 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_AUDIOSRC_H__ +#define __GST_AUDIOSRC_H__ + + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_audiosrc_details; + + +#define GST_TYPE_AUDIOSRC \ + (gst_audiosrc_get_type()) +#define GST_AUDIOSRC(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_AUDIOSRC,GstAudioSrc)) +#define GST_AUDIOSRC_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIOSRC,GstAudioSrcClass)) +#define GST_IS_AUDIOSRC(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_AUDIOSRC)) +#define GST_IS_AUDIOSRC_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIOSRC))) + +typedef struct _GstAudioSrc GstAudioSrc; +typedef struct _GstAudioSrcClass GstAudioSrcClass; + +struct _GstAudioSrc { + GstSrc src; + + /* pads */ + GstPad *srcpad; + + /* sound card */ + gchar *filename; + gint fd; + + /* audio parameters */ + gint format; + gint channels; + gint frequency; + + /* blocking */ + gulong curoffset; + gulong bytes_per_read; + + gulong seq; + + MetaAudioRaw *meta; +}; + +struct _GstAudioSrcClass { + GstSrcClass parent_class; +}; + +GtkType gst_audiosrc_get_type(void); +GstElement *gst_audiosrc_new(gchar *name); + +void gst_audiosrc_push(GstSrc *src); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_AUDIOSRC_H__ */ diff --git a/plugins/elements/gstdisksrc.c b/plugins/elements/gstdisksrc.c new file mode 100644 index 0000000000..9c0ff78ee7 --- /dev/null +++ b/plugins/elements/gstdisksrc.c @@ -0,0 +1,267 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include + + +GstElementDetails gst_disksrc_details = { + "Disk Source", + "Source/File", + "Synchronous read from a file", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* DiskSrc signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_LOCATION, + ARG_BYTESPERREAD, + ARG_OFFSET, +}; + + +static void gst_disksrc_class_init(GstDiskSrcClass *klass); +static void gst_disksrc_init(GstDiskSrc *disksrc); +static void gst_disksrc_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_disksrc_get_arg(GtkObject *object,GtkArg *arg,guint id); + +static void gst_disksrc_push(GstSrc *src); +static void gst_disksrc_push_region(GstSrc *src,gulong offset,gulong size); +static gboolean gst_disksrc_change_state(GstElement *element, + GstElementState state); + + +static GstSrcClass *parent_class = NULL; +static guint gst_disksrc_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_disksrc_get_type(void) { + static GtkType disksrc_type = 0; + + if (!disksrc_type) { + static const GtkTypeInfo disksrc_info = { + "GstDiskSrc", + sizeof(GstDiskSrc), + sizeof(GstDiskSrcClass), + (GtkClassInitFunc)gst_disksrc_class_init, + (GtkObjectInitFunc)gst_disksrc_init, + (GtkArgSetFunc)gst_disksrc_set_arg, + (GtkArgGetFunc)gst_disksrc_get_arg, + (GtkClassInitFunc)NULL, + }; + disksrc_type = gtk_type_unique(GST_TYPE_SRC,&disksrc_info); + } + return disksrc_type; +} + +static void +gst_disksrc_class_init(GstDiskSrcClass *klass) { + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + GstSrcClass *gstsrc_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + gstsrc_class = (GstSrcClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SRC); + + gtk_object_add_arg_type("GstDiskSrc::location", GTK_TYPE_STRING, + GTK_ARG_READWRITE, ARG_LOCATION); + gtk_object_add_arg_type("GstDiskSrc::bytesperread", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_BYTESPERREAD); + gtk_object_add_arg_type("GstDiskSrc::offset", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_OFFSET); + + gtkobject_class->set_arg = gst_disksrc_set_arg; + gtkobject_class->get_arg = gst_disksrc_get_arg; + + gstelement_class->change_state = gst_disksrc_change_state; + + gstsrc_class->push = gst_disksrc_push; + /* we nominally can't (won't) do async */ + gstsrc_class->push_region = NULL; +} + +static void gst_disksrc_init(GstDiskSrc *disksrc) { + disksrc->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(disksrc),disksrc->srcpad); + + disksrc->filename = NULL; + disksrc->fd = 0; + disksrc->curoffset = 0; + disksrc->bytes_per_read = 4096; + disksrc->seq = 0; +} + + +static void gst_disksrc_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstDiskSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_DISKSRC(object)); + src = GST_DISKSRC(object); + + switch(id) { + case ARG_LOCATION: + /* the element must be stopped in order to do this */ +// g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING)); + + if (src->filename) g_free(src->filename); + /* clear the filename if we get a NULL (is that possible?) */ + if (GTK_VALUE_STRING(*arg) == NULL) { + src->filename = NULL; + gst_element_set_state(GST_ELEMENT(object),~GST_STATE_COMPLETE); + /* otherwise set the new filename */ + } else { + src->filename = g_strdup(GTK_VALUE_STRING(*arg)); + gst_element_set_state(GST_ELEMENT(object),GST_STATE_COMPLETE); + } + break; + case ARG_BYTESPERREAD: + src->bytes_per_read = GTK_VALUE_INT(*arg); + break; + default: + break; + } +} + +static void gst_disksrc_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstDiskSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_DISKSRC(object)); + src = GST_DISKSRC(object); + + switch (id) { + case ARG_LOCATION: + GTK_VALUE_STRING(*arg) = src->filename; + break; + case ARG_BYTESPERREAD: + GTK_VALUE_INT(*arg) = src->bytes_per_read; + break; + case ARG_OFFSET: + GTK_VALUE_INT(*arg) = src->curoffset; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +void gst_disksrc_push(GstSrc *src) { + GstDiskSrc *disksrc; + GstBuffer *buf; + glong readbytes; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_DISKSRC(src)); + g_return_if_fail(GST_FLAG_IS_SET(src,GST_DISKSRC_OPEN)); + disksrc = GST_DISKSRC(src); + + /* create the buffer */ + // FIXME: should eventually use a bufferpool for this + buf = gst_buffer_new(); + g_return_if_fail(buf); + + /* allocate the space for the buffer data */ + GST_BUFFER_DATA(buf) = g_malloc(disksrc->bytes_per_read); + g_return_if_fail(GST_BUFFER_DATA(buf) != NULL); + + /* read it in from the file */ + readbytes = read(disksrc->fd,GST_BUFFER_DATA(buf),disksrc->bytes_per_read); + if (readbytes == 0) { + gst_src_signal_eos(GST_SRC(disksrc)); + return; + } + + /* if we didn't get as many bytes as we asked for, we're at EOF */ + if (readbytes < disksrc->bytes_per_read) + GST_BUFFER_FLAG_SET(buf,GST_BUFFER_EOS); + GST_BUFFER_OFFSET(buf) = disksrc->curoffset; + GST_BUFFER_SIZE(buf) = readbytes; + disksrc->curoffset += readbytes; + + /* we're done, push the buffer off now */ + gst_pad_push(disksrc->srcpad,buf); +} + + +/* open the file, necessary to go to RUNNING state */ +static gboolean gst_disksrc_open_file(GstDiskSrc *src) { + g_return_if_fail(!GST_FLAG_IS_SET(src,GST_DISKSRC_OPEN)); + + /* open the file */ + src->fd = open(src->filename,O_RDONLY); + if (src->fd < 0) { + perror("open()"); + gst_element_error(GST_ELEMENT(src),"opening file"); + return FALSE; + } + GST_FLAG_SET(src,GST_DISKSRC_OPEN); + return TRUE; +} + +/* close the file */ +static void gst_disksrc_close_file(GstDiskSrc *src) { + g_return_if_fail(GST_FLAG_IS_SET(src,GST_DISKSRC_OPEN)); + + /* close the file */ + close(src->fd); + + /* zero out a lot of our state */ + src->fd = 0; + src->curoffset = 0; + src->seq = 0; + + GST_FLAG_UNSET(src,GST_DISKSRC_OPEN); +} + +static gboolean gst_disksrc_change_state(GstElement *element, + GstElementState state) { + g_return_if_fail(GST_IS_DISKSRC(element)); + + switch (state) { + case GST_STATE_RUNNING: + if (!gst_disksrc_open_file(GST_DISKSRC(element))) + return FALSE; + break; + case ~GST_STATE_RUNNING: + gst_disksrc_close_file(GST_DISKSRC(element)); + break; + default: + break; + } + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + return TRUE; +} diff --git a/plugins/elements/gstdisksrc.h b/plugins/elements/gstdisksrc.h new file mode 100644 index 0000000000..bdf2f9e2c5 --- /dev/null +++ b/plugins/elements/gstdisksrc.h @@ -0,0 +1,83 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_DISKSRC_H__ +#define __GST_DISKSRC_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_disksrc_details; + + +#define GST_TYPE_DISKSRC \ + (gst_disksrc_get_type()) +#define GST_DISKSRC(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_DISKSRC,GstDiskSrc)) +#define GST_DISKSRC_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_DISKSRC,GstDiskSrcClass)) +#define GST_IS_DISKSRC(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_DISKSRC)) +#define GST_IS_DISKSRC_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_DISKSRC))) + +// NOTE: per-element flags start with 16 for now +typedef enum { + GST_DISKSRC_OPEN = (1 << 16), +} GstDiskSrcFlags; + +typedef struct _GstDiskSrc GstDiskSrc; +typedef struct _GstDiskSrcClass GstDiskSrcClass; + +struct _GstDiskSrc { + GstSrc src; + /* pads */ + GstPad *srcpad; + + /* filename */ + gchar *filename; + /* fd */ + gint fd; + + gulong curoffset; /* current offset in file */ + gulong bytes_per_read; /* bytes per read */ + + gulong seq; /* buffer sequence number */ +}; + +struct _GstDiskSrcClass { + GstSrcClass parent_class; +}; + +GtkType gst_disksrc_get_type(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_DISKSRC_H__ */ diff --git a/plugins/elements/gstelements.c b/plugins/elements/gstelements.c new file mode 100644 index 0000000000..a44418d20e --- /dev/null +++ b/plugins/elements/gstelements.c @@ -0,0 +1,85 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +struct _elements_entry { + gchar *name; + GtkType (*type) (void); + GstElementDetails *details; +}; + +struct _elements_entry _elements[] = { + { "asyncdisksrc", gst_asyncdisksrc_get_type, &gst_asyncdisksrc_details }, + { "audiosink", gst_audiosink_get_type, &gst_audiosink_details }, + { "audiosrc", gst_audiosrc_get_type, &gst_audiosrc_details }, + { "disksrc", gst_disksrc_get_type, &gst_disksrc_details }, + { "identity", gst_identity_get_type, &gst_identity_details }, + { "fakesink", gst_fakesink_get_type, &gst_fakesink_details }, + { "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details }, + { "fdsink", gst_fdsink_get_type, &gst_fdsink_details }, + { "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details }, + { "httpsrc", gst_httpsrc_get_type, &gst_httpsrc_details }, + { "queue", gst_queue_get_type, &gst_queue_details }, + { "sinesrc", gst_sinesrc_get_type, &gst_sinesrc_details }, + { NULL, 0 }, +}; + +GstPlugin *plugin_init(GModule *module) { + GstPlugin *plugin; + GstElementFactory *factory; + int i = 0; + + if (gst_plugin_find("gstelements") != NULL) return NULL; + + plugin = gst_plugin_new("gstelements"); + g_return_val_if_fail(plugin != NULL,NULL); + + gst_plugin_set_longname(plugin,"Standard GST Elements"); + + while (_elements[i].name) { + factory = gst_elementfactory_new(_elements[i].name, + (_elements[i].type)(), + _elements[i].details); + if (factory != NULL) { + gst_plugin_add_factory(plugin,factory); +// DEBUG("added factory '%s'\n",_elements[i].name); + } + i++; + } + + gst_info("gstelements: loaded %d standard elements\n",i); + + return plugin; +} diff --git a/plugins/elements/gstesdsink.c b/plugins/elements/gstesdsink.c new file mode 100644 index 0000000000..e69de29bb2 diff --git a/plugins/elements/gstesdsink.h b/plugins/elements/gstesdsink.h new file mode 100644 index 0000000000..97dce1e9bf --- /dev/null +++ b/plugins/elements/gstesdsink.h @@ -0,0 +1,81 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_ESDSINK_H__ +#define __GST_ESDSINK_H__ + + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GST_TYPE_ESDSINK \ + (gst_esdsink_get_type()) +#define GST_ESDSINK(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_ESDSINK,GstEsdSink)) +#define GST_ESDSINK_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_ESDSINK,GstEsdSinkClass)) +#define GST_IS_ESDSINK(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_ESDSINK)) +#define GST_IS_ESDSINK_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_ESDSINK))) + +typedef struct _GstEsdSink GstEsdSink; +typedef struct _GstEsdSinkClass GstEsdSinkClass; + +struct _GstEsdSink { + GstFilter filter; + + GstPad *sinkpad; + + /* soundcard state */ + + int fd; + gint format; + gint channels; + gint frequency; +}; + +struct _GstEsdSinkClass { + GstFilterClass parent_class; + + /* signals */ + void (*handoff) (GstElement *element,GstPad *pad); +}; + +GtkType gst_esdsink_get_type(void); +GstElement *gst_esdsink_new(gchar *name); +void gst_esdsink_chain(GstPad *pad,GstBuffer *buf); + +void gst_esdsink_sync_parms(GstEsdSink *esdsink); + +void gst_esdsink_set_format(GstEsdSink *esdsink,gint format); +void gst_esdsink_set_channels(GstEsdSink *esdsink,gint channels); +void gst_esdsink_set_frequency(GstEsdSink *esdsink,gint frequency); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_ESDSINK_H__ */ diff --git a/plugins/elements/gstfakesink.c b/plugins/elements/gstfakesink.c new file mode 100644 index 0000000000..661cd4cc4d --- /dev/null +++ b/plugins/elements/gstfakesink.c @@ -0,0 +1,109 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + + +GstElementDetails gst_fakesink_details = { + "Fake Sink", + "Sink", + "Black hole for data", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* FakeSink signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_fakesink_class_init(GstFakeSinkClass *klass); +static void gst_fakesink_init(GstFakeSink *fakesink); + + +static GstSinkClass *parent_class = NULL; +static guint gst_fakesink_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_fakesink_get_type(void) { + static GtkType fakesink_type = 0; + + if (!fakesink_type) { + static const GtkTypeInfo fakesink_info = { + "GstFakeSink", + sizeof(GstFakeSink), + sizeof(GstFakeSinkClass), + (GtkClassInitFunc)gst_fakesink_class_init, + (GtkObjectInitFunc)gst_fakesink_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + fakesink_type = gtk_type_unique(GST_TYPE_SINK,&fakesink_info); + } + return fakesink_type; +} + +static void +gst_fakesink_class_init(GstFakeSinkClass *klass) { + GstSinkClass *gstsink_class; + + gstsink_class = (GstSinkClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SINK); +} + +static void gst_fakesink_init(GstFakeSink *fakesink) { + fakesink->sinkpad = gst_pad_new("sink",GST_PAD_SINK); + gst_element_add_pad(GST_ELEMENT(fakesink),fakesink->sinkpad); + gst_pad_set_chain_function(fakesink->sinkpad,gst_fakesink_chain); + + // we're already complete, since we don't have any args... + gst_element_set_state(GST_ELEMENT(fakesink),GST_STATE_COMPLETE); +} + +GstElement *gst_fakesink_new(gchar *name) { + GstElement *fakesink = GST_ELEMENT(gtk_type_new(GST_TYPE_FAKESINK)); + gst_element_set_name(GST_ELEMENT(fakesink),name); + return fakesink; +} + +void gst_fakesink_chain(GstPad *pad,GstBuffer *buf) { + GstFakeSink *fakesink; + + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(buf != NULL); + + fakesink = GST_FAKESINK(pad->parent); +// g_print("gst_fakesink_chain: got buffer of %d bytes in '%s'\n", +// buf->datasize,gst_element_get_name(GST_ELEMENT(fakesink))); + g_print("<"); + gst_buffer_unref(buf); +} diff --git a/plugins/elements/gstfakesink.h b/plugins/elements/gstfakesink.h new file mode 100644 index 0000000000..e6617fc21b --- /dev/null +++ b/plugins/elements/gstfakesink.h @@ -0,0 +1,71 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_FAKESINK_H__ +#define __GST_FAKESINK_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_fakesink_details; + + +#define GST_TYPE_FAKESINK \ + (gst_fakesink_get_type()) +#define GST_FAKESINK(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_FAKESINK,GstFakeSink)) +#define GST_FAKESINK_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_FAKESINK,GstFakeSinkClass)) +#define GST_IS_FAKESINK(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_FAKESINK)) +#define GST_IS_FAKESINK_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_FAKESINK))) + +typedef struct _GstFakeSink GstFakeSink; +typedef struct _GstFakeSinkClass GstFakeSinkClass; + +struct _GstFakeSink { + GstSink sink; + + GstPad *sinkpad; +}; + +struct _GstFakeSinkClass { + GstSinkClass parent_class; +}; + +GtkType gst_fakesink_get_type(void); +GstElement *gst_fakesink_new(gchar *name); +void gst_fakesink_chain(GstPad *pad,GstBuffer *buf); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_FAKESINK_H__ */ diff --git a/plugins/elements/gstfakesrc.c b/plugins/elements/gstfakesrc.c new file mode 100644 index 0000000000..6251f11f22 --- /dev/null +++ b/plugins/elements/gstfakesrc.c @@ -0,0 +1,112 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + + +GstElementDetails gst_fakesrc_details = { + "Fake Source", + "Source", + "Push empty (no data) buffers around", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* FakeSrc signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + + +static void gst_fakesrc_class_init(GstFakeSrcClass *klass); +static void gst_fakesrc_init(GstFakeSrc *fakesrc); + + +static GstSrcClass *parent_class = NULL; +static guint gst_fakesrc_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_fakesrc_get_type(void) { + static GtkType fakesrc_type = 0; + + if (!fakesrc_type) { + static const GtkTypeInfo fakesrc_info = { + "GstFakeSrc", + sizeof(GstFakeSrc), + sizeof(GstFakeSrcClass), + (GtkClassInitFunc)gst_fakesrc_class_init, + (GtkObjectInitFunc)gst_fakesrc_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL, + (GtkClassInitFunc)NULL, + }; + fakesrc_type = gtk_type_unique(GST_TYPE_SRC,&fakesrc_info); + } + return fakesrc_type; +} + +static void +gst_fakesrc_class_init(GstFakeSrcClass *klass) { + GstSrcClass *gstsrc_class; + + gstsrc_class = (GstSrcClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SRC); + + gstsrc_class->push = gst_fakesrc_push; + gstsrc_class->push_region = NULL; +} + +static void gst_fakesrc_init(GstFakeSrc *fakesrc) { + fakesrc->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(fakesrc),fakesrc->srcpad); + + // we're already complete, since we don't have any args... + gst_element_set_state(GST_ELEMENT(fakesrc),GST_STATE_COMPLETE); +} + +GstElement *gst_fakesrc_new(gchar *name) { + GstElement *fakesrc = GST_ELEMENT(gtk_type_new(GST_TYPE_FAKESRC)); + gst_element_set_name(GST_ELEMENT(fakesrc),name); + return fakesrc; +} + +void gst_fakesrc_push(GstSrc *src) { + GstFakeSrc *fakesrc; + GstBuffer *buf; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_FAKESRC(src)); + fakesrc = GST_FAKESRC(src); + +// g_print("gst_fakesrc_push(): pushing fake buffer from '%s'\n", +// gst_element_get_name(GST_ELEMENT(fakesrc))); + g_print(">"); + buf = gst_buffer_new(); + gst_pad_push(fakesrc->srcpad,buf); +} diff --git a/plugins/elements/gstfakesrc.h b/plugins/elements/gstfakesrc.h new file mode 100644 index 0000000000..946e0f154c --- /dev/null +++ b/plugins/elements/gstfakesrc.h @@ -0,0 +1,70 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_FAKESRC_H__ +#define __GST_FAKESRC_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_fakesrc_details; + + +#define GST_TYPE_FAKESRC \ + (gst_fakesrc_get_type()) +#define GST_FAKESRC(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_FAKESRC,GstFakeSrc)) +#define GST_FAKESRC_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_FAKESRC,GstFakeSrcClass)) +#define GST_IS_FAKESRC(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_FAKESRC)) +#define GST_IS_FAKESRC_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_FAKESRC))) + +typedef struct _GstFakeSrc GstFakeSrc; +typedef struct _GstFakeSrcClass GstFakeSrcClass; + +struct _GstFakeSrc { + GstSrc src; + + GstPad *srcpad; +}; + +struct _GstFakeSrcClass { + GstSrcClass parent_class; +}; + +GtkType gst_fakesrc_get_type(void); +GstElement *gst_fakesrc_new(gchar *name); +void gst_fakesrc_push(GstSrc *src); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_FAKESRC_H__ */ diff --git a/plugins/elements/gstfdsink.c b/plugins/elements/gstfdsink.c new file mode 100644 index 0000000000..136f37c0b2 --- /dev/null +++ b/plugins/elements/gstfdsink.c @@ -0,0 +1,155 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + + +GstElementDetails gst_fdsink_details = { + "Filedescriptor Sink", + "Sink", + "Write data to a file descriptor", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* FdSink signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_FD +}; + + +static void gst_fdsink_class_init(GstFdSinkClass *klass); +static void gst_fdsink_init(GstFdSink *fdsink); +static void gst_fdsink_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_fdsink_get_arg(GtkObject *object,GtkArg *arg,guint id); + + +static GstSinkClass *parent_class = NULL; +static guint gst_fdsink_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_fdsink_get_type(void) { + static GtkType fdsink_type = 0; + + if (!fdsink_type) { + static const GtkTypeInfo fdsink_info = { + "GstFdSink", + sizeof(GstFdSink), + sizeof(GstFdSinkClass), + (GtkClassInitFunc)gst_fdsink_class_init, + (GtkObjectInitFunc)gst_fdsink_init, + (GtkArgSetFunc)gst_fdsink_set_arg, + (GtkArgGetFunc)gst_fdsink_get_arg, + (GtkClassInitFunc)NULL, + }; + fdsink_type = gtk_type_unique(GST_TYPE_SINK,&fdsink_info); + } + return fdsink_type; +} + +static void +gst_fdsink_class_init(GstFdSinkClass *klass) { + GtkObjectClass *gtkobject_class; + GstSinkClass *gstsink_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstsink_class = (GstSinkClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SINK); + + gtk_object_add_arg_type("GstFdSink::fd", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FD); + + gtkobject_class->set_arg = gst_fdsink_set_arg; + gtkobject_class->get_arg = gst_fdsink_get_arg; +} + +static void gst_fdsink_init(GstFdSink *fdsink) { + fdsink->sinkpad = gst_pad_new("sink",GST_PAD_SINK); + gst_element_add_pad(GST_ELEMENT(fdsink),fdsink->sinkpad); + gst_pad_set_chain_function(fdsink->sinkpad,gst_fdsink_chain); + + fdsink->fd = 1; +} + +GstElement *gst_fdsink_new(gchar *name) { + GstElement *fdsink = GST_ELEMENT(gtk_type_new(GST_TYPE_FDSINK)); + gst_element_set_name(GST_ELEMENT(fdsink),name); + return fdsink; +} + +GstElement *gst_fdsink_new_with_fd(gchar *name,gint fd) { + GstElement *fdsink = gst_fdsink_new(name); + gtk_object_set(GTK_OBJECT(fdsink),"fd",fd,NULL); + return fdsink; +} + +void gst_fdsink_chain(GstPad *pad,GstBuffer *buf) { + GstFdSink *fdsink; + + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(buf != NULL); + + fdsink = GST_FDSINK(pad->parent); + g_return_if_fail(fdsink->fd >= 0); + if (GST_BUFFER_DATA(buf)) + write(fdsink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf)); + gst_buffer_unref(buf); +} + +static void gst_fdsink_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstFdSink *fdsink; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_FDSINK(object)); + fdsink = GST_FDSINK(object); + + switch(id) { + case ARG_FD: + fdsink->fd = GTK_VALUE_INT(*arg); + break; + default: + break; + } +} + +static void gst_fdsink_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstFdSink *fdsink; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_FDSINK(object)); + fdsink = GST_FDSINK(object); + + switch(id) { + case ARG_FD: + GTK_VALUE_INT(*arg) = fdsink->fd; + break; + default: + break; + } +} diff --git a/plugins/elements/gstfdsink.h b/plugins/elements/gstfdsink.h new file mode 100644 index 0000000000..8a7cba37bf --- /dev/null +++ b/plugins/elements/gstfdsink.h @@ -0,0 +1,74 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_FDSINK_H__ +#define __GST_FDSINK_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_fdsink_details; + + +#define GST_TYPE_FDSINK \ + (gst_fdsink_get_type()) +#define GST_FDSINK(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_FDSINK,GstFdSink)) +#define GST_FDSINK_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_FDSINK,GstFdSinkClass)) +#define GST_IS_FDSINK(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_FDSINK)) +#define GST_IS_FDSINK_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_FDSINK))) + +typedef struct _GstFdSink GstFdSink; +typedef struct _GstFdSinkClass GstFdSinkClass; + +struct _GstFdSink { + GstSink sink; + + GstPad *sinkpad; + + int fd; +}; + +struct _GstFdSinkClass { + GstSinkClass parent_class; +}; + +GtkType gst_fdsink_get_type(void); +GstElement *gst_fdsink_new(gchar *name); +GstElement *gst_fdsink_new_with_fd(gchar *name,gint fd); +void gst_fdsink_chain(GstPad *pad,GstBuffer *buf); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_FDSINK_H__ */ diff --git a/plugins/elements/gstfdsrc.c b/plugins/elements/gstfdsrc.c new file mode 100644 index 0000000000..f24c06e2c4 --- /dev/null +++ b/plugins/elements/gstfdsrc.c @@ -0,0 +1,206 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include + + +GstElementDetails gst_fdsrc_details = { + "Disk Source", + "Source/File", + "Synchronous read from a file", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* FdSrc signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_LOCATION, + ARG_BYTESPERREAD, + ARG_OFFSET, +}; + + +static void gst_fdsrc_class_init(GstFdSrcClass *klass); +static void gst_fdsrc_init(GstFdSrc *fdsrc); +static void gst_fdsrc_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_fdsrc_get_arg(GtkObject *object,GtkArg *arg,guint id); + +static void gst_fdsrc_push(GstSrc *src); +static void gst_fdsrc_push_region(GstSrc *src,gulong offset,gulong size); + + +static GstSrcClass *parent_class = NULL; +static guint gst_fdsrc_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_fdsrc_get_type(void) { + static GtkType fdsrc_type = 0; + + if (!fdsrc_type) { + static const GtkTypeInfo fdsrc_info = { + "GstFdSrc", + sizeof(GstFdSrc), + sizeof(GstFdSrcClass), + (GtkClassInitFunc)gst_fdsrc_class_init, + (GtkObjectInitFunc)gst_fdsrc_init, + (GtkArgSetFunc)gst_fdsrc_set_arg, + (GtkArgGetFunc)gst_fdsrc_get_arg, + (GtkClassInitFunc)NULL, + }; + fdsrc_type = gtk_type_unique(GST_TYPE_SRC,&fdsrc_info); + } + return fdsrc_type; +} + +static void +gst_fdsrc_class_init(GstFdSrcClass *klass) { + GtkObjectClass *gtkobject_class; + GstSrcClass *gstsrc_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstsrc_class = (GstSrcClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SRC); + + gtk_object_add_arg_type("GstFdSrc::location", GTK_TYPE_STRING, + GTK_ARG_WRITABLE, ARG_LOCATION); + gtk_object_add_arg_type("GstFdSrc::bytesperread", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_BYTESPERREAD); + gtk_object_add_arg_type("GstFdSrc::offset", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_OFFSET); + + gtkobject_class->set_arg = gst_fdsrc_set_arg; + gtkobject_class->get_arg = gst_fdsrc_get_arg; + + gstsrc_class->push = gst_fdsrc_push; + /* we nominally can't (won't) do async */ + gstsrc_class->push_region = NULL; +} + +static void gst_fdsrc_init(GstFdSrc *fdsrc) { + fdsrc->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(fdsrc),fdsrc->srcpad); + + fdsrc->fd = 0; + fdsrc->curoffset = 0; + fdsrc->bytes_per_read = 4096; + fdsrc->seq = 0; +} + + +static void gst_fdsrc_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstFdSrc *src; + int fd; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_FDSRC(object)); + src = GST_FDSRC(object); + + switch(id) { + case ARG_LOCATION: + /* the element must be stopped in order to do this */ + g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING)); + + /* if we get a NULL, consider it to be a fd of 0 */ + if (GTK_VALUE_STRING(*arg) == NULL) { + src->fd = 0; + gst_element_set_state(GST_ELEMENT(object),~GST_STATE_COMPLETE); + /* otherwise set the new filename */ + } else { + if (sscanf(GTK_VALUE_STRING(*arg),"%d",&fd)) + src->fd = fd; + gst_element_set_state(GST_ELEMENT(object),GST_STATE_COMPLETE); + } + break; + case ARG_BYTESPERREAD: + src->bytes_per_read = GTK_VALUE_INT(*arg); + break; + default: + break; + } +} + +static void gst_fdsrc_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstFdSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_FDSRC(object)); + src = GST_FDSRC(object); + + switch (id) { + case ARG_BYTESPERREAD: + GTK_VALUE_INT(*arg) = src->bytes_per_read; + break; + case ARG_OFFSET: + GTK_VALUE_INT(*arg) = src->curoffset; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +void gst_fdsrc_push(GstSrc *src) { + GstFdSrc *fdsrc; + GstBuffer *buf; + glong readbytes; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_FDSRC(src)); + fdsrc = GST_FDSRC(src); + + /* create the buffer */ + // FIXME: should eventually use a bufferpool for this + buf = gst_buffer_new(); + g_return_if_fail(buf); + + /* allocate the space for the buffer data */ + GST_BUFFER_DATA(buf) = g_malloc(fdsrc->bytes_per_read); + g_return_if_fail(GST_BUFFER_DATA(buf) != NULL); + + /* read it in from the file */ + readbytes = read(fdsrc->fd,GST_BUFFER_DATA(buf),fdsrc->bytes_per_read); + if (readbytes == 0) { + gst_src_signal_eos(GST_SRC(fdsrc)); + return; + } + + /* if we didn't get as many bytes as we asked for, we're at EOF */ + if (readbytes < fdsrc->bytes_per_read) { + // FIXME: set the buffer's EOF bit here + } + GST_BUFFER_OFFSET(buf) = fdsrc->curoffset; + GST_BUFFER_SIZE(buf) = readbytes; + fdsrc->curoffset += readbytes; + + /* we're done, push the buffer off now */ + gst_pad_push(fdsrc->srcpad,buf); +} diff --git a/plugins/elements/gstfdsrc.h b/plugins/elements/gstfdsrc.h new file mode 100644 index 0000000000..1b85e065fb --- /dev/null +++ b/plugins/elements/gstfdsrc.h @@ -0,0 +1,77 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_FDSRC_H__ +#define __GST_FDSRC_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_fdsrc_details; + + +#define GST_TYPE_FDSRC \ + (gst_fdsrc_get_type()) +#define GST_FDSRC(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_FDSRC,GstFdSrc)) +#define GST_FDSRC_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_FDSRC,GstFdSrcClass)) +#define GST_IS_FDSRC(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_FDSRC)) +#define GST_IS_FDSRC_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_FDSRC))) + + +typedef struct _GstFdSrc GstFdSrc; +typedef struct _GstFdSrcClass GstFdSrcClass; + +struct _GstFdSrc { + GstSrc src; + /* pads */ + GstPad *srcpad; + + /* fd */ + gint fd; + + gulong curoffset; /* current offset in file */ + gulong bytes_per_read; /* bytes per read */ + + gulong seq; /* buffer sequence number */ +}; + +struct _GstFdSrcClass { + GstSrcClass parent_class; +}; + +GtkType gst_fdsrc_get_type(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_FDSRC_H__ */ diff --git a/plugins/elements/gsthttpsrc.c b/plugins/elements/gsthttpsrc.c new file mode 100644 index 0000000000..3b378ed620 --- /dev/null +++ b/plugins/elements/gsthttpsrc.c @@ -0,0 +1,258 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include + + +GstElementDetails gst_httpsrc_details = { + "HTTP Source", + "Source/Network", + "Read data from an HTTP stream", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +static void gst_httpsrc_push(GstSrc *src); +static gboolean gst_httpsrc_open_url(GstHttpSrc *src); +static void gst_httpsrc_close_url(GstHttpSrc *src); +static gboolean gst_httpsrc_change_state(GstElement *element, + GstElementState state); + + +/* HttpSrc signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_LOCATION, + ARG_BYTESPERREAD, + ARG_OFFSET +}; + + +static void gst_httpsrc_class_init(GstHttpSrcClass *klass); +static void gst_httpsrc_init(GstHttpSrc *httpsrc); +static void gst_httpsrc_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_httpsrc_get_arg(GtkObject *object,GtkArg *arg,guint id); + + +static GstSrcClass *parent_class = NULL; +static guint gst_httpsrc_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_httpsrc_get_type(void) { + static GtkType httpsrc_type = 0; + + if (!httpsrc_type) { + static const GtkTypeInfo httpsrc_info = { + "GstHttpSrc", + sizeof(GstHttpSrc), + sizeof(GstHttpSrcClass), + (GtkClassInitFunc)gst_httpsrc_class_init, + (GtkObjectInitFunc)gst_httpsrc_init, + (GtkArgSetFunc)gst_httpsrc_set_arg, + (GtkArgGetFunc)gst_httpsrc_get_arg, + (GtkClassInitFunc)NULL, + }; + httpsrc_type = gtk_type_unique(GST_TYPE_SRC,&httpsrc_info); + } + return httpsrc_type; +} + +static void +gst_httpsrc_class_init(GstHttpSrcClass *klass) { + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + GstSrcClass *gstsrc_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + gstsrc_class = (GstSrcClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SRC); + + + gtk_object_add_arg_type("GstHttpSrc::location", GTK_TYPE_STRING, + GTK_ARG_READWRITE, ARG_LOCATION); + gtk_object_add_arg_type("GstHttpSrc::bytesperread", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_BYTESPERREAD); + + gtkobject_class->set_arg = gst_httpsrc_set_arg; + gtkobject_class->get_arg = gst_httpsrc_get_arg; + + gstelement_class->change_state = gst_httpsrc_change_state; + + gstsrc_class->push = gst_httpsrc_push; + gstsrc_class->push_region = NULL; +} + +static void gst_httpsrc_init(GstHttpSrc *httpsrc) { + httpsrc->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(httpsrc),httpsrc->srcpad); + + httpsrc->url = NULL; + httpsrc->request = NULL; + httpsrc->fd = 0; + httpsrc->curoffset = 0; + httpsrc->bytes_per_read = 4096; +} + +static void gst_httpsrc_push(GstSrc *src) { + GstHttpSrc *httpsrc; + GstBuffer *buf; + glong readbytes; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_HTTPSRC(src)); +// g_return_if_fail(GST_FLAG_IS_SET(src,GST_)); + httpsrc = GST_HTTPSRC(src); + + buf = gst_buffer_new(); + GST_BUFFER_DATA(buf) = (gpointer)malloc(httpsrc->bytes_per_read); + readbytes = read(httpsrc->fd,GST_BUFFER_DATA(buf),httpsrc->bytes_per_read); + if (readbytes == 0) { + gst_src_signal_eos(GST_SRC(httpsrc)); + return; + } + + if (readbytes < httpsrc->bytes_per_read) { + // FIXME: set the buffer's EOF bit here + } + GST_BUFFER_OFFSET(buf) = httpsrc->curoffset; + GST_BUFFER_SIZE(buf) = readbytes; + httpsrc->curoffset += readbytes; + + gst_pad_push(httpsrc->srcpad,buf); +} + +static gboolean gst_httpsrc_open_url(GstHttpSrc *httpsrc) { + gint status; + + g_return_if_fail(httpsrc != NULL); + g_return_if_fail(GST_IS_HTTPSRC(httpsrc)); + g_return_if_fail(httpsrc->url != NULL); + + httpsrc->request = ghttp_request_new(); + ghttp_set_uri(httpsrc->request,httpsrc->url); + ghttp_set_sync(httpsrc->request,ghttp_async); + ghttp_set_header(httpsrc->request,"User-Agent","GstHttpSrc"); + ghttp_prepare(httpsrc->request); + + /* process everything up to the actual data stream */ + /* FIXME: should be in preroll, but hey */ + status = 0; + while ((ghttp_get_status(httpsrc->request).proc != ghttp_proc_response) + && (status >= 0)) { + status = ghttp_process(httpsrc->request); + } + + /* get the fd so we can read data ourselves */ + httpsrc->fd = ghttp_get_socket(httpsrc->request); + return TRUE; +} + +/* unmap and close the file */ +static void gst_httpsrc_close_url(GstHttpSrc *src) { + g_return_if_fail(src->fd > 0); + + close(src->fd); + src->fd = 0; +} + +static void gst_httpsrc_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstHttpSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_HTTPSRC(object)); + src = GST_HTTPSRC(object); + + switch(id) { + case ARG_LOCATION: + /* the element must be stopped in order to do this */ + g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING)); + + if (src->url) g_free(src->url); + /* clear the url if we get a NULL (is that possible?) */ + if (GTK_VALUE_STRING(*arg) == NULL) { + src->url = NULL; + gst_element_set_state(GST_ELEMENT(object),~GST_STATE_COMPLETE); + /* otherwise set the new url */ + } else { + src->url = g_strdup(GTK_VALUE_STRING(*arg)); + gst_element_set_state(GST_ELEMENT(object),GST_STATE_COMPLETE); + } + break; + case ARG_BYTESPERREAD: + src->bytes_per_read = GTK_VALUE_INT(*arg); + break; + default: + break; + } +} + +static void gst_httpsrc_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstHttpSrc *httpsrc; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_HTTPSRC(object)); + httpsrc = GST_HTTPSRC(object); + + switch (id) { + case ARG_LOCATION: + GTK_VALUE_STRING(*arg) = httpsrc->url; + break; + case ARG_BYTESPERREAD: + GTK_VALUE_INT(*arg) = httpsrc->bytes_per_read; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static gboolean gst_httpsrc_change_state(GstElement *element, + GstElementState state) { + g_return_if_fail(GST_IS_HTTPSRC(element)); + + switch (state) { + case GST_STATE_RUNNING: + if (!gst_httpsrc_open_url(GST_HTTPSRC(element))) + return FALSE; + break; + case ~GST_STATE_RUNNING: + gst_httpsrc_close_url(GST_HTTPSRC(element)); + break; + default: + break; + } + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + return TRUE; +} + diff --git a/plugins/elements/gsthttpsrc.h b/plugins/elements/gsthttpsrc.h new file mode 100644 index 0000000000..ae55f293f2 --- /dev/null +++ b/plugins/elements/gsthttpsrc.h @@ -0,0 +1,77 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_HTTPSRC_H__ +#define __GST_HTTPSRC_H__ + + +#include +#include + +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_httpsrc_details; + + +#define GST_TYPE_HTTPSRC \ + (gst_httpsrc_get_type()) +#define GST_HTTPSRC(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_HTTPSRC,GstHttpSrc)) +#define GST_HTTPSRC_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_HTTPSRC,GstHttpSrcClass)) +#define GST_IS_HTTPSRC(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_HTTPSRC)) +#define GST_IS_HTTPSRC_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_HTTPSRC))) + +typedef struct _GstHttpSrc GstHttpSrc; +typedef struct _GstHttpSrcClass GstHttpSrcClass; + +struct _GstHttpSrc { + GstSrc src; + /* pads */ + GstPad *srcpad; + + gchar *url; + ghttp_request *request; + int fd; + + gulong curoffset; /* current offset in file */ + gulong bytes_per_read; /* bytes per read */ +}; + +struct _GstHttpSrcClass { + GstSrcClass parent_class; +}; + +GtkType gst_httpsrc_get_type(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_HTTPSRC_H__ */ diff --git a/plugins/elements/gstidentity.c b/plugins/elements/gstidentity.c new file mode 100644 index 0000000000..4896f5de88 --- /dev/null +++ b/plugins/elements/gstidentity.c @@ -0,0 +1,152 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + + +GstElementDetails gst_identity_details = { + "Identity", + "Filter", + "Pass data without modification", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* Identity signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_CONTROL +}; + + +static void gst_identity_class_init(GstIdentityClass *klass); +static void gst_identity_init(GstIdentity *identity); +static void gst_identity_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_identity_get_arg(GtkObject *object,GtkArg *arg,guint id); + + +static GstFilterClass *parent_class = NULL; +static guint gst_identity_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_identity_get_type(void) { + static GtkType identity_type = 0; + + if (!identity_type) { + static const GtkTypeInfo identity_info = { + "GstIdentity", + sizeof(GstIdentity), + sizeof(GstIdentityClass), + (GtkClassInitFunc)gst_identity_class_init, + (GtkObjectInitFunc)gst_identity_init, + (GtkArgSetFunc)gst_identity_set_arg, + (GtkArgGetFunc)gst_identity_get_arg, + (GtkClassInitFunc)NULL, + }; + identity_type = gtk_type_unique(GST_TYPE_FILTER,&identity_info); + } + return identity_type; +} + +static void gst_identity_class_init(GstIdentityClass *klass) { + GtkObjectClass *gtkobject_class; + GstFilterClass *gstfilter_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstfilter_class = (GstFilterClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_FILTER); + + gtk_object_add_arg_type("GstIdentity::control", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_CONTROL); + + gtkobject_class->set_arg = gst_identity_set_arg; + gtkobject_class->get_arg = gst_identity_get_arg; +} + +static void gst_identity_init(GstIdentity *identity) { + identity->sinkpad = gst_pad_new("sink",GST_PAD_SINK); + gst_element_add_pad(GST_ELEMENT(identity),identity->sinkpad); + gst_pad_set_chain_function(identity->sinkpad,gst_identity_chain); + identity->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(identity),identity->srcpad); + + identity->control = 0; +} + +GstElement *gst_identity_new(gchar *name) { + GstElement *identity = GST_ELEMENT(gtk_type_new(GST_TYPE_IDENTITY)); + gst_element_set_name(GST_ELEMENT(identity),name); + return identity; +} + +void gst_identity_chain(GstPad *pad,GstBuffer *buf) { + GstIdentity *identity; + + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(buf != NULL); + + identity = GST_IDENTITY(pad->parent); +// g_print("gst_identity_chain: got buffer in '%s'\n", +// gst_element_get_name(GST_ELEMENT(identity))); + g_print("i"); + gst_pad_push(identity->srcpad,buf); +} + +static void gst_identity_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstIdentity *identity; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_IDENTITY(object)); + identity = GST_IDENTITY(object); + + switch(id) { + case ARG_CONTROL: + identity->control = GTK_VALUE_INT(*arg); + break; + default: + break; + } +} + +static void gst_identity_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstIdentity *identity; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_IDENTITY(object)); + identity = GST_IDENTITY(object); + + switch (id) { + case ARG_CONTROL: + GTK_VALUE_INT(*arg) = identity->control; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} diff --git a/plugins/elements/gstidentity.h b/plugins/elements/gstidentity.h new file mode 100644 index 0000000000..f186a49847 --- /dev/null +++ b/plugins/elements/gstidentity.h @@ -0,0 +1,74 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_IDENTITY_H__ +#define __GST_IDENTITY_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_identity_details; + + +#define GST_TYPE_IDENTITY \ + (gst_identity_get_type()) +#define GST_IDENTITY(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_IDENTITY,GstIdentity)) +#define GST_IDENTITY_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_IDENTITY,GstIdentityClass)) +#define GST_IS_IDENTITY(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_IDENTITY)) +#define GST_IS_IDENTITY_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_IDENTITY))) + +typedef struct _GstIdentity GstIdentity; +typedef struct _GstIdentityClass GstIdentityClass; + +struct _GstIdentity { + GstFilter filter; + + GstPad *sinkpad; + GstPad *srcpad; + + gint control; +}; + +struct _GstIdentityClass { + GstFilterClass parent_class; +}; + +GtkType gst_identity_get_type(void); +GstElement *gst_identity_new(gchar *name); +void gst_identity_chain(GstPad *pad,GstBuffer *buf); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_IDENTITY_H__ */ diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c new file mode 100644 index 0000000000..2abf235a0d --- /dev/null +++ b/plugins/elements/gstqueue.c @@ -0,0 +1,216 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include + + +GstElementDetails gst_queue_details = { + "Queue", + "Connection", + "Simple data queue", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* Queue signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_LEVEL, +}; + + +static void gst_queue_class_init(GstQueueClass *klass); +static void gst_queue_init(GstQueue *queue); +static void gst_queue_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_queue_get_arg(GtkObject *object,GtkArg *arg,guint id); + + +static GstConnectionClass *parent_class = NULL; +static guint gst_queue_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_queue_get_type(void) { + static GtkType queue_type = 0; + + if (!queue_type) { + static const GtkTypeInfo queue_info = { + "GstQueue", + sizeof(GstQueue), + sizeof(GstQueueClass), + (GtkClassInitFunc)gst_queue_class_init, + (GtkObjectInitFunc)gst_queue_init, + (GtkArgSetFunc)gst_queue_set_arg, + (GtkArgGetFunc)gst_queue_get_arg, + (GtkClassInitFunc)NULL, + }; + queue_type = gtk_type_unique(GST_TYPE_CONNECTION,&queue_info); + } + return queue_type; +} + +static void gst_queue_class_init(GstQueueClass *klass) { + GtkObjectClass *gtkobject_class; + GstConnectionClass *gstconnection_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstconnection_class = (GstConnectionClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_CONNECTION); + + gtk_object_add_arg_type("GstQueue::level", GTK_TYPE_INT, + GTK_ARG_READABLE, ARG_LEVEL); + + gstconnection_class->push = gst_queue_push; + + gtkobject_class->set_arg = gst_queue_set_arg; + gtkobject_class->get_arg = gst_queue_get_arg; +} + +static void gst_queue_init(GstQueue *queue) { + queue->sinkpad = gst_pad_new("sink",GST_PAD_SINK); + gst_element_add_pad(GST_ELEMENT(queue),queue->sinkpad); + gst_pad_set_chain_function(queue->sinkpad,gst_queue_chain); + queue->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(queue),queue->srcpad); + + queue->queue = NULL; + queue->tail = NULL; + queue->level_buffers = 0; + queue->level_bytes = 0; + queue->size_buffers = 0; + queue->size_bytes = 0; + + queue->waiterlock = g_mutex_new(); + queue->waitercond = g_cond_new(); +} + +GstElement *gst_queue_new(gchar *name) { + GstElement *queue = GST_ELEMENT(gtk_type_new(GST_TYPE_QUEUE)); + gst_element_set_name(GST_ELEMENT(queue),name); + return queue; +} + +void gst_queue_chain(GstPad *pad,GstBuffer *buf) { + GstQueue *queue; + gboolean tosignal = FALSE; + + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(buf != NULL); + + queue = GST_QUEUE(pad->parent); + + /* we have to lock the queue since we span threads */ + GST_LOCK(queue); + + /* put the buffer on the head of the list */ + /* if the queue is NULL, start a new list and make this the tail */ + if (!queue->queue) { + queue->queue = g_list_prepend(queue->queue,buf); +// queue->tail = queue->queue; + /* otherwise append to the end of the list */ + } else { +// queue->tail = g_list_append(queue->tail,buf); +// queue->tail = g_list_next(queue->tail); + queue->queue = g_list_append(queue->queue,buf); + } +// g_print("+"); + + /* if we were empty, but aren't any more, signal a condition */ + tosignal = (queue->level_buffers++ == 0); + + /* we can unlock now */ + GST_UNLOCK(queue); + + if (tosignal) { + g_mutex_lock(queue->waiterlock); + g_cond_signal(queue->waitercond); + g_mutex_unlock(queue->waiterlock); +// g_print(">"); + } +} + +void gst_queue_push(GstConnection *connection) { + GstQueue *queue = GST_QUEUE(connection); + GstBuffer *buf = NULL; + GList *front; + + /* have to lock for thread-safety */ + GST_LOCK(queue); + + if (!queue->level_buffers) { + GST_UNLOCK(queue); + while (!queue->level_buffers) { + g_mutex_lock(queue->waiterlock); +// g_print("0"); + g_cond_wait(queue->waitercond,queue->waiterlock); + g_mutex_unlock(queue->waiterlock); + } + GST_LOCK(queue); + } + + front = queue->queue; + buf = (GstBuffer *)(front->data); + queue->queue = g_list_remove_link(queue->queue,front); + gst_pad_push(queue->srcpad,buf); + queue->level_buffers--; +// g_print("-"); + + /* unlock now */ + GST_UNLOCK(queue); +} + + +static void gst_queue_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstQueue *queue; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_QUEUE(object)); + queue = GST_QUEUE(object); + + switch(id) { + default: + break; + } +} + +static void gst_queue_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstQueue *queue; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_QUEUE(object)); + queue = GST_QUEUE(object); + + switch (id) { + case ARG_LEVEL: + GTK_VALUE_INT(*arg) = queue->level_buffers; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} diff --git a/plugins/elements/gstqueue.h b/plugins/elements/gstqueue.h new file mode 100644 index 0000000000..5ce8d6f57b --- /dev/null +++ b/plugins/elements/gstqueue.h @@ -0,0 +1,84 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_QUEUE_H__ +#define __GST_QUEUE_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_queue_details; + + +#define GST_TYPE_QUEUE \ + (gst_queue_get_type()) +#define GST_QUEUE(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_QUEUE,GstQueue)) +#define GST_QUEUE_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_QUEUE,GstQueueClass)) +#define GST_IS_QUEUE(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_QUEUE)) +#define GST_IS_QUEUE_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_QUEUE))) + +typedef struct _GstQueue GstQueue; +typedef struct _GstQueueClass GstQueueClass; + +struct _GstQueue { + GstConnection Connection; + + GstPad *sinkpad; + GstPad *srcpad; + + /* the queue of buffers we're keeping our grubby hands on */ + GList *queue; + GList *tail; /* have to keep track of this myself */ + + gint level_buffers; /* number of buffers queued here */ + gint level_bytes; /* number of bytes queued here */ + gint size_buffers; /* size of queue in buffers */ + gint size_bytes; /* size of queue in bytes */ + + GMutex *waiterlock; /* used when the queue is empty */ + GCond *waitercond; +}; + +struct _GstQueueClass { + GstConnectionClass parent_class; +}; + +GtkType gst_queue_get_type(void); +GstElement *gst_queue_new(gchar *name); +void gst_queue_chain(GstPad *pad,GstBuffer *buf); +void gst_queue_push(GstConnection *connection); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_QUEUE_H__ */ diff --git a/plugins/elements/gstsinesrc.c b/plugins/elements/gstsinesrc.c new file mode 100644 index 0000000000..ede6f38edb --- /dev/null +++ b/plugins/elements/gstsinesrc.c @@ -0,0 +1,269 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +#include + + +GstElementDetails gst_sinesrc_details = { + "Sine-wave src", + "Source/Audio", + "Create a sine wave of a given frequency and volume", + VERSION, + "Erik Walthinsen ", + "(C) 1999", +}; + + +/* SineSrc signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_VOLUME, + ARG_FREQ, + ARG_FORMAT, + ARG_CHANNELS, + ARG_FREQUENCY, +}; + + +static void gst_sinesrc_class_init(GstSineSrcClass *klass); +static void gst_sinesrc_init(GstSineSrc *sinesrc); +static void gst_sinesrc_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_sinesrc_get_arg(GtkObject *object,GtkArg *arg,guint id); +//static gboolean gst_sinesrc_change_state(GstElement *element, +// GstElementState state); +static void gst_sinesrc_close_audio(GstSineSrc *src); +static gboolean gst_sinesrc_open_audio(GstSineSrc *src); +void gst_sinesrc_sync_parms(GstSineSrc *sinesrc); + + +static GstSrcClass *parent_class = NULL; +static guint gst_sinesrc_signals[LAST_SIGNAL] = { 0 }; + +GtkType +gst_sinesrc_get_type(void) { + static GtkType sinesrc_type = 0; + + if (!sinesrc_type) { + static const GtkTypeInfo sinesrc_info = { + "GstSineSrc", + sizeof(GstSineSrc), + sizeof(GstSineSrcClass), + (GtkClassInitFunc)gst_sinesrc_class_init, + (GtkObjectInitFunc)gst_sinesrc_init, + (GtkArgSetFunc)gst_sinesrc_set_arg, + (GtkArgGetFunc)gst_sinesrc_get_arg, + (GtkClassInitFunc)NULL, + }; + sinesrc_type = gtk_type_unique(GST_TYPE_SRC,&sinesrc_info); + } + return sinesrc_type; +} + +static void +gst_sinesrc_class_init(GstSineSrcClass *klass) { + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + GstSrcClass *gstsrc_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + gstsrc_class = (GstSrcClass*)klass; + + parent_class = gtk_type_class(GST_TYPE_SRC); + + gtk_object_add_arg_type("GstSineSrc::volume", GTK_TYPE_DOUBLE, + GTK_ARG_READWRITE, ARG_VOLUME); + gtk_object_add_arg_type("GstSineSrc::freq", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FREQ); + gtk_object_add_arg_type("GstSineSrc::format", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FORMAT); + gtk_object_add_arg_type("GstSineSrc::channels", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_CHANNELS); + gtk_object_add_arg_type("GstSineSrc::frequency", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FREQUENCY); + + gtkobject_class->set_arg = gst_sinesrc_set_arg; + gtkobject_class->get_arg = gst_sinesrc_get_arg; + +// gstelement_class->change_state = gst_sinesrc_change_state; + + gstsrc_class->push = gst_sinesrc_push; +} + +static void gst_sinesrc_init(GstSineSrc *sinesrc) { + sinesrc->srcpad = gst_pad_new("src",GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(sinesrc),sinesrc->srcpad); + + sinesrc->volume = 1.0; + sinesrc->freq = 512; + + sinesrc->format = AFMT_S16_LE; + sinesrc->channels = 2; + sinesrc->frequency = 44100; + + sinesrc->seq = 0; + + sinesrc->sentmeta = FALSE; +} + +GstElement *gst_sinesrc_new(gchar *name) { + GstElement *sinesrc = GST_ELEMENT(gtk_type_new(GST_TYPE_SINESRC)); + gst_element_set_name(GST_ELEMENT(sinesrc),name); + return sinesrc; +} + +GstElement *gst_sinesrc_new_with_fd(gchar *name,gchar *filename) { + GstElement *sinesrc = gst_sinesrc_new(name); + gtk_object_set(GTK_OBJECT(sinesrc),"location",filename,NULL); + return sinesrc; +} + +void gst_sinesrc_push(GstSrc *src) { + GstSineSrc *sinesrc; + GstBuffer *buf; + gint16 *samples; + gint i; + gint volume; + gdouble val; + + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_SINESRC(src)); + sinesrc = GST_SINESRC(src); + + buf = gst_buffer_new(); + g_return_if_fail(buf); + GST_BUFFER_DATA(buf) = (gpointer)malloc(4096); + samples = (gint16*)GST_BUFFER_DATA(buf); + GST_BUFFER_DATA(buf) = 4096; + + volume = 65535 * sinesrc->volume; + for (i=0;i<1024;i++) { + val = sin((gdouble)i/sinesrc->frequency); + samples[i] = val * volume; + samples[i+1] = samples[i]; + } + + if (!sinesrc->sentmeta) { + MetaAudioRaw *newmeta = g_new(MetaAudioRaw,1); + memcpy(newmeta,&sinesrc->meta,sizeof(MetaAudioRaw)); + gst_buffer_add_meta(buf,GST_META(newmeta)); + sinesrc->sentmeta = TRUE; + } + + gst_pad_push(sinesrc->srcpad,buf); + g_print(">"); +} + +static void gst_sinesrc_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstSineSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_SINESRC(object)); + src = GST_SINESRC(object); + + switch (id) { + case ARG_VOLUME: + src->volume = GTK_VALUE_DOUBLE(*arg); + break; + case ARG_FREQ: + src->freq = GTK_VALUE_INT(*arg); + break; + case ARG_FORMAT: + src->format = GTK_VALUE_INT(*arg); + break; + case ARG_CHANNELS: + src->channels = GTK_VALUE_INT(*arg); + break; + case ARG_FREQUENCY: + src->frequency = GTK_VALUE_INT(*arg); + break; + default: + break; + } +} + +static void gst_sinesrc_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstSineSrc *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_SINESRC(object)); + src = GST_SINESRC(object); + + switch (id) { + case ARG_VOLUME: + GTK_VALUE_DOUBLE(*arg) = src->volume; + break; + case ARG_FREQ: + GTK_VALUE_INT(*arg) = src->freq; + break; + case ARG_FORMAT: + GTK_VALUE_INT(*arg) = src->format; + break; + case ARG_CHANNELS: + GTK_VALUE_INT(*arg) = src->channels; + break; + case ARG_FREQUENCY: + GTK_VALUE_INT(*arg) = src->frequency; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +/* +static gboolean gst_sinesrc_change_state(GstElement *element, + GstElementState state) { + g_return_if_fail(GST_IS_SINESRC(element)); + + switch (state) { + case GST_STATE_RUNNING: + if (!gst_sinesrc_open_audio(GST_SINESRC(element))) + return FALSE; + break; + case ~GST_STATE_RUNNING: + gst_sinesrc_close_audio(GST_SINESRC(element)); + break; + default: + break; + } + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element,state); + return TRUE; +} +*/ + +void gst_sinesrc_sync_parms(GstSineSrc *sinesrc) { + sinesrc->meta.format = sinesrc->format; + sinesrc->meta.channels = sinesrc->channels; + sinesrc->meta.frequency = sinesrc->frequency; + sinesrc->sentmeta = FALSE; +} diff --git a/plugins/elements/gstsinesrc.h b/plugins/elements/gstsinesrc.h new file mode 100644 index 0000000000..9964ff553f --- /dev/null +++ b/plugins/elements/gstsinesrc.h @@ -0,0 +1,87 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_SINESRC_H__ +#define __GST_SINESRC_H__ + + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +GstElementDetails gst_sinesrc_details; + + +#define GST_TYPE_SINESRC \ + (gst_sinesrc_get_type()) +#define GST_SINESRC(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_SINESRC,GstSineSrc)) +#define GST_SINESRC_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_SINESRC,GstSineSrcClass)) +#define GST_IS_SINESRC(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_SINESRC)) +#define GST_IS_SINESRC_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_SINESRC))) + +typedef struct _GstSineSrc GstSineSrc; +typedef struct _GstSineSrcClass GstSineSrcClass; + +struct _GstSineSrc { + GstSrc src; + + /* pads */ + GstPad *srcpad; + + /* parameters */ + gdouble volume; + gint freq; + + /* audio parameters */ + gint format; + gint channels; + gint frequency; + + gulong seq; + + MetaAudioRaw meta; + gboolean sentmeta; +}; + +struct _GstSineSrcClass { + GstSrcClass parent_class; +}; + +GtkType gst_sinesrc_get_type(void); +GstElement *gst_sinesrc_new(gchar *name); + +void gst_sinesrc_push(GstSrc *src); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_SINESRC_H__ */ diff --git a/stamp.h.in b/stamp.h.in new file mode 100644 index 0000000000..9788f70238 --- /dev/null +++ b/stamp.h.in @@ -0,0 +1 @@ +timestamp