From 1762dfbf982a75d895676b0063379e33b4f9b96a Mon Sep 17 00:00:00 2001 From: Erik Walthinsen Date: Sun, 30 Jan 2000 09:03:00 +0000 Subject: [PATCH 1/1] initial checkin Original commit message from CVS: initial checkin --- AUTHORS | 1 + COPYING | 340 +++++++++++++++++++++++++ COPYING.LIB | 481 +++++++++++++++++++++++++++++++++++ ChangeLog | 0 INSTALL | 182 +++++++++++++ Makefile.am | 1 + NEWS | 0 README | 7 + acconfig.h | 11 + autogen.sh | 67 +++++ config.h.in | 29 +++ configure.in | 145 +++++++++++ gst/Makefile.am | 61 +++++ gst/cothreads.c | 143 +++++++++++ gst/cothreads.h | 48 ++++ gst/elements/Makefile.am | 35 +++ gst/elements/gstasyncdisksrc.c | 346 +++++++++++++++++++++++++ gst/elements/gstasyncdisksrc.h | 88 +++++++ gst/elements/gstaudiosink.c | 291 +++++++++++++++++++++ gst/elements/gstaudiosink.h | 85 +++++++ gst/elements/gstaudiosrc.c | 319 +++++++++++++++++++++++ gst/elements/gstaudiosrc.h | 90 +++++++ gst/elements/gstdisksrc.c | 267 +++++++++++++++++++ gst/elements/gstdisksrc.h | 83 ++++++ gst/elements/gstelements.c | 85 +++++++ gst/elements/gstesdsink.c | 0 gst/elements/gstesdsink.h | 81 ++++++ gst/elements/gstfakesink.c | 109 ++++++++ gst/elements/gstfakesink.h | 71 ++++++ gst/elements/gstfakesrc.c | 112 ++++++++ gst/elements/gstfakesrc.h | 70 +++++ gst/elements/gstfdsink.c | 155 ++++++++++++ gst/elements/gstfdsink.h | 74 ++++++ gst/elements/gstfdsrc.c | 206 +++++++++++++++ gst/elements/gstfdsrc.h | 77 ++++++ gst/elements/gsthttpsrc.c | 258 +++++++++++++++++++ gst/elements/gsthttpsrc.h | 77 ++++++ gst/elements/gstidentity.c | 152 +++++++++++ gst/elements/gstidentity.h | 74 ++++++ gst/elements/gstqueue.c | 216 ++++++++++++++++ gst/elements/gstqueue.h | 84 ++++++ gst/elements/gstsinesrc.c | 269 ++++++++++++++++++++ gst/elements/gstsinesrc.h | 87 +++++++ gst/gst.c | 60 +++++ gst/gst.h | 60 +++++ gst/gstbin.c | 449 ++++++++++++++++++++++++++++++++ gst/gstbin.h | 106 ++++++++ gst/gstbuffer.c | 241 ++++++++++++++++++ gst/gstbuffer.h | 128 ++++++++++ gst/gstconnection.c | 99 ++++++++ gst/gstconnection.h | 69 +++++ gst/gstelement.c | 507 +++++++++++++++++++++++++++++++++++++ gst/gstelement.h | 194 ++++++++++++++ gst/gstelementfactory.c | 138 ++++++++++ gst/gstfilter.c | 86 +++++++ gst/gstfilter.h | 63 +++++ gst/gstlog.h | 31 +++ gst/gstmeta.c | 57 +++++ gst/gstmeta.h | 85 +++++++ gst/gstobject.c | 223 ++++++++++++++++ gst/gstobject.h | 117 +++++++++ gst/gstpad.c | 340 +++++++++++++++++++++++++ gst/gstpad.h | 127 ++++++++++ gst/gstpipeline.c | 134 ++++++++++ gst/gstpipeline.h | 69 +++++ gst/gstplugin.c | 297 ++++++++++++++++++++++ gst/gstplugin.h | 63 +++++ gst/gstsink.c | 79 ++++++ gst/gstsink.h | 64 +++++ gst/gstsrc.c | 122 +++++++++ gst/gstsrc.h | 86 +++++++ gst/gsttee.c | 130 ++++++++++ gst/gsttee.h | 70 +++++ gst/gstthread.c | 332 ++++++++++++++++++++++++ gst/gstthread.h | 84 ++++++ gst/gsttrace.c | 103 ++++++++ gst/gsttrace.h | 69 +++++ gst/gsttype.c | 160 ++++++++++++ gst/gsttype.h | 76 ++++++ gst/gsttypefind.c | 79 ++++++ gst/gsttypefind.h | 68 +++++ gst/gstutils.c | 77 ++++++ gst/gstutils.h | 35 +++ gst/gstxml.c | 31 +++ gst/gstxml.h | 30 +++ gst/meta/Makefile.am | 3 + gst/meta/audioraw.h | 40 +++ gst/meta/spectrum.h | 38 +++ gst/plugin.c | 139 ++++++++++ gst/plugin.h | 4 + gst/types/Makefile.am | 10 + gst/types/gsttypes.c | 85 +++++++ install-sh | 251 ++++++++++++++++++ missing | 190 ++++++++++++++ mkinstalldirs | 40 +++ plugins/elements/Makefile.am | 35 +++ plugins/elements/gstasyncdisksrc.c | 346 +++++++++++++++++++++++++ plugins/elements/gstasyncdisksrc.h | 88 +++++++ plugins/elements/gstaudiosink.c | 291 +++++++++++++++++++++ plugins/elements/gstaudiosink.h | 85 +++++++ plugins/elements/gstaudiosrc.c | 319 +++++++++++++++++++++++ plugins/elements/gstaudiosrc.h | 90 +++++++ plugins/elements/gstdisksrc.c | 267 +++++++++++++++++++ plugins/elements/gstdisksrc.h | 83 ++++++ plugins/elements/gstelements.c | 85 +++++++ plugins/elements/gstesdsink.c | 0 plugins/elements/gstesdsink.h | 81 ++++++ plugins/elements/gstfakesink.c | 109 ++++++++ plugins/elements/gstfakesink.h | 71 ++++++ plugins/elements/gstfakesrc.c | 112 ++++++++ plugins/elements/gstfakesrc.h | 70 +++++ plugins/elements/gstfdsink.c | 155 ++++++++++++ plugins/elements/gstfdsink.h | 74 ++++++ plugins/elements/gstfdsrc.c | 206 +++++++++++++++ plugins/elements/gstfdsrc.h | 77 ++++++ plugins/elements/gsthttpsrc.c | 258 +++++++++++++++++++ plugins/elements/gsthttpsrc.h | 77 ++++++ plugins/elements/gstidentity.c | 152 +++++++++++ plugins/elements/gstidentity.h | 74 ++++++ plugins/elements/gstqueue.c | 216 ++++++++++++++++ plugins/elements/gstqueue.h | 84 ++++++ plugins/elements/gstsinesrc.c | 269 ++++++++++++++++++++ plugins/elements/gstsinesrc.h | 87 +++++++ stamp.h.in | 1 + 124 files changed, 15477 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 COPYING.LIB create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100644 acconfig.h create mode 100755 autogen.sh create mode 100644 config.h.in create mode 100644 configure.in create mode 100644 gst/Makefile.am create mode 100644 gst/cothreads.c create mode 100644 gst/cothreads.h create mode 100644 gst/elements/Makefile.am create mode 100644 gst/elements/gstasyncdisksrc.c create mode 100644 gst/elements/gstasyncdisksrc.h create mode 100644 gst/elements/gstaudiosink.c create mode 100644 gst/elements/gstaudiosink.h create mode 100644 gst/elements/gstaudiosrc.c create mode 100644 gst/elements/gstaudiosrc.h create mode 100644 gst/elements/gstdisksrc.c create mode 100644 gst/elements/gstdisksrc.h create mode 100644 gst/elements/gstelements.c create mode 100644 gst/elements/gstesdsink.c create mode 100644 gst/elements/gstesdsink.h create mode 100644 gst/elements/gstfakesink.c create mode 100644 gst/elements/gstfakesink.h create mode 100644 gst/elements/gstfakesrc.c create mode 100644 gst/elements/gstfakesrc.h create mode 100644 gst/elements/gstfdsink.c create mode 100644 gst/elements/gstfdsink.h create mode 100644 gst/elements/gstfdsrc.c create mode 100644 gst/elements/gstfdsrc.h create mode 100644 gst/elements/gsthttpsrc.c create mode 100644 gst/elements/gsthttpsrc.h create mode 100644 gst/elements/gstidentity.c create mode 100644 gst/elements/gstidentity.h create mode 100644 gst/elements/gstqueue.c create mode 100644 gst/elements/gstqueue.h create mode 100644 gst/elements/gstsinesrc.c create mode 100644 gst/elements/gstsinesrc.h create mode 100644 gst/gst.c create mode 100644 gst/gst.h create mode 100644 gst/gstbin.c create mode 100644 gst/gstbin.h create mode 100644 gst/gstbuffer.c create mode 100644 gst/gstbuffer.h create mode 100644 gst/gstconnection.c create mode 100644 gst/gstconnection.h create mode 100644 gst/gstelement.c create mode 100644 gst/gstelement.h create mode 100644 gst/gstelementfactory.c create mode 100644 gst/gstfilter.c create mode 100644 gst/gstfilter.h create mode 100644 gst/gstlog.h create mode 100644 gst/gstmeta.c create mode 100644 gst/gstmeta.h create mode 100644 gst/gstobject.c create mode 100644 gst/gstobject.h create mode 100644 gst/gstpad.c create mode 100644 gst/gstpad.h create mode 100644 gst/gstpipeline.c create mode 100644 gst/gstpipeline.h create mode 100644 gst/gstplugin.c create mode 100644 gst/gstplugin.h create mode 100644 gst/gstsink.c create mode 100644 gst/gstsink.h create mode 100644 gst/gstsrc.c create mode 100644 gst/gstsrc.h create mode 100644 gst/gsttee.c create mode 100644 gst/gsttee.h create mode 100644 gst/gstthread.c create mode 100644 gst/gstthread.h create mode 100644 gst/gsttrace.c create mode 100644 gst/gsttrace.h create mode 100644 gst/gsttype.c create mode 100644 gst/gsttype.h create mode 100644 gst/gsttypefind.c create mode 100644 gst/gsttypefind.h create mode 100644 gst/gstutils.c create mode 100644 gst/gstutils.h create mode 100644 gst/gstxml.c create mode 100644 gst/gstxml.h create mode 100644 gst/meta/Makefile.am create mode 100644 gst/meta/audioraw.h create mode 100644 gst/meta/spectrum.h create mode 100644 gst/plugin.c create mode 100644 gst/plugin.h create mode 100644 gst/types/Makefile.am create mode 100644 gst/types/gsttypes.c create mode 100755 install-sh create mode 100755 missing create mode 100755 mkinstalldirs create mode 100644 plugins/elements/Makefile.am create mode 100644 plugins/elements/gstasyncdisksrc.c create mode 100644 plugins/elements/gstasyncdisksrc.h create mode 100644 plugins/elements/gstaudiosink.c create mode 100644 plugins/elements/gstaudiosink.h create mode 100644 plugins/elements/gstaudiosrc.c create mode 100644 plugins/elements/gstaudiosrc.h create mode 100644 plugins/elements/gstdisksrc.c create mode 100644 plugins/elements/gstdisksrc.h create mode 100644 plugins/elements/gstelements.c create mode 100644 plugins/elements/gstesdsink.c create mode 100644 plugins/elements/gstesdsink.h create mode 100644 plugins/elements/gstfakesink.c create mode 100644 plugins/elements/gstfakesink.h create mode 100644 plugins/elements/gstfakesrc.c create mode 100644 plugins/elements/gstfakesrc.h create mode 100644 plugins/elements/gstfdsink.c create mode 100644 plugins/elements/gstfdsink.h create mode 100644 plugins/elements/gstfdsrc.c create mode 100644 plugins/elements/gstfdsrc.h create mode 100644 plugins/elements/gsthttpsrc.c create mode 100644 plugins/elements/gsthttpsrc.h create mode 100644 plugins/elements/gstidentity.c create mode 100644 plugins/elements/gstidentity.h create mode 100644 plugins/elements/gstqueue.c create mode 100644 plugins/elements/gstqueue.h create mode 100644 plugins/elements/gstsinesrc.c create mode 100644 plugins/elements/gstsinesrc.h create mode 100644 stamp.h.in diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..0172ce2 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Erik Walthinsen diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d60c31a --- /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 0000000..eb685a5 --- /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 0000000..e69de29 diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..b42a17a --- /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 0000000..21a11f8 --- /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 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..b66f5df --- /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 0000000..de7a6f8 --- /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 0000000..1e0e7be --- /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 0000000..cedb21b --- /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 0000000..215cc77 --- /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 0000000..7cf7b94 --- /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 0000000..8b12b67 --- /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 0000000..63fef42 --- /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 0000000..d035695 --- /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 0000000..8587fa5 --- /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 0000000..5c50d6e --- /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 0000000..56523cb --- /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 0000000..5159eb0 --- /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 0000000..2f06b4c --- /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 0000000..bcaedcf --- /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 0000000..9c0ff78 --- /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 0000000..bdf2f9e --- /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 0000000..a44418d --- /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 0000000..e69de29 diff --git a/gst/elements/gstesdsink.h b/gst/elements/gstesdsink.h new file mode 100644 index 0000000..97dce1e --- /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 0000000..661cd4c --- /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 0000000..e6617fc --- /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 0000000..6251f11 --- /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 0000000..946e0f1 --- /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 0000000..136f37c --- /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 0000000..8a7cba3 --- /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 0000000..f24c06e --- /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 0000000..1b85e06 --- /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 0000000..3b378ed --- /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 0000000..ae55f29 --- /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 0000000..4896f5d --- /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 0000000..f186a49 --- /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 0000000..2abf235 --- /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 0000000..5ce8d6f --- /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 0000000..ede6f38 --- /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 0000000..9964ff5 --- /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 0000000..3872136 --- /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 0000000..d2e9669 --- /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 0000000..0b7fe91 --- /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 0000000..7f534ef --- /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 0000000..4494f86 --- /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 0000000..bd412b4 --- /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 0000000..4c1c491 --- /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 0000000..a98ca1b --- /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 0000000..941973d --- /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 0000000..8490ce1 --- /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 0000000..c6f185f --- /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 0000000..fc8fcd4 --- /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 0000000..860cc4a --- /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 0000000..e9b353b --- /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 0000000..08208d5 --- /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 0000000..2ba8998 --- /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 0000000..7754cc3 --- /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 0000000..060e948 --- /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 0000000..8f21e1a --- /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 0000000..f2deeed --- /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 0000000..54d9f6f --- /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 0000000..589d02b --- /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 0000000..c7ca374 --- /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 0000000..164ca85 --- /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 0000000..26de07e --- /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 0000000..44c3f7a --- /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 0000000..472cd29 --- /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 0000000..75405ef --- /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 0000000..13ceaef --- /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 0000000..1953325 --- /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 0000000..001dd68 --- /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 0000000..fffd6f5 --- /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 0000000..cbb5dcb --- /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 0000000..0fdbabf --- /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 0000000..7c0bcf9 --- /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 0000000..fa96bf8 --- /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 0000000..473fa68 --- /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 0000000..34bd714 --- /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 0000000..d659fd5 --- /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 0000000..f196c5a --- /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 0000000..cfcd6dc --- /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 0000000..e253881 --- /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 0000000..adc27ce --- /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 0000000..7c8d52d --- /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 0000000..c8e1637 --- /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 0000000..996e3f8 --- /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 0000000..d98d65f --- /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 0000000..2dec260 --- /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 0000000..3d49f24 --- /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 0000000..e9de238 --- /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 0000000..7789652 --- /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 0000000..6b3b5fc --- /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 0000000..d035695 --- /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 0000000..8587fa5 --- /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 0000000..5c50d6e --- /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 0000000..56523cb --- /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 0000000..5159eb0 --- /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 0000000..2f06b4c --- /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 0000000..bcaedcf --- /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 0000000..9c0ff78 --- /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 0000000..bdf2f9e --- /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 0000000..a44418d --- /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 0000000..e69de29 diff --git a/plugins/elements/gstesdsink.h b/plugins/elements/gstesdsink.h new file mode 100644 index 0000000..97dce1e --- /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 0000000..661cd4c --- /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 0000000..e6617fc --- /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 0000000..6251f11 --- /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 0000000..946e0f1 --- /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 0000000..136f37c --- /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 0000000..8a7cba3 --- /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 0000000..f24c06e --- /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 0000000..1b85e06 --- /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 0000000..3b378ed --- /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 0000000..ae55f29 --- /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 0000000..4896f5d --- /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 0000000..f186a49 --- /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 0000000..2abf235 --- /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 0000000..5ce8d6f --- /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 0000000..ede6f38 --- /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 0000000..9964ff5 --- /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 0000000..9788f70 --- /dev/null +++ b/stamp.h.in @@ -0,0 +1 @@ +timestamp -- 2.7.4