From 47437ec8341bc1ed37e18ebe077d987d0fe45336 Mon Sep 17 00:00:00 2001 From: Jaromil Date: Fri, 27 Jun 2008 15:39:47 +0200 Subject: [PATCH] cleanup in trunk --- branches/lydia/AUTHORS | 17 - branches/lydia/COPYING | 280 ---- branches/lydia/Makefile | 50 - branches/lydia/README | 106 -- branches/lydia/cmdline.cpp | 561 -------- branches/lydia/daemon.h | 33 - branches/lydia/decoder.cpp | 701 ---------- branches/lydia/decoder.h | 133 -- branches/lydia/gui.cpp | 610 --------- branches/lydia/gui.h | 96 -- branches/lydia/ivysync-gui.glade | 604 --------- branches/lydia/ivysync-remote.py | 145 --- branches/lydia/ivysync-xmlrpc-spec.odt | Bin 9945 -> 0 bytes branches/lydia/linklist.cpp | 450 ------- branches/lydia/linklist.h | 110 -- branches/lydia/parport.cpp | 103 -- branches/lydia/parport.h | 55 - branches/lydia/pipe.cpp | 386 ------ branches/lydia/pipe.h | 258 ---- branches/lydia/portaudio/LICENSE | 65 - branches/lydia/portaudio/Makefile | 33 - branches/lydia/portaudio/README | 81 -- branches/lydia/portaudio/libportaudio.a | Bin 30716 -> 0 bytes branches/lydia/portaudio/pa_convert.c | 470 ------- branches/lydia/portaudio/pa_host.h | 189 --- branches/lydia/portaudio/pa_lib.c | 806 ------------ branches/lydia/portaudio/pa_trace.c | 83 -- branches/lydia/portaudio/pa_trace.h | 67 - branches/lydia/portaudio/pa_unix.c | 1128 ----------------- branches/lydia/portaudio/pa_unix.h | 141 --- branches/lydia/portaudio/pa_unix_oss.c | 397 ------ branches/lydia/portaudio/portaudio.h | 463 ------- branches/lydia/sndfile_decoder.cpp | 126 -- branches/lydia/sndfile_decoder.h | 60 - branches/lydia/sound_decoder.cpp | 59 - branches/lydia/sound_decoder.h | 174 --- branches/lydia/sound_device.cpp | 297 ----- branches/lydia/sound_device.h | 70 - branches/lydia/thread.cpp | 46 - branches/lydia/thread.h | 47 - branches/lydia/utils.cpp | 168 --- branches/lydia/utils.h | 44 - branches/lydia/xmlrpc++/Doxyfile | 1041 --------------- branches/lydia/xmlrpc++/Makefile | 34 - branches/lydia/xmlrpc++/README | 102 -- branches/lydia/xmlrpc++/XmlRpc.h | 97 -- branches/lydia/xmlrpc++/XmlRpcClient.cpp | 547 -------- branches/lydia/xmlrpc++/XmlRpcClient.h | 148 --- branches/lydia/xmlrpc++/XmlRpcDispatch.cpp | 268 ---- branches/lydia/xmlrpc++/XmlRpcDispatch.h | 93 -- branches/lydia/xmlrpc++/XmlRpcException.h | 42 - branches/lydia/xmlrpc++/XmlRpcMutex.cpp | 60 - branches/lydia/xmlrpc++/XmlRpcMutex.h | 46 - branches/lydia/xmlrpc++/XmlRpcServer.cpp | 494 -------- branches/lydia/xmlrpc++/XmlRpcServer.h | 160 --- .../lydia/xmlrpc++/XmlRpcServerConnection.cpp | 205 --- .../lydia/xmlrpc++/XmlRpcServerConnection.h | 82 -- .../lydia/xmlrpc++/XmlRpcServerMethod.cpp | 21 - branches/lydia/xmlrpc++/XmlRpcServerMethod.h | 47 - branches/lydia/xmlrpc++/XmlRpcSocket.cpp | 285 ----- branches/lydia/xmlrpc++/XmlRpcSocket.h | 76 -- branches/lydia/xmlrpc++/XmlRpcSource.cpp | 40 - branches/lydia/xmlrpc++/XmlRpcSource.h | 67 - branches/lydia/xmlrpc++/XmlRpcThread.cpp | 74 -- branches/lydia/xmlrpc++/XmlRpcThread.h | 60 - .../lydia/xmlrpc++/XmlRpcThreadedServer.cpp | 27 - .../lydia/xmlrpc++/XmlRpcThreadedServer.h | 67 - branches/lydia/xmlrpc++/XmlRpcUtil.cpp | 259 ---- branches/lydia/xmlrpc++/XmlRpcUtil.h | 61 - branches/lydia/xmlrpc++/XmlRpcValue.cpp | 611 --------- branches/lydia/xmlrpc++/XmlRpcValue.h | 259 ---- branches/lydia/xmlrpc++/base64.h | 379 ------ branches/lydia/xmlrpc.cpp | 373 ------ branches/lydia/xmlrpc.h | 245 ---- 74 files changed, 16082 deletions(-) delete mode 100644 branches/lydia/AUTHORS delete mode 100644 branches/lydia/COPYING delete mode 100644 branches/lydia/Makefile delete mode 100644 branches/lydia/README delete mode 100644 branches/lydia/cmdline.cpp delete mode 100644 branches/lydia/daemon.h delete mode 100644 branches/lydia/decoder.cpp delete mode 100644 branches/lydia/decoder.h delete mode 100644 branches/lydia/gui.cpp delete mode 100644 branches/lydia/gui.h delete mode 100644 branches/lydia/ivysync-gui.glade delete mode 100755 branches/lydia/ivysync-remote.py delete mode 100644 branches/lydia/ivysync-xmlrpc-spec.odt delete mode 100644 branches/lydia/linklist.cpp delete mode 100644 branches/lydia/linklist.h delete mode 100644 branches/lydia/parport.cpp delete mode 100644 branches/lydia/parport.h delete mode 100644 branches/lydia/pipe.cpp delete mode 100644 branches/lydia/pipe.h delete mode 100644 branches/lydia/portaudio/LICENSE delete mode 100644 branches/lydia/portaudio/Makefile delete mode 100644 branches/lydia/portaudio/README delete mode 100644 branches/lydia/portaudio/libportaudio.a delete mode 100644 branches/lydia/portaudio/pa_convert.c delete mode 100644 branches/lydia/portaudio/pa_host.h delete mode 100644 branches/lydia/portaudio/pa_lib.c delete mode 100644 branches/lydia/portaudio/pa_trace.c delete mode 100644 branches/lydia/portaudio/pa_trace.h delete mode 100644 branches/lydia/portaudio/pa_unix.c delete mode 100644 branches/lydia/portaudio/pa_unix.h delete mode 100644 branches/lydia/portaudio/pa_unix_oss.c delete mode 100644 branches/lydia/portaudio/portaudio.h delete mode 100644 branches/lydia/sndfile_decoder.cpp delete mode 100644 branches/lydia/sndfile_decoder.h delete mode 100644 branches/lydia/sound_decoder.cpp delete mode 100644 branches/lydia/sound_decoder.h delete mode 100644 branches/lydia/sound_device.cpp delete mode 100644 branches/lydia/sound_device.h delete mode 100644 branches/lydia/thread.cpp delete mode 100644 branches/lydia/thread.h delete mode 100644 branches/lydia/utils.cpp delete mode 100644 branches/lydia/utils.h delete mode 100644 branches/lydia/xmlrpc++/Doxyfile delete mode 100644 branches/lydia/xmlrpc++/Makefile delete mode 100644 branches/lydia/xmlrpc++/README delete mode 100644 branches/lydia/xmlrpc++/XmlRpc.h delete mode 100644 branches/lydia/xmlrpc++/XmlRpcClient.cpp delete mode 100644 branches/lydia/xmlrpc++/XmlRpcClient.h delete mode 100644 branches/lydia/xmlrpc++/XmlRpcDispatch.cpp delete mode 100644 branches/lydia/xmlrpc++/XmlRpcDispatch.h delete mode 100644 branches/lydia/xmlrpc++/XmlRpcException.h delete mode 100644 branches/lydia/xmlrpc++/XmlRpcMutex.cpp delete mode 100644 branches/lydia/xmlrpc++/XmlRpcMutex.h delete mode 100644 branches/lydia/xmlrpc++/XmlRpcServer.cpp delete mode 100644 branches/lydia/xmlrpc++/XmlRpcServer.h delete mode 100644 branches/lydia/xmlrpc++/XmlRpcServerConnection.cpp delete mode 100644 branches/lydia/xmlrpc++/XmlRpcServerConnection.h delete mode 100644 branches/lydia/xmlrpc++/XmlRpcServerMethod.cpp delete mode 100644 branches/lydia/xmlrpc++/XmlRpcServerMethod.h delete mode 100644 branches/lydia/xmlrpc++/XmlRpcSocket.cpp delete mode 100644 branches/lydia/xmlrpc++/XmlRpcSocket.h delete mode 100644 branches/lydia/xmlrpc++/XmlRpcSource.cpp delete mode 100644 branches/lydia/xmlrpc++/XmlRpcSource.h delete mode 100644 branches/lydia/xmlrpc++/XmlRpcThread.cpp delete mode 100644 branches/lydia/xmlrpc++/XmlRpcThread.h delete mode 100644 branches/lydia/xmlrpc++/XmlRpcThreadedServer.cpp delete mode 100644 branches/lydia/xmlrpc++/XmlRpcThreadedServer.h delete mode 100644 branches/lydia/xmlrpc++/XmlRpcUtil.cpp delete mode 100644 branches/lydia/xmlrpc++/XmlRpcUtil.h delete mode 100644 branches/lydia/xmlrpc++/XmlRpcValue.cpp delete mode 100644 branches/lydia/xmlrpc++/XmlRpcValue.h delete mode 100644 branches/lydia/xmlrpc++/base64.h delete mode 100644 branches/lydia/xmlrpc.cpp delete mode 100644 branches/lydia/xmlrpc.h diff --git a/branches/lydia/AUTHORS b/branches/lydia/AUTHORS deleted file mode 100644 index 89d2289..0000000 --- a/branches/lydia/AUTHORS +++ /dev/null @@ -1,17 +0,0 @@ - -Author: - - Denis "Jaromil" Rojo - coder and mantainer - -Contributors: - - Ramon Coelho - experienced review of sync quality - Robert De Geuss - user friendly documentation - Wiel Seuskens - testing, debugging, web based XMLRPC client - -Artists: - - IvySync has been employed by Montevideo / Time Based Arts to produce and - exhibit video-art installations by, among the others: - Linda Wallace, Calin Dan, Erwin Olaf, Sami Kallinen - diff --git a/branches/lydia/COPYING b/branches/lydia/COPYING deleted file mode 100644 index 5a965fb..0000000 --- a/branches/lydia/COPYING +++ /dev/null @@ -1,280 +0,0 @@ - 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 diff --git a/branches/lydia/Makefile b/branches/lydia/Makefile deleted file mode 100644 index 9062abb..0000000 --- a/branches/lydia/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# We don't need kludgy automatizations here, -# let's use a simple Makefile. -# Just tweak the values below to fix your paths -# -# $Id: Makefile 60 2004-11-12 15:40:18Z jaromil $ - - -CPP = g++ -LINKER = ld - -GTKFLAGS = `pkg-config --cflags gtk+-2.0` -GTKLIBS = `pkg-config --libs gtk+-2.0` -SNDLIBS = `pkg-config --libs sndfile` - - -# debugging flags: -CPPFLAGS = -I. -Ixmlrpc++ -Iportaudio -Wall -g -ggdb $(GTKFLAGS) $(AOFLAGS) -# optimized flags: -#CPPFLAGS = -I. -Ixmlrpc++ -Wall -O2 -fomit-frame-pointer -ffast-math $(GTKFLAGS) - - - - -LIBS = xmlrpc++/libxmlrpc++.a portaudio/libportaudio.a -lpthread -lssl - -IVYSYNC_OBJ = decoder.o thread.o linklist.o utils.o cmdline.o gui.o \ - pipe.o xmlrpc.o sound_device.o sndfile_decoder.o sound_decoder.o parport.o - -all: xmlrpc ivysync - -xmlrpc: - cd xmlrpc++ && $(MAKE) - -ivysync: $(IVYSYNC_OBJ) - $(CPP) $(CPPFLAGS) -o ivysync $(IVYSYNC_OBJ) $(LIBS) $(GTKLIBS) $(SNDLIBS) - -#make clean -clean: - rm -rf *.o *~ ivysync - -install: ivysync - install ivysync /usr/local/bin - -# generic make rules -#%: %.c -# $(CC) $(CFLAGS) -o $@ $< $(LIBS) -#%.o: %.c -# $(CC) $(CFLAGS) -c -o $@ $< - - diff --git a/branches/lydia/README b/branches/lydia/README deleted file mode 100644 index ddbcf02..0000000 --- a/branches/lydia/README +++ /dev/null @@ -1,106 +0,0 @@ - ,-_/ .---. - ' | . , . . \___ . . ,-. ,-. - .^ | | / | | \ | | | | | - `--' `' `-| `---' `-| ' ' `-' [ver 0.4 Jardin Secret] - /| /| - `-' `-' by Denis "jaromil" Rojo - Montevideo Artlab R&D - - -Interactive customization - branched from mainstream ivysync - commissioned by Lydia Schouten - -IvySync provides synced playback of multiple videos on multiple screens - -In the video art field there are many artworks requiring the synced and -parallel playback of audio/video materials: IvySync provides such -functionality for IvyTV supported hardware decoders, with accurate -frame precision. - -IvySync reaches to sync up to 4 video channels with frame precision and -comes together with a user friendly graphical interface (GTK2) to edit -the playlists. - -It is possible to remotely control the playlist and playback of each -video sending commands across the network (XMLRPC). -Support for time based scheduling of different playlists is also -implemented (but still lacking a graphical interface) to let a running -syncstarter cycle various screening programs at different hours, days -or months. - - -IvySync is a dyne.org free software production (GNU GPL) -commissioned by Montevideo / Time Based Arts -used to exhibit video-art installations by, among the others: -Linda Wallace, Calin Dan, Erwin Olaf, Sami Kallinen - - -== DOCUMENTATION - -For more documentation, screenshots and download, go to the website: - ______ http://montevideo.dyne.org/trac.cgi/wiki/IvySync - - - - -== FEATURES - - **** interactive (parallel port interfacing) - - * full quality s/video or composite multiple output - - * professional grade low cost solution - - * remotely controllable playback (XMLRPC) - - * graphical interface for playlist scheduling - - * extensible, scriptable and reliable *NIX technology - - * frame accurate sync of DVD quality audio/video (MPEG2) - - * streaming playback from a local network (with Samba) - - * capable of syncing up to 4 videos - - * time based scheduling of multiple playlists - - -== REQUIREMENTS - - * GNU/Linux supported platform with ~500Mhz CPU - - * IvyTV compatible hardware decoder - - * ppdev parport parport_pc kernel modules - - *** RENT or BUY a syncstarter pre-configured for your needs *** - *** warranty and delivery services available, please contact: *** - - Denis "Jaromil" Rojo Netherlands Media Art Institute - software inventor R&D Montevideo / Time Based Arts - GNU/Linux developer Dyne.org Foundation - ------------------------------------------------------------ - Tel: +31 20 6237101 121 ___ Tue and Fri, 10:30 - 17:30 CET - Fax: +31 20 6244423 Irc: irc.freenode.net /msg jaromil - Post: NMAI/Artlab Keizersgracht 264 1016 EV Amsterdam - - - -== DISCLAIMER - - IvySync is Copyright (C) 2004-2006 by Denis Roio - -# This source code is free software; you can redistribute it and/or -# modify it under the terms of the GNU Public License as published -# by the Free Software Foundation; either version 2 of the License, -# or (at your option) any later version. -# -# This source code is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# Please refer to the GNU Public License for more details. -# -# You should have received a copy of the GNU Public License along with -# this source code; if not, write to: -# Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. diff --git a/branches/lydia/cmdline.cpp b/branches/lydia/cmdline.cpp deleted file mode 100644 index c155cb1..0000000 --- a/branches/lydia/cmdline.cpp +++ /dev/null @@ -1,561 +0,0 @@ - -/* IvySync - Video SyncStarter - * - * (c) Copyright 2004-2006 Denis Rojo aka jaromil - * Nederlands Instituut voor Mediakunst - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * to compile this sourcecode: gcc -o ivysync ivysync.c -lpthreads - * it should work on any POSIX system, including embedded hardware - * wherever the IvyTV drivers can also run (see http://ivtv.sf.net) - * - */ - -#include -#include -#include -#include -#include -#include -#include - - - -#include - -#include - -#include -#include -#include -#include - -#include - - -bool useaudio = true; -bool syncstart = false; -bool graphical = false; -bool dummytest = false; -bool rpcdaemon = false; -int rpcdaemonport = 2640; -int videobuf = 64; - -// our global linklist holding all instantiated decoders -Linklist decoders; - -// graphical interface -Gui *gui = NULL; - -// xmlrpc interface -XmlRpcServer *xmlrpc = NULL; - -// sound device -SoundDevice *snddev = NULL; - -// sound file -MuseDecSndFile *sndfile = NULL; - -// Threaded daemon -IvySyncDaemon *ivydaemon = NULL; - -// Parallel port controller -ParPort *parport = NULL; - - -// hardcoded movie offset positions -class Offset { -public: - Offset(int f, int b, int e) { - fogstart = f; - black = b; - enddrama = e; - } - ~Offset() { }; - int fogstart; - int black; - int enddrama; -}; -Offset *minidrama[5]; - - -char *help = -"Usage: ivysync [-hsDgt] [ -d /dev/video16 [ -p playmode files ] ]\n" -" -h --help show this help\n" -" -t --test dummy testrun: don't open devices\n" -" -D --debug print verbose debugging messages\n" -" -s --scan scan for available devices\n" -" -d --device activate a device (i.e. /dev/video16)\n" -" -b --buffer size of video buffer in KB (default 64)\n" -" -p --playmode playlist mode (play|cont|loop|rand)\n" -" -x --xmlrpc run XmlRpc daemon on a network port\n" -" -g --gui start the graphical user interface\n" -" -a --noaudio don't open the sound device\n"; - -char *short_options = "-hd:sb:x:p:gtD:a"; -const struct option long_options[] = { -{ "help", no_argument, NULL, 'h'}, -{ "device", required_argument, NULL, 'd'}, -{ "scan", no_argument, NULL, 's'}, -{ "buffer", required_argument, NULL, 'b'}, -{ "xmlrpc", required_argument, NULL, 'x'}, -{ "playmode", required_argument, NULL, 'p'}, -{ "gui", no_argument, NULL, 'g'}, -{ "test", no_argument, NULL, 't'}, -{ "debug", required_argument, NULL, 'D'}, -{ "noaudio", required_argument, NULL, 'a'}, -{0, 0, 0, 0} -}; - - -void quitproc (int Sig) { /* signal handling */ - N("received signal %u on process %u",Sig,getpid()); - A("please wait while quitting threads"); - - if(graphical) gtk_main_quit(); - - Decoder *dec; - dec = (Decoder*)decoders.begin(); - while(dec) { - dec->close(); - delete dec; - dec = (Decoder*)decoders.begin(); - } - -} - -#define CHECK_DECODER \ -if(!dec) { \ - dec = (Decoder*)decoders[1]; \ - if(!dec) { \ - dec = new Decoder(); \ - if( dec->init("/dev/video16") ) { \ - decoders.append( dec ); \ - } else { \ - delete dec; \ - dec = NULL; \ - } \ - } \ -} - -int cmdline(int argc, char **argv) { - Decoder *dec = NULL; - FILE *fd = NULL; - int c; - int res; - - N("IvySync 0.3 / (c)2004-2006 Denis Rojo "); - - do { - res = getopt_long(argc, argv, short_options, long_options, NULL); - - switch(res) { - - case 'h': - fprintf(stderr,"%s",help); - exit(1); - break; - - case 'd': - dec = new Decoder(); - dec->dummy = dummytest; - if( dec->init(optarg) ) - decoders.append( dec ); - else { - E("can't initialize device %s",optarg); - delete dec; - dec = NULL; - } - break; - - case 's': - N("Scanning for available playback devices..."); - dec = new Decoder(); - c=0; - - if( dec->init("/dev/video16") ) { - A("1. /dev/video16 is present"); - c++; - } - dec->close(); - - - if( dec->init("/dev/video17") ) { - A("2. /dev/video17 is present"); - c++; - } - dec->close(); - - - if( dec->init("/dev/video18") ) { - A("3. /dev/video18 is present"); - c++; - } - dec->close(); - - - if( dec->init("/dev/video19") ) { - A("4. /dev/video19"); - c++; - } - dec->close(); - - delete dec; - N("Total of %u device(s) found",c); - exit(1); - break; - - case 'p': - CHECK_DECODER; - if( strncasecmp(optarg,"play",4) ==0 ) { - - dec->playmode = PLAY; - - } else if( strncasecmp(optarg,"cont",4) ==0 ) { - - dec->playmode = CONT; - - } else if( strncasecmp(optarg,"loop",4) ==0 ) { - - dec->playmode = LOOP; - - } else if( strncasecmp(optarg,"rand",4) ==0 ) { - - dec->playmode = RAND; - - } else if( strncasecmp(optarg,"single",6) ==0 ) { - - dec->playmode = SINGLE; - - } else - E("unrecognized playmode: %s",optarg); - - break; - - case 'x': - rpcdaemon = true; - rpcdaemonport = atoi(optarg); - break; - - case 'a': - useaudio = false; - break; - - case 'g': - graphical = true; - break; - - case 't': - dummytest = true; - break; - - case 'D': - set_debug( atoi(optarg) ); - break; - - case 'b': - videobuf = atoi(optarg); - break; - - case 1: - fd = fopen(optarg,"rb"); - if(!fd) { - - E("file %s is not readable: %s",optarg, strerror(errno)); - - } else { - - CHECK_DECODER; - dec->append( optarg ); - fclose(fd); - } - - break; - - default: break; - - } - - } while(res > 0); - - return res; -} - - -int main(int argc, char **argv) { - Decoder *dec; - - set_debug(1); - - /* register quit signal handlers */ - if (signal (SIGINT, quitproc) == SIG_ERR) { - fprintf(stderr,"Couldn't install SIGINT handler\n"); - exit (0); - } - if (signal (SIGQUIT, quitproc) == SIG_ERR) { - fprintf(stderr,"Couldn't install SIGQUIT handler\n"); - exit (0); - } - if (signal (SIGTERM, quitproc) == SIG_ERR) { - fprintf(stderr,"Couldn't install SIGTERM handler\n"); - exit (0); - } - - - cmdline(argc, argv); - - if( !decoders.len() ) { - E("no decoder device is initialized, aborting operations"); - exit(0); - } - - - - ///////////////////////////////// - // setup the graphical interface - if(graphical) - if(!getenv("DISPLAY")) { - graphical = false; - E("can't use graphical interface: no display found"); - } - - if(graphical) { - A("activating graphical user interface for playlist configuration"); - // gtk_set_locale(); - gtk_init(&argc,&argv); - // add_pixmap_directory(PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); - - gui = new Gui(); - gui->init(&decoders); - gui->start(); - - exit(1); - } - //////////////////////////////// - - - //////////////////////////////// - /// setup the XMLRPC interface - if(rpcdaemon) { - A("activating XMLRPC daemon listener for remote network control"); - - xmlrpc = new XmlRpcServer(); - - // instantiate all classes - new Play (xmlrpc, &decoders); - new Stop (xmlrpc, &decoders); - new Pause (xmlrpc, &decoders); - new GetPos(xmlrpc, &decoders); - new SetPos(xmlrpc, &decoders); - new GetOffset(xmlrpc, &decoders); - new SetOffset(xmlrpc, &decoders); - new Open (xmlrpc, &decoders); - new Quit (xmlrpc, &decoders); - new SyncStart (xmlrpc, &decoders); - new SyncOffset(xmlrpc, &decoders); - - ivydaemon = new IvySyncDaemon(xmlrpc); - - if( ! ivydaemon->init( rpcdaemonport) ) { - E("can't initialize daemon listening"); - delete ivydaemon; - delete xmlrpc; - rpcdaemon = false; - } else - A("XMLRPC daemon listening for commands on port %u", - rpcdaemonport); - } - - //////////////////////////////// - - //////////////////////////////// - /// Sound device - if(useaudio) { - snddev = new SoundDevice(); - // open only for playback - snddev->open(false, true); - sndfile = new MuseDecSndFile(); - sndfile->load("/mnt/hd1/1/Lydia/pleistersound_def.wav"); - sndfile->play_once(snddev); - } - //////////////////////////////// - - ///////////////////////////////// - // Parallel port - parport = new ParPort(); - parport->init(); - // flash light at startup - parport->light(true); - jsleep(1,0); - parport->light(false); - parport->launch(); - - ///////////////////////////////// - // video files minidrama offsets - minidrama[0] = new Offset(1750, 1950, 3200); - minidrama[1] = new Offset(4680, 4880, 5560); - minidrama[2] = new Offset(6955, 7140, 7900); - minidrama[3] = new Offset(9460, 9610, 9990); - minidrama[4] = new Offset(10380, 10520, 11170); - - - //////////////////////////////// - /// Syncstart! - - N("Proceeding to syncstart"); - dec = (Decoder*)decoders.begin(); - while(dec) { - - dec->setup( &syncstart, videobuf ); - - dec->launch(); - - if( ! rpcdaemon ) { - // try to load the playlist - dec->load(); - dec->play(); - } - - dec = (Decoder*)dec->next; - } - - if( ! rpcdaemon ) { - A("Syncing %i players...",decoders.len()); - - jsleep(0,500); - A("Start!"); - } - - syncstart = 1; - - ////////////////////////////////////// - // live interactive part while playing - int c, off; - bool trigger; - int interval = 100; - static bool syncer; - - for( c=0; c<5; c++) { // cycle thru 5 minidramas - trigger = false; - dec = (Decoder*)decoders.begin(); - - do { - jsleep(0, interval); - off = dec->getoffset(); - } while(off < minidrama[c]->fogstart); - - A("fogstart of minidrama %u",c); - - // fog start: reset button and play sound - parport->button_reset(); - parport->light(true); - if(useaudio) sndfile->replay = true; - - do { - - jsleep(0, interval); - - if( parport->button_is_pressed() ) { - - parport->light(false); - - D("seek to offset %u", minidrama[c]->black); - /// global seek of all channels - dec = (Decoder*) decoders.begin(); - syncer = false; - while(dec) { - - dec->stop(); - dec->setup(&syncer, 0); - dec->setoffset( minidrama[c]->black ); - dec->play(); - dec = (Decoder*) dec->next; - - } - - jsleep(0, interval); - syncer = true; - break; - - } - - off = dec->getoffset(); - - } while(off < minidrama[c]->black); - - parport->light(false); - - // fog end: check button and skip if not pressed - if(! parport->button_is_pressed() ) { - A("no button pressed: skipping minidrama %u", c); - D("seek to offset %u", minidrama[c]->enddrama); - /// global seek of all channels - dec = (Decoder*) decoders.begin(); - syncer = false; - while(dec) { - dec->stop(); - dec->setup(&syncer, 0); - dec->setoffset( minidrama[c]->enddrama ); - dec->play(); - dec = (Decoder*) dec->next; - } - jsleep(0, interval); - syncer = true; - - } else { - A("button was pressed: showing minidrama %u",c); - } - - parport->button_reset(); - - } - - ////////////////////////////////////// - - if(rpcdaemon) { - - // run as a daemon: quit only when requested - while( ! ivydaemon->quit ) { - ivydaemon->run(1.0); - jsleep(0,10); - } - - } else { - - // run until all the channels are at the end - int still_running = decoders.len(); - - while(still_running) { - - still_running = 0; - dec = (Decoder*)decoders.begin(); - - while(dec) { - - if(dec->playing) still_running++; - - jsleep(1,0); // 1 second delay check - - dec = (Decoder*)dec->next; - } - } - } - - N("quit!"); - - - exit(1); -} diff --git a/branches/lydia/daemon.h b/branches/lydia/daemon.h deleted file mode 100644 index c49e9ef..0000000 --- a/branches/lydia/daemon.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __DAEMON_H__ -#define __DAEMON_H__ - -#include -#include -#include - -class Daemon { - public: - Daemon(); - ~Daemon(); - - bool init(vector *devices); - void launch(); - void quit(); - - - /// fakiir external api - int get_num_decoders(); - - int play(int dec, char *path); - int stop(); - - float get_position(int dec); - int set_position(float pos); - /// - - - private: - vector *decoders; -}; - -#endif diff --git a/branches/lydia/decoder.cpp b/branches/lydia/decoder.cpp deleted file mode 100644 index 570038d..0000000 --- a/branches/lydia/decoder.cpp +++ /dev/null @@ -1,701 +0,0 @@ -/* IvySync - Video SyncStarter - * - * (c) Copyright 2004 - 2006 Denis Rojo - * Nederlands Instituut voor Mediakunst - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - - -Decoder::Decoder() - : Thread(), Entry() { - fd = 0; - playmode = SINGLE; - position = -1; - playing = false; - stopped = false; - dummy = false; - gui = false; - quit = true; - - filesize = 0L; - filepos = 0L; - newfilepos = 0L; - - playlist_fd = 0; - - buffo = NULL; -} - -Decoder::~Decoder() { - close(); - free(buffo); - quit = true; -} - -bool Decoder::init(char *dev) { - int len; - - if(dummy) { - - N("running in dummy test run - no device opened"); - - } else { - - fd = ::open(dev, O_WRONLY|O_NDELAY,S_IWUSR|S_IWGRP|S_IWOTH); - if(fd<0) { - D("error opening device %s: %s",dev,strerror(errno)); - return false; - } - - } - - // save the path to the device - strncpy(device, dev, MAXPATH); - - // parse the last 2 cyphers of the device path - len = strlen(dev); - // last two chars of the device name are the number - device_num = atoi(&dev[len-2]); - - - return true; -} - -bool Decoder::setup(bool *sync, int bufsize) { - - quit = false; - - // save the syncstarter flag - syncstart = sync; - - // if no buffer size is specified, use old one - if(!bufsize) return(true); - - if(buffo) free(buffo); - - buffo = (uint8_t*) calloc( bufsize+1, 1024); // +1 safety bound - if(!buffo) { - E("fatal error: can't allocate %uKB of memory for decoder", bufsize); - return(false); - } - - buffo_size = bufsize*1024; - - - - return(true); - -} - -void Decoder::close() { - playing = false; - quit = true; - - if(running) { - D("thread was running, waiting to join..."); - join(); - } - if(fd) ::close(fd); - - position = -1; - - // delete playlist entries - empty(); - - -} - -void Decoder::update() { - if(position<0) { // first time we play from the playlist - - position = 1; - - } else { - - switch(playmode) { - - case PLAY: // next - - position++; - - if( position > playlist.len() ) { - // stop(); - position = 1; - } - - break; - - case CONT: // next or first if at the end - - if( position >= (int)playlist.len() ) position = 1; - else position++; - - break; - - case LOOP: - // play the same again - break; - - case RAND: - // play a random one - break; - - case SINGLE: - stop(); - break; - - default: - stop(); - // just stop - break; - } - - } - - // current movie is now in playlist[position]; - if( ! playlist.len() ) D("playlist empty"); - else { - D("current playlist at position %u:", position); - int c; - for(c=1; c<=playlist.len(); c++) { - D("%s[%u] %s", - (c==position)?"->":" ", - c, playlist[c]->name); - } - } - - // refresh the GUI if present - if(gui) gui->refresh(); - -} - - - -void Decoder::run() { - int in, written, writing; - uint8_t *buf; - Entry *movie; - - - if(!fd && !dummy) { - E("thread %u falling down: no device opened",pthread_self()); - return; - } - - running = true; - - D("thread %u launched",pthread_self()); - -// set max realtime priority -// if( set_rtpriority(true) ) -// A("thread %u running on max realtime priority",pthread_self()); - - while(!quit) { - - update(); - - if(quit) break; - - if(stopped) { - stopped = false; - playing = false; - } - - // if is not playing, sleep - while(!playing && !quit) jsleep(0,100); - /////////////////////////// - - // check it out from the playlist - movie = playlist[position]; - if(!movie) { - E("no movie at position %i", position); - playing = false; - continue; - } - - // just to be sure - if(playlist_fd) fclose(playlist_fd); - - // STAT METHOD FOR FILESIZE -// // check if it exists and ackowledge filesize -// if( stat(movie->name, &moviestat) < 0 ) { -// E("error %u on movie %s: %s", errno, movie->name, strerror(errno)); -// if(errno == 75) // value too large for defined datatype -// // we just deactivate seek and position handling -// filesize = 0x0; -// else -// continue; -// } else -// filesize = moviestat.st_size; - - playlist_fd = fopen64( movie->name, "rb" ); - if(!playlist_fd) { - E("can't open %s: %s (%i)", movie->name, strerror(errno), errno); - - if(errno==27) { // EOVERFLOW - file too large on Linux/Glibc - - int tmpfd; - tmpfd = open( movie->name, O_RDONLY|O_LARGEFILE); - - if(!tmpfd) { - E("failed opening with largefile support: %s",strerror(errno)); - continue; - } else playlist_fd = fdopen( tmpfd , "rb" ); - - } else { - continue; - } - } - - N("now playing %s",movie->name); - - // read the total length of movie file - fseeko64(playlist_fd, 0L, SEEK_END); - filesize = ftello64(playlist_fd); - // set position at the beginning - filepos = 0L; - fseeko64(playlist_fd, filepos, SEEK_SET); - ////////////////////////////////////// - - // ??? or should we use: - // fgetpos(playlist_fd, &filesize); - // fsetpos(playlist_fd, &filepos); - // none seem to work with files > 2GB - - if(filesize) - A("movie length: %lu KB",filesize/1024); - else - A("movie is too large to be seekable"); - - do { // inner reading loop - - // update the GUI - if(gui) gui->refresh(); - - // process asynchronous flags - if(quit || stopped) break; - while(!playing && !quit) jsleep(0,100); - ////////////////////////////// - - - // read in the data - in = fread(buffo, 1, buffo_size, playlist_fd); - if( feof(playlist_fd) || in<1 ) { // EOF - D("end of file %s",movie->name); - break; - } - - written = 0; - writing = in; - buf = buffo; - - if(!*syncstart) { - // unlock(); - while(!*syncstart) jsleep(0,1); // check every nanosecond - } - - while(writing) { // writing loop - - buf += written; - - // if(quit || stopped) break; - - if(dummy) // emulation mode with no device (for devel) - written = writing; - else - written = ::write(fd, buf, writing); - - if(written<0) // error on write - continue; - else - filepos += written; - - writing -= written; - - flush(); - - } - - } while(in>0 && !quit); // read/write inner loop - - clear(); - // close the file playing - A("end of movie %s", movie->name); - if(playlist_fd) { - fclose(playlist_fd); - playlist_fd = 0; - } - - } // run() thread loop - - clear(); - // close the file playing - if(playlist_fd) { - fclose(playlist_fd); - playlist_fd = 0; - } - A("quitting decoder for %s",device); - - D("thread %u finished", pthread_self()); - return; -} - -void Decoder::flush() { - struct pollfd fdled; - fdled.fd = fd; - fdled.events=POLLOUT; - - while( poll(&fdled,1,1000) < 1 ) { // wait infinite until ready - if(fdled.revents & POLLOUT) return; - else { - W("device %i still not ready for writing",fd); - if(quit) return; - } - } - - // if there is a seek to do, do it now - if((newfilepos > 0L) && playlist_fd) { - D("seeking to new position %lu", newfilepos); - fseeko64(playlist_fd, newfilepos, SEEK_SET); - filepos = newfilepos; - newfilepos = 0; - } -} - -bool Decoder::play() { - playing = true; - stopped = false; - return true; -} - -bool Decoder::stop() { - // newfilepos = 1; - // clear(); - // playing = false; - stopped = true; - return true; -} - -bool Decoder::pause() { - playing = false; - return true; -} - -bool Decoder::clear() { - if(!fd) return false; - - // close the device - flush(); - - ::close(fd); // *BLANK* - - - // reopen the device again - fd = ::open(device, O_WRONLY|O_NDELAY,S_IWUSR|S_IWGRP|S_IWOTH); - if(fd<0) { - D("error opening device %s: %s",device,strerror(errno)); - return false; - } - - return true; -} - - -int Decoder::getpos() { - // filesize : 100 = filepos : x - // filesize : filepos = 100 : x - int percent; - - if(!playlist_fd) return 0; - if(!filesize) return 0; - - percent = (int) ( (filepos * 100) / filesize ); - D("movie %s at position %u %% (%lu byte)", - playlist[position]->name, percent, filepos); - return percent; -} - -void Decoder::setpos(int pos) { - // filesize : 100 = x : pos - - if(!playlist_fd) return; - if(!filesize) return; - - newfilepos = (filesize * pos) / 100; - - D("Decoder::setpos(%u) : newfilepos = %lu", - pos, newfilepos); -} - -int Decoder::getoffset() { - return( (int)(filepos / 100000) ); -} - -void Decoder::setoffset(int pos) { - off64_t offset = pos * 100000; - (offset < filesize) ? newfilepos = offset : newfilepos = filesize; -} - -bool Decoder::prepend(char *file) { - - Entry *ent = new Entry(); - - ent->set_name(file); - - playlist.prepend( ent ); - - return true; -} - -bool Decoder::append(char *file) { - - Entry *ent = new Entry(); - - ent->set_name(file); - - playlist.append( ent ); - - return true; -} - -bool Decoder::insert(char *file, int pos) { - Entry *ent = new Entry(); - - ent->set_name(file); - - playlist.insert( ent, pos ); - - return true; -} - -/* -bool Decoder::remove(char *file) { - A("TODO: Decoder::remove(char *file)"); - return true; -} -*/ -bool Decoder::remove(int pos) { - Entry *ent; - - ent = playlist[pos]; - - if(!ent) return false; - - delete ent; - - return true; -} - -bool Decoder::empty() { - Entry *ent = playlist.begin(); - while(ent) { - ent->rem(); - delete ent; - ent = playlist.begin(); - } - // playlist.clear() - position = 1; - return true; -} - -static time_t now_epoch; -static struct tm now; - -int playlist_selector(const struct dirent *dir) { - char today_str[32]; - - strftime(today_str,31,"%d%b%y",&now); - - if( strstr(dir->d_name, today_str) ) - return 1; - - if( strstr(dir->d_name, "video") ) - return 1; - - return 0; -} - - - -int Decoder::load() { - // load the playlist from the .ivysync/ directory - // renders a date string of today in the format of DDMMMYY-HHMM (12Aug) - // if the playlist .ivysync/DDMMM*-videoNN is there load that one - // otherwise fallback on the .ivysync/videoNN playlist - // if that is not even there then we don't have a playlist. - FILE *fd; - char path[512]; - char line[1024]; - int c = 0; - struct stat st; - - struct tm pltime; - struct tm plseltime; - - struct dirent **filelist; - int found; - - char ThePlaylist[512]; - char videodev[64]; - char *home = getenv("HOME"); - - snprintf(path,511,"%s/.ivysync",home); - if( stat(path, &st) != 0) { - D("no saved playlists in %s: %s",path,strerror(errno)); - return -1; - } - - // when we are now - now_epoch = time(NULL); - localtime_r( &now_epoch, &now ); - snprintf(videodev,63,"video%u",device_num); - // use the default playlist - snprintf(ThePlaylist,511,"video%u",device_num); - - // scan the directory for scheduled playlists starting with date - found = scandir(path, &filelist, playlist_selector, alphasort); - if(found < 0) { - E("playlist scandir: %s",strerror(errno)); - return -1; - } - - // setup time selection of the latest playlist of today - memcpy(&plseltime, &now, sizeof(struct tm)); - plseltime.tm_hour = 0; - plseltime.tm_min = 0; - - // in filelist[] we have all playlists of today - // now need to sort out the ones that are not from this device - // and the ones that are in the future (hour and minutes) - while(found--) { - - D("checking playlist for today %s", filelist[found]->d_name); - // eliminate the ones that are not for this device - if( ! strstr( filelist[found]->d_name, videodev ) ) continue; - - // read and check the exact time on the filename - // in case the playlist filename doesn't starts with video* - if ( filelist[found]->d_name[0] == 'v') { - - snprintf(ThePlaylist,511,"%s",filelist[found]->d_name); - - } else { - - get_time( filelist[found]->d_name, &pltime ); - - // skip if we already have a more recent playlist - if(plseltime.tm_hour > pltime.tm_hour) continue; - else if(plseltime.tm_hour == pltime.tm_hour) - if(plseltime.tm_min >= pltime.tm_min) continue; - - if(now.tm_hour > pltime.tm_hour) { - - D("this playlist is actual, we're going to use this"); - snprintf(ThePlaylist,511,"%s",filelist[found]->d_name); - memcpy(&plseltime,&pltime,sizeof(struct tm)); - - } else if(now.tm_hour == pltime.tm_hour) { - - // same hour, let's check the minutes - if(now.tm_min >= pltime.tm_min) { - - D("this playlist is scheduled right now"); - snprintf(ThePlaylist,511,"%s",filelist[found]->d_name); - memcpy(&plseltime,&pltime,sizeof(struct tm)); - - } - } else D("this playlist will be activated later"); - } - } - - snprintf(path,511,"%s/.ivysync/%s",home,ThePlaylist); - - fd = fopen(path,"r"); - if(!fd) { - E("can't load playlist %s: %s", path, strerror(errno)); - return -1; - } - - A("reading from playlist file %s",path); - while( fgets(line,1023,fd) ) { - if( feof(fd) ) break; - - chomp(line); - if( append(line) ) { - c++; - D("%u+ %s",c,line); - } - } - fclose(fd); - return c; -} - -int Decoder::save() { - FILE *fd; - char *home = getenv("HOME"); - char path[512]; - int c; - struct stat st; - - vector::iterator pl_iter; - string pl; - - // create the configuration directory if doesn't exist - snprintf(path,511,"%s/.ivysync",home); - if( stat(path, &st) != 0) { - if(errno==ENOENT) mkdir(path,0744); - else { - E("error saving in %s: %s",path, strerror(errno)); - return -1; - } - } - - snprintf(path,511,"%s/.ivysync/video%u",home,device_num); - fd = fopen(path,"w+"); - if(!fd) { - E("can't save to %s: %s", path, strerror(errno)); - return -1; - } - - D("saving to configuration file %s",path); - Entry *ent; - ent = playlist.begin(); - c = 0; - while(ent) { - fputs(ent->name, fd); - fputs("\n",fd); - D("%u - %s", c, ent->name); - ent = ent->next; - c++; - } - fflush(fd); - fclose(fd); - return c; -} diff --git a/branches/lydia/decoder.h b/branches/lydia/decoder.h deleted file mode 100644 index b6b836e..0000000 --- a/branches/lydia/decoder.h +++ /dev/null @@ -1,133 +0,0 @@ -/* IvySync - Video SyncStarter - * - * (c) Copyright 2004 - 2006 Denis Rojo - * Nederlands Instituut voor Mediakunst - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - - -#ifndef __DECODER_H__ -#define __DECODER_H__ - -// for large file support (64bit file offsets) -#define _LARGEFILE_SOURCE 1 - -/* On many architectures both off_t and long are 32-bit types, but - compilation with #define _FILE_OFFSET_BITS 64 will turn off_t into - a 64-bit type. - see man fseeko(3) */ -#define _FILE_OFFSET_BITS 64 - - -#include -#include -#include - -#include -#include - - - -// playmode values -#define PLAY 1 -#define CONT 2 -#define LOOP 3 -#define RAND 4 -#define SINGLE 5 - -// maximum path lenght -#define MAXPATH 512 - -class Playlist; // graphical interface - -class Decoder : public Thread, public Entry { - - public: - Decoder(); - ~Decoder(); - - bool init(char *dev); - - bool setup(bool *sync, int bufsize); - - void close(); - - // playlist stuff - bool prepend(char *file); ///< prepend *file at the beginning of the playlist - bool append(char *file); ///< append *file at the end of the playlist - bool insert(char *file, int pos); ///< insert *file in playlist at pos - // bool remove(char *file); ///< remove the first occurrence of *file - bool remove(int pos); ///< remove the playlist entry at pos - bool empty(); ///< empty all the playlist discarding all entries - - // save on file - int load(); - int save(); - - int playmode; ///< PLAY, CONT, LOOP or RAND - int position; ///< current position in playlist (read-only) - - - bool play(); - bool stop(); - bool pause(); - bool clear(); - - int getpos(); - void setpos(int pos); - - int getoffset(); - void setoffset(int pos); - - /** state flags for use in the inner loop - the following booleans are changed by asynchronous calls - then behaviour is synched and executed in the main loop */ - bool playing; - bool stopped; - - bool *syncstart; - - char device[MAXPATH]; - int device_num; - - Linklist playlist; - Entry *current; ///< path of movie currently playing - - Playlist *gui; ///< pointer to the GUI, NULL if none - - bool dummy; // for dummy test run without devices - - private: - void run(); - void update(); - - void flush(); - - off64_t filesize; // current file playing, size in bytes - off64_t filepos; // current file playing, position in bytes - off64_t newfilepos; // new position to skip in file - - int fd; - FILE *playlist_fd; - -// uint8_t buffo[CHUNKSIZE+1024]; // + 1k bound - uint8_t *buffo; - int buffo_size; - -}; - - -#endif diff --git a/branches/lydia/gui.cpp b/branches/lydia/gui.cpp deleted file mode 100644 index 6464e60..0000000 --- a/branches/lydia/gui.cpp +++ /dev/null @@ -1,610 +0,0 @@ - -#include -#include - -#include -#include -#include - -#include - -#include -#include - - -#define PACKAGE_DATA_DIR "/usr/share/ivysync" -#define CONFIGFILE "/home/jaromil/ivysyncrc" - -static GtkWindow *main_window; - -// playlist model columns -enum { - POSITION, - FILENAME, - COLUMNS -}; - -/* DND stuff ripped from wolfpack.twu.net/docs/gtkdnd */ -#define DRAG_TAR_NAME_0 "text/plain" -#define DRAG_TAR_INFO_0 0 - -#define DRAG_TAR_NAME_1 "text/uri-list" /* not url-list */ -#define DRAG_TAR_INFO_1 1 - -#define DRAG_TAR_NAME_2 "STRING" -#define DRAG_TAR_INFO_2 2 -/* end */ - - -// CALLBACKS - -void on_add_button(GtkWidget *widget, gpointer *data) { - GtkWidget *dialog; - Playlist *pl = (Playlist*)data; - - dialog = gtk_file_chooser_dialog_new ("Open File", main_window, - GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, - GTK_RESPONSE_ACCEPT, NULL); - - gtk_file_chooser_set_select_multiple((GtkFileChooser*)dialog, true); - - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { - GSList *filenames; - filenames = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (dialog)); - while(filenames) { - D("file choosen: %s",filenames->data); - pl->decoder->append((char*)filenames->data); - g_free(filenames->data); - filenames = filenames->next; - } - g_slist_free(filenames); - } - - gtk_widget_destroy(dialog); - pl->refresh(); -} - - -void on_save_button(GtkWidget *widget, gpointer *data) { - Playlist *pl = (Playlist*)data; - pl->decoder->save(); -} - -void on_syncstart_button(GtkWidget *widget, gpointer *data) { - vector::iterator pl_iter; - Gui *gui = (Gui*)data; - Playlist *pl; - - gui->syncstart = false; - - for( pl_iter = gui->playlist.begin(); - pl_iter != gui->playlist.end(); - ++pl_iter) { - pl = *pl_iter; - pl->decoder->stop(); - pl->decoder->position = 0; - pl->decoder->play(); - pl->refresh(); - - } - - jsleep(1,0); - gui->syncstart = true; - -} - -void on_play_button(GtkWidget *widget, gpointer *data) { - Playlist *pl = (Playlist*)data; - if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { - if(!pl->decoder->running) pl->decoder->launch(); - pl->decoder->play(); - } else { - pl->decoder->stop(); - } -} - -void on_rewind_button(GtkWidget *widget, gpointer *data) { - Playlist *pl = (Playlist*)data; - pl->decoder->stop(); - pl->decoder->position = 0; - pl->refresh(); -} - -void on_delete_button(GtkWidget *widget, gpointer *data) { - GtkTreeSelection *select; - GtkTreeModel *model; - GtkTreeIter iter; - GList *rowlist; - char *pos, *p; - int numpos; - - Playlist *pl = (Playlist*)data; - - // get out a rowlist of selections - model = gtk_tree_view_get_model(GTK_TREE_VIEW(pl->treeview)); - select = gtk_tree_view_get_selection(GTK_TREE_VIEW(pl->treeview)); - rowlist = gtk_tree_selection_get_selected_rows(select, &model); - - if(!rowlist) return; - - rowlist = g_list_reverse(rowlist); - rowlist = g_list_first(rowlist); - - // fill in filelist with all the selected FILENAME entries - if(rowlist->data) { - - while(rowlist && rowlist->data) { - - gtk_tree_model_get_iter(model, &iter, (GtkTreePath*)rowlist->data); - gtk_tree_model_get(model, &iter, POSITION, &pos, -1); - - // strip out the -> selection - for(p = pos; *p!='\0'; p++) - if(!isdigit(*p)) *p=' '; - - - numpos = atoi(pos); - - D("removing playlist entry at pos %u",numpos); - pl->decoder->remove(numpos); - - g_free(pos); // free the char* - gtk_tree_path_free((GtkTreePath*)rowlist->data); // free the path - - rowlist = g_list_next(rowlist); - } - } - - // free the rowlist - g_list_free(rowlist); - - pl->refresh(); -} - - -void on_set_playmode(GtkWidget *w, gpointer *data) { - Playlist *pl = (Playlist*)data; - gint mode; - if((mode = gtk_option_menu_get_history(GTK_OPTION_MENU(w))) != -1) - pl->decoder->playmode = mode+1; - D("playmode set to %u",mode+1); -} - -void DND_begin(GtkWidget *w, GdkDragContext *dc, gpointer *data) { D("drag begin"); } -void DND_end(GtkWidget *w, GdkDragContext *dc, gpointer *data) { D("drag end"); } - -gboolean DND_data_get(GtkWidget *w, GdkDragContext *dc, - GtkSelectionData *selection, guint info, guint t, gpointer *data) { - - GtkTreeIter iter; - GtkTreeModel *model; - GtkTreeSelection *select; - // gint row=0; - gchar *title; - GList *rowlist; - - Playlist *pl = (Playlist*)data; - - model = gtk_tree_view_get_model(GTK_TREE_VIEW(w)); - select = gtk_tree_view_get_selection(GTK_TREE_VIEW(w)); - rowlist = gtk_tree_selection_get_selected_rows(select, &model); - - rowlist = g_list_first(rowlist); - if(rowlist->data) { - // rowsrc = gtk_tree_path_get_indices((GtkTreePath *)rowlist->data)[0]; - while(rowlist && rowlist->data) { - gtk_tree_model_get_iter(model, &iter, (GtkTreePath *)rowlist->data); - gtk_tree_model_get(model, &iter, POSITION, &title, -1); - - pl->draglist = g_list_append(pl->draglist, (void *) title); - D("dragging entry at position %s",title); - // gtk_tree_path_free((GtkTreePath *)rowlist->data); - - rowlist = g_list_next(rowlist); - } - } else - return FALSE; - - // free the rowlist - g_list_free(rowlist); - - return TRUE; -} - -gboolean DND_drop(GtkWidget *w, GdkDragContext *dc, gint x, gint y, - guint t, gpointer *data) { - - GtkTreePath *path; - gint row =0; - char *p; - int numpos; - Playlist *pl = (Playlist*)data; - - if(gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(w), - x, y, &path, NULL, NULL, NULL)) { - row = gtk_tree_path_get_indices(path)[0]; - D("DND drop on row = %d", row); - gtk_tree_path_free(path); - } - - g_list_first(pl->draglist); - if(!pl->draglist || !pl->draglist->data) return FALSE; - - while(pl->draglist) { - - if(row) { // if there is a place where to move it - - // strip out the -> selection and get the position - for(p = (char*)pl->draglist->data; *p!='\0'; p++) - if(!isdigit(*p)) *p=' '; - numpos = atoi((char*)pl->draglist->data); - D("move entry %u:%s into slot %u",numpos, - (char*)pl->decoder->playlist[numpos-1]->name,row+1); - numpos--; - - if(row>numpos) row++; - - pl->decoder->insert - ( (char*)pl->decoder->playlist[numpos]->name, row ); - - if(rowdecoder->remove(numpos+1); - - } - - // g_free(pl->draglist->data); - pl->draglist = g_list_next(pl->draglist); - } - - // g_list_free(pl->draglist); - // pl->draglist = NULL; - - pl->refresh(); - return TRUE; -} - -gboolean DND_data_motion(GtkWidget *w, GdkDragContext *dc, gint x, gint y, - guint t, gpointer *data) { - gdk_drag_status(dc, GDK_ACTION_MOVE, t); - // D("drag_data_motion"); - return FALSE; -} - - - -////////////////// PLAYLIST WIDGET CLASS - -Playlist::Playlist(int num) { - - selected = 0; - draglist = NULL; - - widget = gtk_vbox_new (FALSE, 0); - snprintf(widget_name,255,"widget_%u",num); - gtk_widget_set_name (widget, widget_name); - gtk_widget_show (widget); - - scrolledwindow = gtk_scrolled_window_new (NULL, NULL); - snprintf(scrolledwindow_name,255,"scrolledwindow_%u",num); - gtk_widget_set_name (scrolledwindow, scrolledwindow_name); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), - GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); - gtk_widget_show (scrolledwindow); - gtk_box_pack_start (GTK_BOX (widget), scrolledwindow, TRUE, TRUE, 0); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_SHADOW_IN); - - treeview = gtk_tree_view_new (); - snprintf(treeview_name,255,"treeview_%u",num); - gtk_widget_set_name (treeview, treeview_name); - gtk_widget_show (treeview); - gtk_container_add (GTK_CONTAINER (scrolledwindow), treeview); - - buttonbox = gtk_hbox_new (FALSE, 0); - snprintf(buttonbox_name,255,"buttonbox_%u",num); - gtk_widget_set_name (buttonbox, buttonbox_name); - gtk_widget_show (buttonbox); - gtk_box_pack_start (GTK_BOX (widget), buttonbox, FALSE, FALSE, 0); - - add_button = gtk_button_new_from_stock ("gtk-add"); - snprintf(add_button_name,255,"add_button_%u",num); - gtk_widget_set_name (add_button, add_button_name); - gtk_widget_show (add_button); - gtk_box_pack_start (GTK_BOX (buttonbox), add_button, FALSE, FALSE, 0); - g_signal_connect((gpointer)add_button, "pressed", G_CALLBACK(on_add_button), this); - - delete_button = gtk_button_new_from_stock ("gtk-delete"); - snprintf(delete_button_name,255,"delete_button_%u",num); - gtk_widget_set_name (delete_button, delete_button_name); - gtk_widget_show (delete_button); - gtk_box_pack_start (GTK_BOX (buttonbox), delete_button, FALSE, FALSE, 0); - g_signal_connect((gpointer)delete_button, "pressed", G_CALLBACK(on_delete_button), this); - - /* - up_button = gtk_button_new (); - snprintf(up_button_name,255,"up_button_%u",num); - gtk_widget_set_name (up_button, up_button_name); - gtk_widget_show (up_button); - gtk_box_pack_start (GTK_BOX (buttonbox), up_button, FALSE, FALSE, 0); - - image2 = gtk_image_new_from_stock ("gtk-go-up", GTK_ICON_SIZE_BUTTON); - snprintf(image2_name,255,"image2_%u",num); - gtk_widget_set_name (image2, image2_name); - gtk_widget_show (image2); - gtk_container_add (GTK_CONTAINER (up_button), image2); - - down_button = gtk_button_new (); - snprintf(down_button_name,255,"down_button_%u",num); - gtk_widget_set_name (down_button, down_button_name); - gtk_widget_show (down_button); - gtk_box_pack_start (GTK_BOX (buttonbox), down_button, FALSE, FALSE, 0); - - image3 = gtk_image_new_from_stock ("gtk-go-down", GTK_ICON_SIZE_BUTTON); - snprintf(image3_name,255,"image3_%u",num); - gtk_widget_set_name (image3, image3_name); - gtk_widget_show (image3); - gtk_container_add (GTK_CONTAINER (down_button), image3); - */ - - rewind_button = gtk_button_new(); - snprintf(rewind_button_name,255,"rewind_button_%u",num); - gtk_widget_set_name(rewind_button, rewind_button_name); - gtk_widget_show(rewind_button); - gtk_box_pack_start(GTK_BOX(buttonbox), rewind_button, FALSE, FALSE, 0); - rewind_image = gtk_image_new_from_stock("gtk-media-previous", GTK_ICON_SIZE_BUTTON); - snprintf(rewind_image_name,255,"rewind_image_%u",num); - gtk_widget_set_name(rewind_image, rewind_image_name); - gtk_widget_show(rewind_image); - gtk_container_add(GTK_CONTAINER(rewind_button), rewind_image); - g_signal_connect((gpointer)rewind_button, "pressed", G_CALLBACK(on_rewind_button), this); - - play_button = gtk_toggle_button_new_with_mnemonic ("gtk-media-play"); - gtk_button_set_use_stock (GTK_BUTTON (play_button), TRUE); - snprintf(play_button_name,255,"play_button_%u",num); - gtk_widget_set_name (play_button, play_button_name); - gtk_widget_show (play_button); - gtk_box_pack_start (GTK_BOX (buttonbox), play_button, FALSE, FALSE, 0); - g_signal_connect((gpointer)play_button, "pressed", G_CALLBACK(on_play_button), this); - - { - GtkWidget *tmpwid; - playmode_menu = gtk_menu_new(); - tmpwid = gtk_menu_item_new_with_label("once"); - gtk_menu_append(GTK_MENU(playmode_menu), tmpwid); - gtk_widget_show(tmpwid); - tmpwid = gtk_menu_item_new_with_label("loop"); - gtk_menu_append(GTK_MENU(playmode_menu), tmpwid); - gtk_widget_show(tmpwid); - tmpwid = gtk_menu_item_new_with_label("continuous"); - gtk_menu_append(GTK_MENU(playmode_menu), tmpwid); - gtk_widget_show(tmpwid); - gtk_widget_show(playmode_menu); - - playmode_menuopt = gtk_option_menu_new(); - gtk_option_menu_set_menu(GTK_OPTION_MENU(playmode_menuopt), playmode_menu); - gtk_widget_show(playmode_menuopt); - gtk_box_pack_start (GTK_BOX (buttonbox), playmode_menuopt, TRUE, TRUE, 0); - - g_signal_connect(G_OBJECT(playmode_menuopt), "changed", G_CALLBACK(on_set_playmode), this); - } - - save_button = gtk_button_new_from_stock ("gtk-save"); - snprintf(save_button_name,255,"save_button_%u",num); - gtk_widget_set_name (save_button, save_button_name); - gtk_widget_show (save_button); - gtk_box_pack_start (GTK_BOX (buttonbox), save_button, TRUE, TRUE, 0); - g_signal_connect((gpointer)save_button, "pressed", G_CALLBACK(on_save_button), this); - - /* - statusbar = gtk_statusbar_new (); - snprintf(statusbar_name,255,"statusbar_%u",num); - gtk_widget_set_name (statusbar, statusbar_name); - gtk_widget_show (statusbar); - gtk_box_pack_start (GTK_BOX (widget), statusbar, FALSE, FALSE, 0); - */ - - // now setup the model view for the treeview - treestore = gtk_tree_store_new(COLUMNS, - G_TYPE_STRING, // position - G_TYPE_STRING); // name - gtk_tree_view_set_model((GtkTreeView*)treeview,GTK_TREE_MODEL(treestore)); - - { // then the selection handling - GtkTreeSelection *treeselect; - treeselect = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); - gtk_tree_selection_set_mode(treeselect, GTK_SELECTION_MULTIPLE); - // g_signal_connect(G_OBJECT(treeselect), "changed", - // G_CALLBACK(on_playlist_select), this); - } - - - { // then the drag and drop stuff - target_entry[0].target = DRAG_TAR_NAME_0; - target_entry[0].flags = 0; - target_entry[0].info = DRAG_TAR_INFO_0; - - target_entry[1].target = DRAG_TAR_NAME_1; - target_entry[1].flags = 0; - target_entry[1].info = DRAG_TAR_INFO_1; - - target_entry[2].target = DRAG_TAR_NAME_2; - target_entry[2].flags = 0; - target_entry[2].info = DRAG_TAR_INFO_2; - - gtk_drag_source_set - (treeview, - (GdkModifierType) (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK), - target_entry, sizeof(target_entry) / sizeof(GtkTargetEntry), - (GdkDragAction)GDK_ACTION_MOVE ); -// g_signal_connect(G_OBJECT(treeview), "drag_motion", G_CALLBACK(DND_data_motion), this); - g_signal_connect(G_OBJECT(treeview), "drag_begin", G_CALLBACK(DND_begin), this); - g_signal_connect(G_OBJECT(treeview), "drag_end", G_CALLBACK(DND_end), this); - g_signal_connect(G_OBJECT(treeview), "drag_data_get", G_CALLBACK(DND_data_get), this); - g_signal_connect(G_OBJECT(treeview), "drag_drop", G_CALLBACK(DND_drop), this); -// g_signal_connect(G_OBJECT(treeview), "drag_data_delete", G_CALLBACK(DND_data_delete), this); - - gtk_drag_dest_set - (treeview, - // (GtkDestDefaults)(GTK_DEST_DEFAULT_ALL), - (GtkDestDefaults)(GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP), - target_entry, sizeof(target_entry) / sizeof(GtkTargetEntry), - (GdkDragAction)GDK_ACTION_MOVE ); -// g_signal_connect(G_OBJECT(treeview), "drag_data_received", G_CALLBACK(DND_data_received), this); - - } - - { // and finally the cell rendering - GtkCellRenderer *rend; - GtkTreeViewColumn *col; - rend = gtk_cell_renderer_text_new(); - g_object_set(G_OBJECT(rend),"background","orange",NULL); - col = gtk_tree_view_column_new_with_attributes - ("Pos",rend,"text",POSITION,NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeview),col); - - rend = gtk_cell_renderer_text_new(); - col = gtk_tree_view_column_new_with_attributes - ("Filename",rend,"text",FILENAME,NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeview),col); - } -} - -Playlist::~Playlist() { - gtk_widget_destroy(statusbar); - gtk_widget_destroy(save_button); - gtk_widget_destroy(image3); - gtk_widget_destroy(down_button); - gtk_widget_destroy(image2); - gtk_widget_destroy(up_button); - gtk_widget_destroy(delete_button); - gtk_widget_destroy(add_button); - gtk_widget_destroy(buttonbox); - gtk_widget_destroy(treeview); - gtk_widget_destroy(scrolledwindow); - - gtk_widget_destroy(widget); - -} - -// read again the playlist from the decoder and fill it up -int Playlist::refresh() { - GtkTreeIter iter; // static - Entry *ent; - char tmp[16]; - int c; - - gtk_tree_store_clear(treestore); - - c = 0; - ent = decoder->playlist.begin(); - while(ent) { - gtk_tree_store_append(treestore,&iter,NULL); - - snprintf(tmp,15,"%s%u", - ((decoder->position+1)==c)?"->":" ", - c); - - gtk_tree_store_set(treestore,&iter, - POSITION, tmp, - FILENAME, ent->name, - -1); - - ent = ent->next; - c++; - } - - return 1; -} - -///////////////////////////////////////////////////////////////// - - - - -Gui::Gui() { - - D("instantiating Gui class"); - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_widget_set_name (window, "window"); - gtk_widget_set_size_request (window, 400, 300); - gtk_window_set_title (GTK_WINDOW (window), "IvySync Graphical Interface"); - main_window = (GtkWindow*)window; // global static pointer - - vbox = gtk_vbox_new (FALSE, 0); - gtk_widget_set_name (vbox, "main_vbox"); - gtk_widget_show (vbox); - gtk_container_add(GTK_CONTAINER(window), vbox); - - D("gtk_notebook_new"); - notebook = gtk_notebook_new (); - gtk_widget_set_name (notebook, "notebook"); - gtk_widget_show (notebook); - gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0); - //gtk_container_add (GTK_CONTAINER (vbox), notebook); - - D("syncbutton"); - syncbutton = gtk_toggle_button_new_with_mnemonic ("gtk-media-play"); - gtk_button_set_use_stock (GTK_BUTTON (syncbutton), TRUE); - gtk_widget_set_name (syncbutton, "sync_button"); - gtk_widget_show (syncbutton); - gtk_box_pack_start (GTK_BOX (vbox), syncbutton, FALSE, FALSE, 0); - g_signal_connect((gpointer)syncbutton, "pressed", G_CALLBACK(on_syncstart_button), this); - - // QUAA - syncstart = true; -} - -Gui::~Gui() { - gtk_widget_destroy(notebook); - gtk_widget_destroy(window); -} - -bool Gui::init(Linklist *devices) { - Decoder *dec; - Playlist *pl; - int c; - - c = 1; - - D("Gui::init"); - - dec = (Decoder*)devices->begin(); - while(dec) { - - dec->syncstart = &syncstart; - - D("new Playlist(%i)",c); - pl = new Playlist(c); - - pl->decoder = dec; // store the decoder pointer in the playlist - dec->gui = pl; // store the GUI pointer in the decoder (cross reference) - - D("refresh the playlist"); - pl->refresh(); // refresh with the filenames - playlist.push_back(pl); // store the playlist in the gui array - - D("add to the container"); - gtk_container_add(GTK_CONTAINER(notebook), pl->widget); - char tmp[256]; - snprintf(tmp,255,"/dev/video%u",dec->device_num); - gtk_notebook_set_tab_label_text ((GtkNotebook*)notebook, - gtk_notebook_get_nth_page((GtkNotebook*)notebook, - c-1), tmp); - dec = (Decoder*)dec->next; - c++; - } - return true; -} -void Gui::status(char *format, ...) { - // TODO status bar messages - return; -} - - - -void Gui::start() { - g_signal_connect((gpointer)window, "destroy", G_CALLBACK(gtk_main_quit), NULL); - gtk_widget_show(window); - gtk_main(); -} diff --git a/branches/lydia/gui.h b/branches/lydia/gui.h deleted file mode 100644 index 58de6db..0000000 --- a/branches/lydia/gui.h +++ /dev/null @@ -1,96 +0,0 @@ - -#ifndef __GUI_H__ -#define __GUI_H__ - - - -#include -#include - -#include - -// damn STL -#include -using namespace std; -using namespace __gnu_cxx; - - -class Playlist { - public: - Playlist(int num); - ~Playlist(); - - int refresh(); - - GtkWidget *widget; - - Decoder *decoder; - - int selected; - - GtkWidget *treeview; - - GList *draglist; - bool draglock; - - private: - // rendered widget names - char widget_name[256]; - char scrolledwindow_name[256]; - char treeview_name[256]; - char buttonbox_name[256]; - char add_button_name[256]; - char delete_button_name[256]; - char up_button_name[256]; - char down_button_name[256]; - char play_button_name[256]; - char image2_name[256]; - char image3_name[256]; - char save_button_name[256]; - char statusbar_name[256]; - char rewind_button_name[256]; - char rewind_image_name[256]; - - // widget pointers - GtkTreeStore *treestore; - - GtkWidget *scrolledwindow; - GtkWidget *buttonbox; - GtkWidget *add_button; - GtkWidget *delete_button; - GtkWidget *up_button; - GtkWidget *image2; - GtkWidget *down_button; - GtkWidget *play_button; - GtkWidget *image3; - GtkWidget *save_button; - GtkWidget *statusbar; - GtkWidget *playmode_menu; - GtkWidget *playmode_menuopt; - GtkWidget *rewind_button; - GtkWidget *rewind_image; - GtkTargetEntry target_entry[3]; -}; - -class Gui { - public: - Gui(); - ~Gui(); - - bool init(Linklist *devices); - void start(); - - bool syncstart; - - vector playlist; - - private: - void status(char *format, ...); - GtkWidget *window; - GtkWidget *vbox; - GtkWidget *syncbutton; - GtkWidget *notebook; - -}; - -#endif diff --git a/branches/lydia/ivysync-gui.glade b/branches/lydia/ivysync-gui.glade deleted file mode 100644 index a993574..0000000 --- a/branches/lydia/ivysync-gui.glade +++ /dev/null @@ -1,604 +0,0 @@ - - - - - - - True - window1 - GTK_WINDOW_TOPLEVEL - GTK_WIN_POS_NONE - False - True - False - True - False - False - GDK_WINDOW_TYPE_HINT_NORMAL - GDK_GRAVITY_NORTH_WEST - True - - - - True - True - True - True - GTK_POS_TOP - False - False - - - - True - False - 0 - - - - True - True - GTK_POLICY_ALWAYS - GTK_POLICY_ALWAYS - GTK_SHADOW_IN - GTK_CORNER_TOP_LEFT - - - - True - True - True - False - False - True - False - False - False - - - - - 0 - True - True - - - - - - True - False - 0 - - - - True - True - gtk-add - True - GTK_RELIEF_NORMAL - True - - - 0 - False - False - - - - - - True - True - gtk-delete - True - GTK_RELIEF_NORMAL - True - - - 0 - False - False - - - - - - True - True - GTK_RELIEF_NORMAL - True - - - - True - gtk-go-up - 4 - 0.5 - 0.5 - 0 - 0 - - - - - 0 - False - False - - - - - - True - True - GTK_RELIEF_NORMAL - True - - - - True - gtk-go-down - 4 - 0.5 - 0.5 - 0 - 0 - - - - - 0 - False - False - - - - - - True - True - gtk-save - True - GTK_RELIEF_NORMAL - True - - - 0 - True - True - - - - - 0 - False - False - - - - - - True - True - - - 0 - False - False - - - - - False - True - - - - - - True - label2 - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - tab - - - - - - True - False - 0 - - - - True - True - GTK_POLICY_ALWAYS - GTK_POLICY_ALWAYS - GTK_SHADOW_IN - GTK_CORNER_TOP_LEFT - - - - True - True - True - False - False - True - False - False - False - - - - - 0 - True - True - - - - - - True - False - 0 - - - - True - True - gtk-add - True - GTK_RELIEF_NORMAL - True - - - 0 - False - False - - - - - - True - True - gtk-delete - True - GTK_RELIEF_NORMAL - True - - - 0 - False - False - - - - - - True - True - GTK_RELIEF_NORMAL - True - - - - True - gtk-go-up - 4 - 0.5 - 0.5 - 0 - 0 - - - - - 0 - False - False - - - - - - True - True - GTK_RELIEF_NORMAL - True - - - - True - gtk-go-down - 4 - 0.5 - 0.5 - 0 - 0 - - - - - 0 - False - False - - - - - - True - True - gtk-save - True - GTK_RELIEF_NORMAL - True - - - 0 - True - True - - - - - 0 - False - False - - - - - - True - True - - - 0 - False - False - - - - - False - True - - - - - - True - label3 - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - tab - - - - - - True - False - 0 - - - - True - True - GTK_POLICY_ALWAYS - GTK_POLICY_ALWAYS - GTK_SHADOW_IN - GTK_CORNER_TOP_LEFT - - - - True - True - True - False - False - True - False - False - False - - - - - 0 - True - True - - - - - - True - False - 0 - - - - True - True - gtk-add - True - GTK_RELIEF_NORMAL - True - - - 0 - False - False - - - - - - True - True - gtk-delete - True - GTK_RELIEF_NORMAL - True - - - 0 - False - False - - - - - - True - True - GTK_RELIEF_NORMAL - True - - - - True - gtk-go-up - 4 - 0.5 - 0.5 - 0 - 0 - - - - - 0 - False - False - - - - - - True - True - GTK_RELIEF_NORMAL - True - - - - True - gtk-go-down - 4 - 0.5 - 0.5 - 0 - 0 - - - - - 0 - False - False - - - - - - True - True - gtk-save - True - GTK_RELIEF_NORMAL - True - - - 0 - True - True - - - - - 0 - False - False - - - - - - True - True - - - 0 - False - False - - - - - False - True - - - - - - True - label4 - False - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - tab - - - - - - - diff --git a/branches/lydia/ivysync-remote.py b/branches/lydia/ivysync-remote.py deleted file mode 100755 index 35b9007..0000000 --- a/branches/lydia/ivysync-remote.py +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/python - -# python xmlrpc client for ivysync -# (C)2006 by Denis "Jaromil" Rojo -# released under the GNU General Public License - -# general system functions -import sys -from string import atoi - -# xmlrpclib client functions -from socket import gethostname -from xmlrpclib import Transport, dumps - - - - - -###################################################################### -# XMLRPC Client connection class - -class xmlrpc_connection: - """The xmlrpc_connection class tests the xmlrpc_server. You must - download and install the medusa and xmlrpclib libraries to run - this code: http://www.nightmare.com http://www.pythonware.com""" - - def __init__(self, host=None, port=2640): - if host is None: - host = gethostname() - self.host = "%s:%s" % (host, port) - self.transport = Transport() - - def remote(self, method, params=()): - """remote invokes the server with the method name and an - optional set of parameters. The return value is always a - tuple.""" - - response = self.transport.request(self.host, - '/RPC2', - dumps(params, method)) - return response - -################################################################### - - - - - -################################################################### -## MAIN - - - -if __name__ == '__main__': - - commands = ("Play", "SyncStart", "Stop", "Open", "Pause", "Quit", "GetPos", "SetPos", "GetOffset", "SetOffset", "SyncOffset") - - connection = xmlrpc_connection() - -# if(sys.argc): -# cmd = "none" -# else: - cmd = sys.argv[1] - - - if not cmd in commands: - - print "no valid command recognized, list of valid commands:" - print commands - sys.exit(2) - - if cmd == "SyncStart": - (res,) = connection.remote(cmd, (0, 0)) - if res == 1: - answer = "Sync starting OK" - else: - answer = "Error in sync starting" - - elif cmd == "SyncOffset": - - pos = int( sys.argv[2] ) - - (res,) = connection.remote(cmd, (pos, 0)) - if res == 1: - answer = "Global sync to offset " + str(pos) - else: - answer = "Error in SyncOffset" - - elif cmd == "Quit": - - (res,) = connection.remote(cmd, (0, 0)) - if res == 1: - answer = "Server is now quitting" - else: - answer = "Server refuses to quit" - - - elif cmd == "SetPos": - - chan = int( sys.argv[2] ) - pos = int( sys.argv[3] ) - - (res,) = connection.remote(cmd, (chan, pos)) - answer = "Channel " + str(chan) + " is now at " + str(pos) + "%" - - elif cmd == "SetOffset": - chan = int( sys.argv[2] ) - pos = int( sys.argv[3] ) - - (res,) = connection.remote(cmd, (chan, pos)) - answer = "Channel " + str(chan) + " is now at " + str(pos) + " byte offset" - - elif cmd == "GetPos": - - chan = int( sys.argv[2] ) - (res,) = connection.remote(cmd, (chan, 0)) - answer = "Channel " + str(chan) + " is now at " + str(res) + "%" - - elif cmd == "GetOffset": - - chan = int( sys.argv[2] ) - (res,) = connection.remote(cmd, (chan, 0)) - answer = "Channel " + str(chan) + " is now at " + str(res) + " byte offset" - - elif cmd == "Open": - - chan = int(sys.argv[2] ) - path = str(sys.argv[3] ) - (res,) = connection.remote(cmd, (chan, path)) - if res == 1: - answer = "File " + path + " opened on channel " + str(chan) - else: - answer = "Error opening file " + path - - else: # all other commands needing only one argument (channel num) - - chan = int( sys.argv[2] ) - - (res,) = connection.remote(cmd, (chan, 0)) - if res == 1: - answer = "Command '" + cmd + "' succesfully executed on channel " + str(chan) - else: - answer = "Error executing command '" + cmd + "' on channel " + str(chan) - - print answer # 42! ;D diff --git a/branches/lydia/ivysync-xmlrpc-spec.odt b/branches/lydia/ivysync-xmlrpc-spec.odt deleted file mode 100644 index 4be2dbb16f32cdc9807c37b3f91f5472c53862c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9945 zcma)i1zc3k*FPfNDJhZyBC(XPG}0~Ivg|I+E&>aJbczy!ASn{kCEZB3bV?)LjR?ZK z7|-ML{NLa2{|?N4=FWW2nRDmP+&T91t?i-C zZVph8gM*zl802gXhjF{WAY5>eleH5U+yM%Mz`+Q6D9oA58T!;&;~&b9@_!{FWa%Ls zW?^lKaQvahiI@97qp^`_4QsG7!V&893x$7d zrXPjsB*OxGN(HJ%by#U8Gpe8J&y%O&v+!#4H(${|LkrzjSD=DT}oXKH2 z&D#y1Eo(Q-T5XVct2Q-kYSbAyCoCdzxNWuIpx>Dh57E7crWo#Zd13vSnZq_bH>&qJHTsiKq-=lqv#vQOe(@eLl1ctqe zuPnO(n@V6e0p%dSaw0N!t{4qL zBPwGyKukWCc56Y_boR%oP64`?Xs&|#4ot3}t|DzRSemfE;YL!LfC>i!=gs|_ErrN8 zMk}yk&g_&A25E@Zm;*JHWMr5hlPKm8fXdsB-pIICe^Y}*B^($Z+5sGSzR)z!qJ7g1 z6>Q{tAkh?+u)WSj$i+t3k$9kqH*IuWr(H2Na8tWT`bO7tjxQDg93wGkcOF=rG^j~8 z(8W#ZP>e?3L&Uzktl;AN7{P}hX+!O;8@Jtd9U@&fZ@XQwGrfD~bWn8Ny~!$|0e9=8aS`>GPEpx;zgVkd8}ewL$HKMb$5L0=l_FBP zMua(315tVb!^hd^&@zg)64@(;&29IvcA6B9;j&b-!SLsm_!K*az8igokq7ljo;Yf5 z_3fDjJyWp<>Xj35pQ*La3N^H+gHzb71@4leyoN=yQY)R?I?W(^Mn_hU>7z3J^>+UC|Yg>wCPdiF2XJ*##gm1 zZBCd}gJ{gT6z8SeS^WyIS(30RJ~UWGyLiCe$^oYfL|`H@?VLqDppS91e9{{N$97HL|cDS*&6m@`(l|k#j3`3+OF% z0WzFl^^d7@oohB=c4M;na=dXV`N3_qGuqXw#t<-KjW4cdp~pv;_LxiDP2zFG!(D(P zn*2Q$hCqlB|Efy|A-}-YJSNWP?@S{PDfENDBlv!=nfQ}Z=fLbF-MV%en-zH3ZM7y| zveiw;aVes@EaqZuQ7J@D{LG#CfPBS(G!G5P?_Llfe_%m6?wT_Z|LC`lR_9dUYS;#7Out&{=J zVU#0P;crwWDcCj9(l0f5jtKB9J(3BJT9!LbXtT?JDB7G^M#Iw;q=ESbxi-CN)uInFJv9bR5?onDV>4J{iNtOZn}x%%nl;qXIPgc& zC>)o>r6GqmLu@CRe=t{!i@O5erG1imh{GT5M=hN3 zf;Lr0hIufaKQDKffQSr)a;3`CgXK;af(JarEj4E@Mx^mN;5%YD0y6LWBk+@H?#$E_ zZY_n|2rzhb1LA$iOU1}`#2-kbL~gUaphq|HwE;44_vzso8IPA0)fvhOD7sXkLboIx z7^w-ri{PF_urF+)nba2iog-ND;R=`*#C+=-9PaylVtDg2;bS`lX>gO60o5MXOeG8)kOhrPNc)as`^k5KuEf#x#MYRe=>$9?_cxbzdzV9w;oY5G_+jm2 z!zIx}WVSk;wh}|aVWMJt>XXIe;v;~Cxs4kI>6=IC&)We2ZrSu#gWAI8*qnVM`kGIk zt#1!Isjt+^R^JE8cdD1BN~97Kcds4=*-W>SeiQn%1}U)h@9KE;y+k0+9Dg-5zLUA+ zlBs1U-XuLhUOwnS03}=MdRv6`cuEzNWi$7~|bDXDS#G!~O!C-{s}J&gcn^I8WyVmtwcdP$wH z=ygahcul=i=Jf*9tBIewBOKg88iGO|8j4&8)%_l!?rUZG!miA(+J z>Dx%Z^U~zMd5JhkFVV@_%?|2x?IeCORF0SuBx*R-qrCSy(XQvbWM&IPVIU2?q~31G zR#LgFO^y*g%5duJ_;ys9Oiy(FF$`yws4)psqR)etAjk96E7mgIvKJk6B>ud8*et-h zmqhx(X;W;!cfjHN_ZIct33pZVIu(86mAGz=PS2n=tk4{N>IF{?#~O$NQSp1W4s-S| zEF3)La>{zoaJ$Q*S&ri7PI5aX^8*MfTMN{TYf6FU5UbcBcW(gG5SXtT<4{VrE?`cc$II(# zWu}%V%}WG_1TAXSa4{RMaP(pZV<+IK2^*&!!mA6_X+i#j4=nh`5R|?8Hz4yf4 ziFr6Ysh2f^e&kBb%ciRFFx82D#$Tf?iOfINy3FKRyFR`SRUCfqLSN?aX2{vL75v#~ zWs*Yg?c*vvF*yTc`K0BB6kk*R8(~Be90?fdxdF7%1(-(ZV|W|G)NMj44oM-wu0ck} zdz}}$fEvPN=0){$kG2vsG|>`6;jR--&=(nESu?D!Tx4><^><5rN(SMK{djVY-Iq5b zr5!^L1|{Os2T9Y+k2={7g)Yd+RW8P$X74dy0)iGWw0f~2_bjnjjwCbac``6lq7Rx(}cf> zZuK24@Crr`=IvtfJy8=P5};8Evkhhw%mZ-5|5aGE55 zp8?b@bVh(H89x|acwY97JYgao*Rsd#qkN5ck&X|qe&3r;e*S_PYG`w+ysywuu_F^y zMoB^@17brmkEh7Pm&?X6Xk@OT znXAC9_ib1Oj7v%6(tu1Fmx4lvI|Z3!l+BVlj-RSqcrjFCmRM-pZ7qnf4{pDbE0x|T z#v4=(5#$NTp?hwi$bzZs;Re(XDZx!OkQ_18E6$OS-$(-VzVIlk68~)ptM-eQU z7#gKLPG$|9PA29cBkIp~UxefXHY|oTVJ`2rqZ#dU>dcMSaPy7QdACT~r{Q{`c_t~8 z80A!JQK`~wmkln9uS)H09VxB1JK&TQsSuj`S_oh5^X-w=odATEI%(_cl+ybXM^FVU zA54*~N%@XTasP`=yKjiLsCt1wF++&e9YJa)y=h?st4 z9X5>$*=J93oliz&XFMvp7ZFM=L}Zr@C&AU+N%datMrn~Yk{kNTIVAD=-)XT>$Ep(ld?qwI0ro{ z2q%YkO4HibtO?U=t3*5*T)(q#q!xMm33_6#e&w!0*`4KSkvZS|v`53Tx&8FAGC4nY zU?o!j>!x#ouuabB%zntp;lp^SesWSr_OTjo)!dWE4TRVYYwM1{*&dU^XP-9j9|>p2 z+~QtGc+D|DPim}=>OP*|1Wc!x>ST2dY6>iD`)<+<2Rk4L`D$A#)CBpVbh!}x`G%)L6 zD1f2G)}RY3torgHwGP2s^}x?Yhk+XP)_&?F!MbMWv-t06wi)U%IaMO%edV(dn1fNA ziX-pd_I8{cq{|O)px%~!Ynxa1aBH5cA3Ohsj)4U&?6C|+hiiWA*$iU*_NIR3;!>=G ze<3jyPyM?^yxT3b+Z&@f2xzqHyk#Ufm%TzreiSy3^N==ln5IP(s;$Z{5gU`UhFm z>+pia01XA@I{%=vpw6J{jayU#`9tplb#y`!T4IayE71CX2B)zy{Dm5&SVXvqx_78d6I(aQL%D+u^6oCCtq?gt72=7!oq zuZcG&ZU7g6`#1L5!vCvL*VsQzg2Ul|b##3XKX36zcf342{MtG%0Grr{P$R0 zD-{?0q1qA(gCfa3xTCl_Qk(jZvHYoxi-%do8isgE|IdcU4vugeDA<`>P>9E#k69XF zZ3p2L5*8E^<^Gq#pB;c5p+C4pP6)^uDvq>KfD^#W$-}G7BMjsh00M-6$^8>23IPLu z3kY)Z@FD-T0m48YULdcaDEIHipFKD@TEm?GQvVlP5C}l3=liAp574!4I}pqg0kVXO zLt&gcT0b=YRrOOV6k_d+oN1h3H!#wZ6i4>@sBFq9#4`Af}^^pE6jQ9TrN$I=dU)VGIyN+_siigS;_C07x6_krlAV(ZGZlfAq#B>EkZ!11X9#urgY$*(-+Lhe5s?^(e5sQi`yzQn@0-o-lHCa-k= zq-IxCOE*#EaTmbrvzj~U(k<+7v6GNf+Qd(9SQa@t@)khoYkEys3TO~CT4m*|Gt+q` zTc*rgA$+`A87Fp6#cEj5CIk~dyQy*O#bf^@K*`+*&|+a^?5;J zNu9Fj62RQK_Tp22p?2j!(%p=k9}2_kp&|Ibjp!+ntGfgW(^eMKqo@oA-$-z~t2^Ww2r$($h0V6-!0tzn`>#jCP*40r2rP>5}B zqFt>$de+XJ)0B^O2C^Mk)Q4&K3}K}U-v)i3m*OW*EptrEsz7$bVqA6a;g-kbkr~b9 zFg0KYwrPDmRC(aaZ)o^Pitr_N;fbJfmRJdyvRK0OE$0N<`l70+o(EH}c1Q?oZpDSL zq@v=AcwAuDyX6@I)s|R?&&g{RX9SZ;_*Fh!XDw+v zT(a!0DXUQ|I?5@7D%<(X(v<#yH&QZGc;jJ!b#`je`vvMv;!SoCW>t36*f6Ij^_OkU z6cYY6w^9jFU2bs?${O-WIPkY`WUFm!H=1F$H-vQcf_cNt!6~rAp{Sh zbmP@9;_t#$F7NJ+hn;lX6u~Ygc_W#|otqsci+e`$m{(ko;k0Qa zy}`T+@ix3_nDo-_OLzS$z`$nq^`<4*v7K3RC(4laZUt^{|I`VRwgsH0B;;U&?3J0S{jJHQN1vWgxyFxDw92Q4|@ILNf%L?R+2gyvUx+aJ$)DNfR3h1Jx4NJ7{cW3YcS5rpU~--$D*Rmrj6*nY|OEZtN(MLZV8 z@{F1|Hd31`-IP3yQl0ClJkZ6SeEhcXRAQR%=i2yEW~}dYeqBN?ugisO%BW;%ZN1oX zP|Dmq!_6z9Gh1is>l2KY$S?h^`lV<)KN$F6J!@uT^B`*ckZd|mE{8at~47J&s|t3wuy zQ7?i3Xt3lN+G$fgWrLOqm#p|;BSFxmd=r1h_qIh{c{*~syFy{b(T4{x&y5dn*4t0s zK6n*;${odxj&Dxoy!|=9spbo7f+TC$*83&savwtht^K^r^E2x<|IFvaO4}ot6154> z*9jJRzfGQXKHHj#x(8zym*tTF;Do$| z3USDcHmbvR5AoRv(Q0e?u#`7N?h7_jfokBwIX;k}J=>LI?u}FI>8Ev@rW-f`HEy0tLq5U4~vl@vj^{LB_izhK4d`7qW@;6~NhS}A%Po;Cz zR*NovFi-y999+MlBXQYqIF& zwCGlb?it3o@Vivc3Bzwss@+^2-(~jA%@}~*jC@1USp1PH;$yY2-p3Vj5qHd-?D=uI z{Z{^PACcw^4|n^cnv?yE{k(7EF>xx{H_7#cQVEUka12mqWiuJ~>9BZu*at-Ep*_;p z5!#p1Dbpgpu{T=My*e2qqYvb@jP5VQSKmz0WRrR1O!77vOPG_aXW5a#ttMduOFVVh zL^h*T;w6c+2i6OU_ub6RN||oD3Rg7p$}At_GHXg&Y|cmXGJK9U<81c8Q?#7H;L$>S zG6T0PB2WEK6JsRM4#F=~KBJULtGK*%vgDH}N zeDmfSi*it$wlv%X9t++xsS^?r>%o}aml?sJ5XL}6?6GGH+yFCB62Y{~@fZ?A?-nT% zvp*%_vU~WBDAOfK;zZFwr5e}C;p3DIUsII88nt6_Vq4-)LavfBr07vtwQ;vs)YNlV zn}la6uqV-chZnqj>EyThgsR>#XS;nxpia-OFs^yWF4w2nO4}~L%N&b6p2XunV-A>; zeUB(~leT!^h-X78k6TSuVP$~^%O&7(;IFD^^~Gzb1MQW9VbAK0jz5v|6m2Dk4Ebu1 zgt={he9zp2Fp`PllDg-Ny4YGgKOb2V$RJnApjP{V&buVAyXb3#zS0qD?3!xv)3)%? z={QG*rc6!iXjD~EKw;vA@KFc7H_sSdZBqbCXKUSK|IBArP)e%JIqAeUkBfLg)?o%Pnsd;OeENTPwOR1Ug+Pg;o zX@$;ymqG&5-Ak^xlji!j&suVhKVH?{Ixni1kovS>FF?!hodEoh&-zk+{hjo}P{r0G zLhruzqBo=aJ!PJ@i7nv*MTejL@cKRt8kJsrbAgA$?F~k{)6#e;6&QPw#DW zXzZ=Iy4acKUAX`}**@G|FzYj%NnGo~IojJ!W*V~-!g|qXZ4^ONIa)rVCH8`jW~}9d zw(ghV^U1XWi>RRLrxkvk?4RN{Ps#hvk37iml0W$gtsSUmMTcPbm)?W` zKw-Z{NPF7KIr>_12LYF8?xxh3vaxFP$4_G)V!u6Gz|8 zeOLK_p|h0(YrO_rYK*gs`X>g6lQ$!wp{H1Cg7NU+IVo9{(ib)KwLIfD75ykKc`w5R z`|`q-YL=65ax&eS!CzB6=@6x;MhbTz)9?#rOU{kmN30P??QzdZs3xLDv0Z(Z>3lzQ9AUdYIEp==4i;!F9XL%LaxQsp zosXgYOg$htV3hflK{Cw07+u|)yxEDFy7Q|by_XpAszeFV0&rEAc%sF}IrMFv87NRhvBNgap|F24GntvK3dnp7_~|K)UF9Ci3Cl@~%7 zHr|(c6e6aHs#|S5#hWp;#p#xMI0^ao!I-;b_tOjQp$$~g7Y+1@+nXKdeggrA2z(b4 zGQ%5As$FNiMp6By6q89s4Q#33$$9`;#9p65gG(;?RjjS@9foYV^Ya^VwVP#&rgJoW zW%u>CYXmJw9Wf|AOOgbtJ{v??GQ2x6_Da)WT#h3IfYwkcEaG0Qj2q-2={{?M297dZ zpswIH&s^six=OUR zNY!9k&)bftK}`UjEm#(5XxH%s^#2p&u5O0YSMAFZw&F zB8&fTu+cyJ{2Pseavg5;cY1~_{tMfBHL-A@%%y8ueT5y8Sv*>fhwo-*WxPP^jzA)oUv3x72Sl z|MW(#zghoIY83zZ3-;ey{#xn7ljr!B_+utqhM(UGnb3JMPL OPaPEn#hLl~>VE)#vui5= diff --git a/branches/lydia/linklist.cpp b/branches/lydia/linklist.cpp deleted file mode 100644 index 4c6d1b4..0000000 --- a/branches/lydia/linklist.cpp +++ /dev/null @@ -1,450 +0,0 @@ -/* C++ Linked list class, threadsafe (boolean is atom) - * - * (c) Copyright 2001-2004 Denis Roio aka jaromil - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * "$Id: linklist.cpp 274 2005-05-04 13:29:10Z kysucix $" - * - ------------------------------------------------------------------------- - linked list container class - - NOTE: add and rem don't take care of deleting pointers - that has to be done by the process that creates them and - knows which inheriting class they are (delete is done in main) -*/ - -#include -#include - -#include -#include - - -Linklist::Linklist() { - length = 0; - first = NULL; - last = NULL; -#ifdef THREADSAFE - pthread_mutex_init(&mutex,NULL); -#endif - -// unlock(); -} - -Linklist::~Linklist() { - clear(); -} - -/* adds one element at the end of the list */ -void Linklist::append(Entry *addr) { - Entry *ptr = NULL; - if(!addr) { - W("Linklist::append called with NULL argument"); - return; - } - if(addr->list) addr->rem(); -#ifdef THREADSAFE - lock(); -#endif - - if(!last) { /* that's the first entry */ - last = addr; - last->next = NULL; - last->prev = NULL; - first = last; - } else { /* add the entry to the end */ - ptr = last; - ptr->next = addr; - addr->next = NULL; - addr->prev = ptr; - last = addr; - } - /* save the pointer to this list */ - addr->list = this; - length++; -#ifdef THREADSAFE - unlock(); -#endif -} - -void Linklist::prepend(Entry *addr) { - Entry *ptr = NULL; - if(addr->list) addr->rem(); -#ifdef THREADSAFE - lock(); -#endif - - if(!first) { /* that's the first entry */ - first = addr; - first->next = NULL; - first->prev = NULL; - last = first; - } else { /* add an entry to the beginning */ - ptr = first; - ptr->prev = addr; - addr->next = ptr; - addr->prev = NULL; - first = addr; - } - addr->list = this; - length++; -#ifdef THREADSAFE - unlock(); -#endif -} - - -// inserts an element after the given one -void Linklist::insert_after(Entry *addr, Entry *pos) { - - // take it out from other lists - if(addr->list) addr->rem(); - -#ifdef THREADSAFE - lock(); -#endif - if(pos->next) { - pos->next->prev = addr; - addr->next = pos->next; - } else last = addr; // it's the last - - addr->prev = pos; - pos->next = addr; - - length++; - addr->list = this; - -#ifdef THREADSAFE - unlock(); -#endif -} - - -/* adds an element at the position specified - if pos is out of bounds adds it at the beginning or the end - the element occupying allready the position slides down - THIS FUNCTION IS NOT YET RELIABLE -*/ -void Linklist::insert(Entry *addr, int pos) { - if(length<=pos) { /* adds it at the end */ - append(addr); - return; - } else if(pos<=1) { - prepend(addr); - return; - } - - if(addr->list) addr->rem(); - - Entry *ptr = pick(pos); - -#ifdef THREADSAFE - lock(); -#endif - ptr->prev->next = addr; - addr->prev = ptr->prev; - - ptr->prev = addr; - addr->next = ptr; - - length++; - addr->list = this; -#ifdef THREADSAFE - unlock(); -#endif -} - -/* clears the list - i don't delete filters here because they have to be deleted - from the procedure creating them. so this call simply discards - the pointers stored into the linked list. OBJECTS ARE NOT FREED */ -void Linklist::clear() { -#ifdef THREADSAFE - lock(); -#endif - sel(0); - length = 0; - first = NULL; - last = NULL; -#ifdef THREADSAFE - unlock(); -#endif -} - -/* takes one element from the list - === STARTING FROM 1 === - returns NULL if called with pos=0 or pos>length - returns Entry pointer otherwise - this function is then overloading the operator[] -*/ -Entry *Linklist::pick(int pos) { - if((lengthnext; - } - - return(ptr); -} - -/* search the linklist for the entry matching *name - returns the Entry* on success, NULL on failure */ -Entry *Linklist::search(char *name) { - Entry *ptr = first; - while(ptr) { - if( strcasecmp(ptr->name,name)==0 ) break; - ptr = ptr->next; - } - return(ptr); -} -/* searches all the linklist for entries starting with *needle - returns a list of indexes where to reach the matches */ -int *Linklist::completion(char *needle) { - register int c; - int found; - int len = strlen(needle); - - /* cleanup */ - memset(compbuf,0,MAX_COMPLETION); - - /* check it */ - Entry *ptr = first; - if(!ptr) return compbuf; - - for( found=0, c=1 ; ptr ; c++ , ptr=ptr->next ) { - if(!len) { // 0 lenght needle: return the full list - compbuf[found] = c; - found++; - } else if( strncasecmp(needle,ptr->name,len)==0 ) { - compbuf[found] = c; - found++; - } - } - - D("completion found %i hits",found); - return compbuf; -} - - -/* this function is a wrapper around Entry::up() - better to use that if you have a pointer to your Entry */ -bool Linklist::moveup(int pos) { - Entry *p = pick(pos); - if(!p) return(false); - return( p->up() ); -} -bool Linklist::movedown(int pos) { - Entry *p = pick(pos); - if(!p) return(false); - return( p->down() ); -} -bool Linklist::moveto(int num, int pos) { - Entry - *p = pick(num); - if(!p) return(false); - return( p->move(pos) ); -} -/* removes one element from the list */ -void Linklist::rem(int pos) { - Entry *ptr = pick(pos); - if(ptr==NULL) return; - ptr->rem(); -} - -/* selects ONLY ONE, deselects the others - use Entry::sel() if you want to do multiple selects */ -void Linklist::sel(int pos) { - int c; - Entry *ptr = last; - - if(pos>length) return; - - for(c=length;c>0;c--) { - if(c==pos) ptr->sel(true); - else ptr->sel(false); - ptr = ptr->prev; - } -} - -/* returns the last one selected - this is supposed to be used with single selections */ -Entry *Linklist::selected() { - int c; - Entry *ptr = last; - for(c=length;c>0;c--) { - if(ptr->select) return ptr; - ptr = ptr->prev; - } - return NULL; -} - -Entry::Entry() { - next = NULL; - prev = NULL; - list = NULL; - data = NULL; - select = false; - strcpy(name,"noname"); -} - -Entry::~Entry() { - rem(); - if(data) free(data); -} - -void Entry::set_name(char *nn) { - strncpy(name,nn,MAX_ENTRY_NAME-1); -} - -bool Entry::up() { - if(!prev || !list) return(false); -#ifdef THREADSAFE - list->lock(); -#endif - - Entry *tprev = prev, - *tnext = next, - *pp = prev->prev; - - if(!next) - list->last = prev; - - if(tnext) - tnext->prev = tprev; - - next = tprev; - prev = pp; - tprev->next = tnext; - tprev->prev = this; - - if(pp) - pp->next = this; - - if(!prev) - list->first = this; - -#ifdef THREADSAFE - list->unlock(); -#endif - return(true); -} - -bool Entry::down() { - if(!next || !list) return(false); -#ifdef THREADSAFE - list->lock(); -#endif - - Entry *tprev = prev, - *tnext = next, - *nn = next->next; - - if(!prev) - list->first = next; - - if(tprev) - tprev->next = tnext; - - prev = tnext; - next = nn; - tnext->prev = tprev; - tnext->next = this; - if(nn) - nn->prev = this; - - if(!next) - list->last = this; - -#ifdef THREADSAFE - list->unlock(); -#endif - return(true); -} - -bool Entry::move(int pos) { - D("Entry::move(%i) - NEW LINKLIST MOVE, TRYING IT..."); - if(!list) return(false); -#ifdef THREADSAFE - list->lock(); -#endif - - Entry *tn, *tp; - - Entry *swapping = list->pick(pos); - if(swapping == this) return(true); - if(!swapping) return(false); - - tn = swapping->next; - tp = swapping->prev; - - swapping->next = next; - swapping->prev = prev; - if(next) next->prev = swapping; - else list->last = swapping; - if(prev) prev->next = swapping; - else list->first = swapping; - - next = tn; - prev = tp; - if(next) next->prev = this; - else list->last = this; - if(prev) prev->next = this; - else list->first = this; - -#ifdef THREADSAFE - list->unlock(); -#endif - D("LINKLIST MOVE RETURNS SUCCESS"); - - return(true); -} - -void Entry::rem() { - bool lastone = false; - if(!list) return; -#ifdef THREADSAFE - list->lock(); -#endif - - if(next) { // if there is a next - next->prev = prev; // link it to the previous - next->select = select; // inherit selection - } else { - list->last = prev; // else just make it the last - lastone = true; - } - - if(prev) { // if there is a previous - prev->next = next; // link it to the next - if(lastone) prev->select = select; - } else list->first = next; // else just make it a first - - list->length--; -#ifdef THREADSAFE - list->unlock(); -#endif - - list = NULL; -} - -void Entry::sel(bool on) { - select = on; -} diff --git a/branches/lydia/linklist.h b/branches/lydia/linklist.h deleted file mode 100644 index db030e5..0000000 --- a/branches/lydia/linklist.h +++ /dev/null @@ -1,110 +0,0 @@ -/* C++ Linked list class, threadsafe (boolean is atom) - * - * (c) Copyright 2001 Denis Roio aka jaromil - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __linklist_h__ -#define __linklist_h__ - - -// uncomment to have mutex locked operations -// can be slow on OSX and adds dependency to pthreads -//#define THREADSAFE 1 -#ifdef THREADSAFE -#include -#endif - -// maximum lenght of names -#define MAX_ENTRY_NAME 512 - -// maximum number of members returned by the completion -#define MAX_COMPLETION 256 - -class Entry; - -class Linklist { - public: - Linklist(); - virtual ~Linklist(); - - Entry *begin() { return(first); }; - Entry *end() { return(last); }; - int len() { return(length); }; - - void append(Entry *addr); - void add(Entry *addr) { append(addr); }; /* lazy backward compatibility */ - void prepend(Entry *addr); - void insert(Entry *addr, int pos); - void insert_after(Entry *addr, Entry *pos); - void rem(int pos); - void sel(int pos); - void clear(); - bool moveup(int pos); - bool movedown(int pos); - bool moveto(int num, int pos); - Entry *pick(int pos); - Entry *search(char *name); - int *completion(char *needle); - - Entry *Linklist::selected(); - - Entry *operator[](int pos) { return pick(pos); }; - - /* don't touch these directly */ - Entry *first; - Entry *last; - int length; - - -#ifdef THREADSAFE - pthread_mutex_t mutex; - void lock() { pthread_mutex_lock(&mutex); }; - void unlock() { pthread_mutex_unlock(&mutex); }; -#endif - - int compbuf[MAX_COMPLETION]; // maximum completion listsize allowed - -}; - -class Entry { - friend class Linklist; - - public: - Entry(); - ~Entry(); - - void set_name(char *nn); - - Entry *next; - Entry *prev; - - Linklist *list; - - bool up(); - bool down(); - bool move(int pos); - void rem(); - void sel(bool on); - - bool select; - - char name[MAX_ENTRY_NAME]; - - void *data; ///< generic data pointer -}; - -#endif diff --git a/branches/lydia/parport.cpp b/branches/lydia/parport.cpp deleted file mode 100644 index bef8334..0000000 --- a/branches/lydia/parport.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Parallel port controller - * - * parallel port I/O by Harry - * C++ interface by Jaromil - * - * (c) Copyright 2004-2006 Harry & Jaromil - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * to compile this sourcecode: gcc -o ivysync ivysync.c -lpthreads - * it should work on any POSIX system, including embedded hardware - * wherever the IvyTV drivers can also run (see http://ivtv.sf.net) - * - */ - -#include -#include -#include - -#include -#include - -#define BASEPORT 0x378 /* lp1 */ - -ParPort::ParPort() - : Thread() { - - quit = false; - button_state = false; - -} - -ParPort::~ParPort() { - if( ioperm(BASEPORT, 3, 0) ) - E("error closing parallel ports"); -} - -bool ParPort::init() { - - if( ioperm(BASEPORT, 3, 1) ) { - E("error accessing parallel ports"); - return false; - } - - N("Parallel port initialized"); - return true; - -} - -void ParPort::run() { - int status; - - A("Parallel port polling started"); - - while(!quit) { - - jsleep(0,100); // sleep for a while - - // Read from the status port (BASE+2) - status = inb(BASEPORT + 1); - - if( status == 88 ) - button_state = true; - - } - -} - -int ParPort::light(bool state) { - if(state) { - // Set the data signals (D0) of the port to high (255) - outb(255, BASEPORT); - D("switch light on"); - } else { - // Set the data signals (D0-7) of the port to all low (0) - outb(0, BASEPORT); - D("switch light off"); - } - return state; -} - -int ParPort::button_reset() { - button_state = false; - return 1; -} - -int ParPort::button_is_pressed() { - if(button_state) return 1; - else return 0; -} diff --git a/branches/lydia/parport.h b/branches/lydia/parport.h deleted file mode 100644 index 76ab0d6..0000000 --- a/branches/lydia/parport.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Parallel port controller - * - * parallel port I/O by Harry - * C++ interface by Jaromil - * - * (c) Copyright 2004-2006 Harry & Jaromil - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * to compile this sourcecode: gcc -o ivysync ivysync.c -lpthreads - * it should work on any POSIX system, including embedded hardware - * wherever the IvyTV drivers can also run (see http://ivtv.sf.net) - * - */ - -#ifndef __PARPORT_H__ -#define __PARPORT_H__ - -#include - -class ParPort : public Thread { - - public: - ParPort(); - ~ParPort(); - - bool init(); - void run(); - - int light(bool state); // switch light on/off - - int button_reset(); // reset button to un-pressed state - int button_is_pressed(); // returns true if the button was pressed - - private: - - bool button_state; - -}; - - -#endif diff --git a/branches/lydia/pipe.cpp b/branches/lydia/pipe.cpp deleted file mode 100644 index 7279b4f..0000000 --- a/branches/lydia/pipe.cpp +++ /dev/null @@ -1,386 +0,0 @@ -/* - Copyright (c) 2001 Charles Samuels - Copyright (c) 2002 - 2004 Denis Rojo - -this pipe class was first written by Charles Samuels -and then heavily mutilated and optimized by Denis "jaromil" Rojo - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public License -along with this library; see the file COPYING.LIB. If not, write to -the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. - -"$Id: pipe.cpp 759 2006-03-16 23:35:57Z xant $" - -*/ - -#include -#include -#include -#include - -#include -#include - - -#define MIN(a,b) (a<=b) ? a : b; - -#define _SIZE(val) \ - if ((char*)end > (char*)start) \ - val = (char*)end-(char*)start; \ - else if((char *)end == (char *)start && (char *)start == (char *)buffer) \ - val = 0; \ - else \ - val = ((char*)bufferEnd-(char*)start)+((char*)end-(char*)buffer); - -#define _SPACE(val) \ - _SIZE(val); \ - val = ((char*)bufferEnd-(char*)buffer)-val; - -// COPY AND MIX CALLBACKS -// they provide function that are moving data -// handling it in different ways. it is an optimization when we do -// conversions while copying the buffer around, or mixing it directly -// from the pipe to a buffer. - -// samples are double if stereo (1 sample is only left or right) -// multiplying them by the samplesize we can obtain sizes in bytes - -static inline void copy_byte(void *dst, void *src, int samples) { - memcpy(dst,src,samples); - } - -static inline void copy_int16_to_float(void *dst, void *src, int samples) { - register int c; - for( c = samples-1; c>=0 ; c-- ) { - ((float*)dst)[c] = ((int16_t*)src)[c] / 32768.0f; - } -} - -static inline void copy_float_to_int16(void *dst, void *src, int samples) { - register int c; - for( c = samples-1; c>=0 ; c-- ) { - ((int16_t*)dst)[c] = (int16_t) ( ((float*)src)[c]*32768.0f); - } -} - -static inline void mix_int16_to_int32(void *dst, void *src, int samples) { - register int c; - for( c = samples-1 ; c>=0 ; c-- ) { - ((int32_t*)dst)[c] - += - ((int16_t*)src)[c]; - } -} - -///// now register all the copy callbacks functions -// // this is also a list for the available types - -static struct pipe_copy_list callbacks[] = { - { "copy_byte", copy_byte, 1, 1 }, - { "copy_int16_to_float", copy_int16_to_float, sizeof(int16_t), sizeof(float) }, - { "copy_float_to_int16", copy_float_to_int16, sizeof(float), sizeof(int16_t) }, - { "mix_int16_to_int32", mix_int16_to_int32, sizeof(int16_t), sizeof(int32_t) }, - { 0, 0 } -}; - -/* - start is a pointer to the first character that goes out - end is a pointer to the last character to go out -*/ - -bool Pipe::set_input_type(char *name) { - int c; - for(c=0 ; callbacks[c].callback ; c++) { - if(strcasecmp(name,callbacks[c].name)==0) { - write_copy_cb = &callbacks[c]; - return true; - } - } - E("can't set input type \"%s\" on pipe",name); - return false; -} - -bool Pipe::set_output_type(char *name) { - int c; - for(c=0 ; callbacks[c].callback ; c++) { - if(strcasecmp(name,callbacks[c].name)==0) { - read_copy_cb = &callbacks[c]; - return true; - } - } - E("can't set output type \"%s\" on pipe",name); - return false; -} - - -Pipe::Pipe(int size) { - D("Pipe::Pipe(%i)",size); - pipesize = size; - buffer = calloc(pipesize, 1); - if(!buffer) - E("FATAL: can't allocate %i bytes buffer for audio Pipe: %s", - pipesize, strerror(errno)); - bufferEnd=(char*)buffer+size; - end=start=buffer; - - // set default types to simple bytes - set_input_type("copy_byte"); - set_output_type("copy_byte"); - // set blocking timeout (ttl) defaults - /* default blocking time is 50 millisecs - * check read() and write() methods for implementation */ - read_blocking = false; - read_blocking_time = 50000; - write_blocking = false; - write_blocking_time = 50000; - _thread_init(); - sleep_time = 150; /* defaults to 150 microsecs */ - //unlock(); - -} - -Pipe::~Pipe() { - D("Pipe::~Pipe : freeing %p",buffer); - lock(); - free(buffer); - unlock(); - // _thread_destroy(); -} - -void Pipe::set_block(bool input, bool output) { - lock(); - write_blocking = input; - read_blocking = output; - unlock(); -} - -void Pipe::set_block_timeout(int input, int output) { - lock(); - write_blocking_time = input; - read_blocking_time = output; - unlock(); -} - -int Pipe::read(int length, void *data) { - int worklen, origlen, truelen; - int blk, len, buffered, buffered_bytes; - int ttl = 0; - - if(read_blocking) ttl = read_blocking_time; - - lock(); - - _SIZE(buffered_bytes); - buffered = buffered_bytes - / read_copy_cb->src_samplesize; - truelen = length; - - - while(bufferedsrc_samplesize; - } else { - // nothing in the pipe - if(!buffered) { - unlock(); - return 0; - } else - truelen = buffered; - break; - } - } - - origlen = worklen = truelen * read_copy_cb->src_samplesize; - - while (worklen) { - - /* |buffer*****|end-----------|start********|bufferEnd - |buffer-----|start*********|end----------|bufferEnd */ - - len = MIN(worklen,buffered_bytes); - - blk = ((char*)bufferEnd - (char*)start); - - blk=MIN(blk,len); - - /* fill */ - (*read_copy_cb->callback) - (data, start, - blk / read_copy_cb->src_samplesize); - /* blank just copied bytes */ - //memset(start,0,blk / read_copy_cb->src_samplesize); - - start = &((char*)start)[blk]; // (char*)start += blk; - len -= blk; - data = &((char*)data)[blk]; // (char*)data += blk; - worklen -= blk; - if ((end!=buffer) && (start==bufferEnd)) - start = buffer; - - if (len) { /* short circuit */ - - (*read_copy_cb->callback) - (data, start, - len / read_copy_cb->src_samplesize); - - // /* blank just copied bytes */ - // memset(start,0,len / read_copy_cb->src_samplesize); - data = &((char*)data)[len]; // (char*)data += len; - start = &((char*)start)[len]; // (char*)start += len; - worklen -= len; - if ((end!=buffer) && (start==bufferEnd)) - start = buffer; - } - } - if (start == end) /* if this read emptied buffer */ - start = end = buffer; /* reset pointers to le _SIZE behave correctly */ - - unlock(); - return ( (origlen-worklen)/read_copy_cb->src_samplesize ); -} - -int Pipe::write(int length, void *data) { - int worklen, origlen, space_samples; - int space_bytes, len, truelen, blk; - int ttl = 0; - - if(write_blocking) ttl = write_blocking_time; - - lock(); - - _SPACE(space_bytes); - space_samples = (space_bytes / write_copy_cb->dst_samplesize); - truelen = length; - - while(length > space_samples) { - - // timeout block mechanism - if(write_blocking) { - unlock(); - if(!ttl) { - return -1; // block timeout - } - jsleep(0,sleep_time*1000); ttl -= sleep_time; - lock(); - // recalculate actual sizes - _SPACE(space_bytes); - space_samples = space_bytes - / write_copy_cb->dst_samplesize; - - } else { // non-block - - if(!space_bytes) { - unlock(); - return 0; // nothing in the pipe - } else - // write what's available - truelen = space_samples; - break; - } - } - - origlen = worklen = truelen * write_copy_cb->dst_samplesize; - - while (worklen) { - - /* |buffer-----|end***********|start--------|bufferEnd - |buffer*****|start---------|end**********|bufferEnd */ - len=MIN(worklen, space_bytes); - - blk = (char*)bufferEnd-(char*)end; - blk = MIN(blk, len); - - /* fill */ - (*write_copy_cb->callback) - (end, data, - blk / write_copy_cb->dst_samplesize); - - end = &((char*)end)[blk]; // (char*)end += blk; - len -= blk; - data = &((char*)data)[blk]; // (char*)data += blk; - worklen -= blk; - if ((start!=buffer) - && (end==bufferEnd)) - end = buffer; - - if (len) { // short circuit - - (*write_copy_cb->callback) - (end, data, - len / write_copy_cb->dst_samplesize); - - data = &((char*)data)[len]; // (char*)data += len; - end = &((char*)end)[len]; // (char*)end += len; - worklen -= len; - - if ((start!=buffer) - && (end==bufferEnd)) - end = buffer; - } - } - _SPACE(space_bytes); - unlock(); - return ((origlen-worklen) / write_copy_cb->dst_samplesize); -} - -// |buffer******|end--------------|start**************|bufferEnd -// |buffer-----|start**************|end---------------|bufferEnd -int Pipe::size() { - int res; - /* size macro allocates the result variable by itself */ - lock(); - _SIZE(res); - unlock(); - - return res; -} - -// |buffer------|end**************|start--------------|bufferEnd -// |buffer*****|start--------------|end***************|bufferEnd -int Pipe::space() { - int res; - lock(); - _SPACE(res); - unlock(); - - return res; -} - -void Pipe::flush() { - lock(); - bufferEnd=(char*)buffer+pipesize; - end=start=buffer; -// memset(buffer,0,pipesize); - unlock(); -} - -void Pipe::flush(int bytes) { - lock(); - void *temp = malloc(bytes); - read(bytes, temp); - free(temp); - unlock(); -} diff --git a/branches/lydia/pipe.h b/branches/lydia/pipe.h deleted file mode 100644 index 0d2b758..0000000 --- a/branches/lydia/pipe.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - Copyright (c) 2001 Charles Samuels - Copyright (c) 2002-2004 Denis Rojo - - this pipe class was first written by Charles Samuels - and almost completely rewritten by Denis "jaromil" Rojo - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - $Id: pipe.h 760 2006-03-16 23:37:40Z xant $ - -*/ - -/** - @file pipe.h - @brief Buffered and threadsafe FIFO pipe -*/ - -#ifndef __PIPE_H__ -#define __PIPE_H__ - -#include -#include -#include - -/** - This class defines the implementation of the FIFO (first in, first out) - buffered threadsafe pipe. This component is massively used in MuSE's - flow of audio data, connecting the Channel to the Stream_mixer and then - to the OutChannel. - - This Pipe implementation is fairly well tested and optimized, usesu - pthread mutexes for fast atomical locking and has a mixing routine - embedded for for reading data from the pipe. - - When an application locks the Pipe, will be waiting until it reaches - to gain the lock, then will (pthread_mutex_lock) - - This pipe is never blocking, meaning that it never makes the calling - process wait for result. The Pipe::blocking attribute of this class - has to be intended in a different way. - - Blocking means that the Pipe::read, Pipe::write and derivative - functions will be returning -1 without moving any data, in case - the aumount of data requested don't fit for pipe buffers. - - Non-blocking means that the Pipe::read, Pipe::write and derivative - functions will move all the data they can move, even if less than - requested, and then return the amount of data moved. - - I know, the above might sound weird, just because i used the word - 'blocking' where i shouldn't. i beg your pardon and plan to change - it in future. - - @brief fast buffered threadsafe FIFO pipe -*/ - -/** this function prototype is used in the callbacks that are handling - the phisical copying of the memory. they are various functions - statically implemented in pipe.cpp */ -typedef void (pipe_copy_f)(void *src, void *dst, int samples); - -/** this is the prototype struct holding the list of available types */ -typedef struct pipe_copy_list { - char *name; - pipe_copy_f *callback; - int src_samplesize; - int dst_samplesize; -}; - -class Pipe { -public: - -/** - The constructor initializes all buffers needed, which will be - in fact the size of the buffer */ - Pipe(int size=16384); - ///< Pipe constructor class - - ~Pipe(); - ///< Pipe destructor class - - /** - A Pipe can be of different types, meaning that it does different - kind of operations when reading or writing like: conversions, - mixing of various kinds, all opearations that we can optimize when - doing in one single pass, while data is flowing around. - Implementations of the various types available can be obtained - looking into pipe.cpp when the copy callback functions are registered. - The set_input_type and set_output_type methods are used to set which - kind of operation the Pipe will execute when moving in and out the - data. - Default is "copy_byte" which simply copies one byte each sample, - you want to change this to set it to the sample type you are using - - types available: - * copy_byte - * copy_int16_to_float int to float using /32768.0f - * copy_float_to_int16 float to int using lrintf() - * mix_int16_to_int32 simple sum of 16bit over 32bit int - - */ - bool set_input_type(char *name); - ///< set the input conversion type for this Pipe - bool set_output_type(char *name); - ///< set the output conversion type for this Pipe - - void set_block(bool input, bool output); - ///< set the blocking policy on the read and write - void set_block_timeout(int input, int output); - ///< set the timeout in milliseconds for the read and write block - - /** - Reads out audio data from the pipe filling up the given buffer - which has to be properly allocated. - - If the pipe is set 'blocking' then will return -1 if the pipe - buffer is full. Otherwise, when non-blocking, will return the - amount of data that could be pushed in the pipe. - - @brief FIFO read from pipe - @param length amount of data to be read in bytes - @param data buffer pointer where to read data, must be allocated allready - @return amount of data read, or -1 on error, if Pipe::blocking is true */ - int read(int length, void *data); - ///< read from the pipe - - /** - This function is used to read from the pipe directly into a stereo - interpolated float audio buffer, which is the ideal input for the - secret rabbit code resampler. - - @brief read from FIFO pipe in a float stereo interpolated l/r array - @param samples amount of data to be read in samples (1= l&r float) - @param buf float buffer to be filled, must be allocated allready - @param channels number of channels (1=mono, 2=stereo) - @return amount of data read, or -1 on error, if Pipe::blocking is true - */ - - // int read_float_intl(int samples, float *buf, int channels); - - /** - Read from FIFO pipe in a float bidimensional array. - It is convenient to read float data for float routines, - this one reads into a bidimensional buffer. - TAKE CARE THIS FUNCTION IS NOT WELL TESTED - i never use it in MuSE i just did it together with the _intl - - */ - // int read_float_bidi(int samples, float **buf, int channels); - ///< read from the pipe into a bidimensional float array - - /** - Mixes the audio in the pipe into a given audio buffer. - Assumes that the audio buffered is 16bit stereo. - This implements the core mixing routine used in Stream_mixer::cafudda. - - @brief Mix audio from FIFO pipe into a mixing buffer - @param samples number of samples to be mixed (1= l&r 16bit) - @param mix 32bit integer mixing buffer - @return amount of samples mixed */ - // int mix16stereo(int samples, int32_t *mix); - - // int peek(int length, void *data, bool block=true) const; // TODO - - /** - Write data inside the FIFO pipe, locking to not overlap read - operations (thread safe). - - @brief write into FIFO pipe - @param length amount of bytes of data to be written - @param data buffer from where to take the data to be written - @return when Pipe::blocking is set, this functions returns -1, otherwise - the amount of data written. - */ - int write(int length, void *data); - - /** - Thread safe write data inside the FIFO pipe, like the main write(). - In one pass does a conversion over the data being written, from - - @param length amount of bytes of data to be written - @param data buffer from where to take the float data to be converted and written - @return the amount of data written - */ - // int write_float2int(int length, void *data); - - /** - Thread safe write data inside the FIFO pipe, like the main write(). - In one pass does a conversion over the data being written, from - int to float using casting. - @param length amount of bytes of data to be written - @param data buffer from where to take the int data to be converted and written - @return the amount of data written - */ - // int write_int2float(int length, void *data); - - /** - @brief Setup blocking behaviour of the Pipe. - - The term 'blocking' here is used in a quite improper way, read more - about in the description of the Pipe class. */ - void block(bool val); - - bool blocking; - - /** - @brief tell the amount of data contained in the Pipe - @return amount in bytes */ - int size(); - - /** - @brief tell the amount of free space in the Pipe - @return amount in bytes */ - int space(); - - void flush(); ///< flush all data contained in the Pipe, loosing it - - void flush(int size); - ///< flush a certain amount of bytes from FIFO Pipe - - private: - pthread_mutex_t _mutex; - void _thread_init() { pthread_mutex_init (&_mutex,NULL); }; - void _thread_destroy() { pthread_mutex_destroy(&_mutex); }; - void lock() { pthread_mutex_lock(&_mutex); }; - void unlock() { pthread_mutex_unlock(&_mutex); }; - - void *buffer; - void *bufferEnd; - void *start; - void *end; - - pipe_copy_list *read_copy_cb; - pipe_copy_list *write_copy_cb; - - int pipesize; - bool read_blocking; - bool write_blocking; - int read_blocking_time; - int write_blocking_time; - unsigned int sleep_time; -}; - -#endif diff --git a/branches/lydia/portaudio/LICENSE b/branches/lydia/portaudio/LICENSE deleted file mode 100644 index 105da3f..0000000 --- a/branches/lydia/portaudio/LICENSE +++ /dev/null @@ -1,65 +0,0 @@ -Portable header file to contain: -/* - * PortAudio Portable Real-Time Audio Library - * PortAudio API Header File - * Latest version available at: http://www.audiomulch.com/portaudio/ - * - * Copyright (c) 1999-2000 Ross Bencina and Phil Burk - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * Any person wishing to distribute modifications to the Software is - * requested to send the modifications to the original developer so that - * they can be incorporated into the canonical version. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - - -Implementation files to contain: -/* - * PortAudio Portable Real-Time Audio Library - * Latest version at: http://www.audiomulch.com/portaudio/ - * Implementation - * Copyright (c) 1999-2000 - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * Any person wishing to distribute modifications to the Software is - * requested to send the modifications to the original developer so that - * they can be incorporated into the canonical version. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ \ No newline at end of file diff --git a/branches/lydia/portaudio/Makefile b/branches/lydia/portaudio/Makefile deleted file mode 100644 index eea546f..0000000 --- a/branches/lydia/portaudio/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# makefile written for gnu make -CXX = g++ -CXXFLAGS = -Wall -ggdb -VERSION = 19 -LIB = ./libportaudio.a - - -# Add your system-dependent network libs here. These are -# only used to build the tests (your application will need them too). -# Linux: none -# Solaris: -lsocket -lnsl -#SYSTEMLIBS = -lsocket -lnsl -SYSTEMLIBS = -LDLIBS = $(LIB) $(SYSTEMLIBS) - -OBJ = pa_convert.o pa_lib.o pa_trace.o pa_unix.o pa_unix_oss.o - - -all: $(LIB) - -$(LIB): $(OBJ) - $(AR) $(ARFLAGS) $(LIB) $(OBJ) - -doc doxygen: - doxygen Doxyfile - -distclean: clean - -clean: - rm -f *.o - rm -f *~ - rm -f $(LIB) - diff --git a/branches/lydia/portaudio/README b/branches/lydia/portaudio/README deleted file mode 100644 index d1e5d7d..0000000 --- a/branches/lydia/portaudio/README +++ /dev/null @@ -1,81 +0,0 @@ -README for PortAudio -Implementations for PC DirectSound and Mac SoundManager - -/* - * PortAudio Portable Real-Time Audio Library - * Latest Version at: http://www.portaudio.com// - * - * Copyright (c) 1999-2000 Phil Burk and Ross Bencina - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * Any person wishing to distribute modifications to the Software is - * requested to send the modifications to the original developer so that - * they can be incorporated into the canonical version. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -PortAudio is a portable audio I/O library designed for cross-platform -support of audio. It uses a callback mechanism to request audio processing. -Audio can be generated in various formats, including 32 bit floating point, -and will be converted to the native format internally. - -Documentation: - See "pa_common/portaudio.h" for API spec. - See docs folder for a tutorial. - Also see http://www.portaudio.com/docs/ - And see "pa_tests/patest_saw.c" for an example. - -For information on compiling programs with PortAudio, please see the -tutorial at: - - http://www.portaudio.com/docs/pa_tutorial.html - -Important Files and Folders: - pa_common/ = platform independant code - pa_common/portaudio.h = header file for PortAudio API. Specifies API. - pa_common/pa_lib.c = host independant code for all implementations. - - pablio = simple blocking read/write interface - -Platform Implementations - pa_asio = ASIO for Windows and Macintosh - pa_beos = BeOS - pa_mac = Macintosh Sound Manager for OS 8,9 and Carbon - pa_mac_core = Macintosh Core Audio for OS X - pa_sgi = Silicon Graphics AL - pa_unix_oss = OSS implementation for various Unixes - pa_win_ds = Windows Direct Sound - pa_win_wmme = Windows MME (most widely supported) - -Test Programs - pa_tests/pa_fuzz.c = guitar fuzz box - pa_tests/pa_devs.c = print a list of available devices - pa_tests/pa_minlat.c = determine minimum latency for your machine - pa_tests/paqa_devs.c = self test that opens all devices - pa_tests/paqa_errs.c = test error detection and reporting - pa_tests/patest_clip.c = hear a sine wave clipped and unclipped - pa_tests/patest_dither.c = hear effects of dithering (extremely subtle) - pa_tests/patest_pink.c = fun with pink noise - pa_tests/patest_record.c = record and playback some audio - pa_tests/patest_maxsines.c = how many sine waves can we play? Tests Pa_GetCPULoad(). - pa_tests/patest_sine.c = output a sine wave in a simple PA app - pa_tests/patest_sync.c = test syncronization of audio and video - pa_tests/patest_wire.c = pass input to output, wire simulator diff --git a/branches/lydia/portaudio/libportaudio.a b/branches/lydia/portaudio/libportaudio.a deleted file mode 100644 index dc90eaf3bf6adf8bac63e9f44be4be8b2961e42d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30716 zcmc(I4_w^UmG6%M6cr09D%Pl@Nh+xkiDE<(bs+p=(&i6IKvNCk1cpEa24N^@bI(2Z-gEz-dvp1GZ%2L8EoWZiPX6Z1nLFqDQv8&;-6ay_{B^q# zju3wLoM{-wb%v33IPrJkkYW5K{^lJtjK9X;x-7$(`mf5nz~8pP*Ab{&4Df2XfAQ0-mY;xpR<9h-IF?cSE=25-Q( z%G=uB;#&z9Lh6>c``T6oI(*(%Vz>DMR`9Ck&r7gyON5iU(%0w>wgeKMW*e_+qz(jx1+K-(B$hNp9S8Q78Sm@Eih*;{T8=12bxg`R?ez@9j(o6Rw+o~ zE$&PZF!j0>L0`w_O5cWN6ftliDsO4=*CWzGZ)aesuhpL@-h~~$WZ$|4{$N`m5ubU3 zEWVC5Z;R#2MBr&5i`yFgwuh9ksDKKrOb)UX!4YQV02x$tOPkx41zRhEjg7tzTll29 zmKe#^D_&B4wxT7xv_d9)%(ivSZLCG*6{p3Iq*K#5ni_%i^OGfv5I1$zoXSFMIdd+SxPBEj_%yY@4}cVMay?ltfoyuc`tm^6c*Gok zHn%ZszBkbN-fOiV4783%YVsQ+<_C>oSH#TSH{{ANb0TIzZ-LQk=4a&hniFv&_T86X z6z=)S+=Gfcx-sGY9vHnR?8gRL$Bx#HBa!W0<3@KpzNHW;ht1LLU8C`BhS3F1;)tCN z2MHqPXxOAMpgW-~Atg&;k}P?>e+MCkC*tvV)zPdOy$v(62C{Q3xoVMXDTQ3YkC@{F zwPOS3*g)6Y5cq8ocx0e;b6@$N0>TM8EH8r>$^1uZi~yP#Z2+BKyFy=iMHulE6PN~x*YmNd3z zl?Z+k&4OqmCeUBAG84 zGvnYM>g!H)A61epi|^z)cs6|wKBKg^+G5p}PJ12P9o=tg5q(=FP>|G=^LoDt&PXI; zgwdhlU-oKv{3iO^(0d2WfGc*E4jajx zj&$tro|4$nnuM~ZbV4^Ejicy<8mu&uO8Erkuy0a9=OE{yuCc7ZM*eO*AHNxSJ>6gn zmn*O+T8@zuPIq7iem#NgXbC*fX@VZ&@Dhz=iOjRA0AZKhN~O zEP?q(ATQKaUdG|& zw^JyTEefu}6O=MG$6_84wTfCkk{ekHZ;L1^?>iL*>>}gOu+$-{xLF;Pc{@uhekgRn z4e!vVLSySJsoCj7Ey)9C!5#6e4x4EH5i=h!Vvb-|qw5&;Q$nWgP4V^yab(4VqfDt{ zwy?HpQwinCdJah%E300c%?Vh}V0pu<`v&h~M4cdXaMTFgFgYWIRz_G+@nAladWJQK z)FRtipeiHK9aK2*KgSo!Uxra;Ou((70bGB5bsi8_NSHB^fQB(&NFVH9_6ZVhKeukMT*DgTI*yN6#UjTdgS+Ds*&Tg+J1tjIIPUeD<3wQLM}{A|PMgC~oy z5PvL}eEhMTbY9^!8uAR|97jaWk73Tw>7Ql1!|8Jf;KUaIvSWW%;f;Xo$~P%|2O!6&r3(LhK#mS|3THfyB41GWAwUi?|5M@b z0&-aS8-?eCHwVKSg;JRzEJ7jGWrS-2{(9+EPiKzqat*7)PlY%9=I+b{O&Sg`0pFo&037eFd zBadZulR_a%*$E`6VYovS!B0RB^6Rd3&^r=GF{c!y5T{|b%Gctn4{&?a!70r~pDyi> zv1bZBnTEd%=;-Ga%z~P@&^eq7NdGGod{+7ISNOjvcrDr!>9#5Os)Bc;9g$B9Aj7vP zn1%Ku`~ii(f)6P88wFoia0TL$ZjXYeqrDI>RPa*@-k{(r1^-#WTTTZ(WV%Dab_K%< z_AB_Bf^RGMCk0PKdt&^H75ubPFSc=5^%@I;znlsNV=voQbTksRh zCx6f^JT}8MSUVIkhaxq{x4#bhZJ6PNYbFNG@j-Jmv8*~5n+=hg35&JNnTC7K5$u#b z5iy7LJh=eVoOm!t7Ui7X$}+_WV*h0H_n6d1pAkXELYwmALF}T8MLY$A#-N!y@Ul+m zBFi__mm>k%+ZDqKVDw#1jQx?Nm>Xm6n;*^yugHq6#_UOEtYh(ZOr!8yu$S3Gr#pJ< z$|@yGp|vbAHrsrzjMNrHmSP4uuFInwdw{NpE3z^xoEct~Wlvb0v)R&qbDZ4m3Hkic z(8P|u0J3;|j9I)7dLHV^kxU=|kUn+dQ)mdyD1DZSPm#lCp7`V%o6ik(O*1x=n-th| z_)8AvnbWrBDp&4SSInl!keK<#HpFxr+vxue(}+T6ImO;|v(!mJqE5IIV{FDm7&|Y= zqx(Py=f0s#&VsSl+BQ?OctTj@8(VFryWyjXg>ow1Gp6G0bMPJ!@oe6o5#DYG?=s;n zx*F>8SmpNtb8;C;M{=7UL9r)N;v&-`dY?oepgRhUWC_uFOrpm%CF-}|Fy~%b7^%Uo zTxqx>OB`k43bYjXc)}I4#ZeiqC=thua7B?g3c?jL#4#;g;T8v0fYZd0AFe16hdW$h zah@NpC>=Cs529;I>_%K5KIjpQgoaDqjZu}O>|0snTiYT_AqwOu376-FSLB0rxCV`~ zH19iHqa4GED%5v+*gO*II$~_j3YkYvkC;dHjb|eKSfpksTu~jV9p@Uu9FMnG>%4~- zV2v>z+Eit&E2W^m4PjU&o+=8;O4)jEYUtAVvQs9HHp+$OX{nQ;CW~+Og(m;B)wXaW>;ZXlj7KP|(@i5) z$*=CUPzI>J)kY$GjfAh(WsGQ|@{W?kwgn0k<)Y=nb_RPL-6@H9(H&BDln|A#`%A+J zmp6o0G)byhqhB;h-cZ+sfjYweA>_gWdrFEcri#h}V#RU!oh)b$GQ;A}8NLMJ7(P@6 z#6N@nY+DI`eH@aUu}48;6}`&EHuQ8N>^4_y8j`?R;V3QCfyz^b&h?Z;*j&6sXB;El zWKJnXxh4F!-6G9+e|HZY{3d6bV+9IjT(ssw5q&}mZ$eixE6E(!rD0_bhfHixc|Dh* z4^hZAFB}{;@_ODtQVQ8N8x9T$c|AY2dR#21$p4R z4F0<1Lpk$$4knOommz^aitpo=uOJUR0wfx?eEuZCPdSkL|GS0!SwbEHBJDgo%Eb&+ zmg}47-&*cMx~Z}7p8*it0*8l=PB^$ai>-&Fi4HFu8|YXK$8I{7!$A#?ErjFebleQb zARQRZCr0VG3XVKvKXwHiT;|0tg5w4{csjF!4(<#3;L!Vmp%L^ZsJycVv%BFvSUVak zw5ksjkzL*38}V$hCQO)0CDorOUEpjGZZG5D6qE_hIHKr=;jHpU>EGOUea}Cgm3?ph zMROk`{wOBMNuI=oGQ5A^2j@!gzVUN=vs~KFFz^cbgq%t^9{I=J=v|3jX3FdxpfydUkY`-gdN`=#H5Qm(l2EMity{o>*4A* zdXMmV$(`5p1B=L$*Rv6&7QIce^;Cs12j%7*93zRj*F5uhUg!!T8tu)c5*QKAS4VMP zi)r9%S+0TXonVAb`)L>T;)vCVy{y?x$&ZT{vY5;-?}aSazM=eZmg4nu+0h<}J|ZzJ z=@M)uq0-Qh3p2p$Q)F(l(ugb_%GhU%+Zf4mHSQbF*_mO9`fn+bZd8Iv-Y5%dOS%Ep zX-=;>o{^8nrcY}zOds0bb%>|6TcM`npqd_%)7qLtVNP&xU^|qt9~}sjby>;onp{H8 ztjtf5iuy)Ild=-t-w3gu>4uW&9Q`aQZYK^iRZX2rZVqnmI;e9a4(8^dm79YqHp}wiJcUJ)y2WXe6(ris|C9$exVArO``e2EPYQ<6&ted(bp~ z3Rg5+G2?bMrZ`|}sajso+fpHxM+S6nrL)k7@$yGWc}s!pJm zljYuYVjeM%4b&bPFps2W-XZU^>EwNSd)L!iUU5Wfo`$^N6M4TU@_sL3K5NT+2jrFN zN~yQNyp&wbkk+1BP3R)_jpsLp(M2Tc<6uhEsMRDB8AYt{i?4hrh0>da#oRc0i+yEz zQVmb0%hn^?yB^Wm5=W%w5oGHL$<`B+Ev)UI)Y*#l*m+8lrPIqK(7}vmqN{%1*f*2| z;}ECpzn&sukt1T_Gqb1AzdQQ2V(K(OXUv+9%beOeAw&CCVWFEz zVNJ8>h+Pstn^5~ZqdF#Al2EN>2b6`O-m~#q?v=3|2fJSRg z8aTqrq=9oNnKb0v{UX3l@b;X8d)#z>%12H!aXWX5^ z_IB7U`Whg};+7WQI&X^`hcs(x6A1f4Cc5~VjYe=2OFCGZZU`}HZ0ROcTJmjgSWYbW}l!|8Itl; z#RysS*ZqYT`>-Wm#xu2taG>%4{<`p|-Gus&VcMMze(@yX>Eby30{_MMPF^3!&Gi2g z=YBX0{Hvb*Jx)2*$JWI!_3ZCiY-le+W8@hZ8z`+GRl=E`hT1= zLe?Wc%8?2;I0@J!>Tq;O}Bm_Ka#JHAY4!a{{( zjxA?s^?-E0uJA5E{jr?Bj6W|j{Ww_j%x#Yj1Z4Qr_`4Ij@)BY0qD7QC;eAa z!g+?NKl1af9y!_NJ=|2nL_}>FR4#w;Uh<^*X{v?0E^H6`~ zD*Ql7_#xm`2&djMKF?fv5L9ohqiwwy#N#}#?z7D;Ey`{hHvJo#{lU)S5~IW0*09Rw zYnW3!$97*^%%emxF#i~r8zvdoCt1L!Gtf`E{UFJvvG~X6-|3^7xe%oA+! zg$WT$O#Gb|>Wfos{2eChR#5Ui3rRbT{r=>82+0>RB%XMs*yiKbh9!>9m=M_}{ji63 zT;xz(KAOqDGO4#M`xTQ(*8VcF`G0;RM5LjbQbTz$A?bFAx~X6hCEXN(uJ_{41-p@p zpz`c&4x-d3{0W;7BA6D>ebl41!D7cppo&E0! zF-FZnpT~3L&kLf%1{RZJD(a#cMa_|d6%nANeK^M{>zJ?HE@m9ji4C6sUH~LHT zC9W$lRuWFfxj5kr*jf;N$}kRLV5gkN6dYFY9R)v7FcW2ei3U%^Wiyi&mu1#eWa zLcz}}Sgl~Kf{hAxDL6=oGJ8wGcNKJ@1ET-w3ZA2&n-FDKqTmD}v^*88*t#mVd^=3a{nMe?28e&T*q13%6YXg_fVZLL0%-Qy&i$N#de zBiAud5!>p^l8y3NADWhYm*baoXxj2kMRz4a(G{JPZZ>GhPk*WWbXe;8gmkB}?pO#q zQ!@wD{0LFi_Q&?p4vaFRtCjgXx{^uj4(c7cDErg=Y!Bsd`k#E=;gp1Brc2jimd;j@ z^EyjG>*)-(HE+_Yny~f3OsS~ZJb0hhY44wc@M3zp3U&0pp>)Eq@8a}jd=(Jh*$;@~OE^dHX z#8p|5@+^?=mve{25hV8Qtdx(3x{e!2d9|brDm&R7eZd7dl&2)(y%AfYp#wN>9y`jj z>Ep*1RSnh-Tifr0o-LNu#H%k4n!|(Y4jb&K@7$uKFT$BI>r?GJsxzv7jOf^fm1yAz-Ih$c;Y0rX%}GPELD!)Xp%G}_7KNW^)wtI5l^4(Q&-w;2XVfg(?m6t zVy(9G7yBgQz*M`5wUZKtC}5M~i8HNG*N73gO3YSp_6?)+VRaPFG?=_2@#sy+jqHBQ zspy$vYcdgb#ZZeAkAaqnqNbwff{uBd0k1?JrDF1WehE*Vfq3w^4&Tw2w_`7YR5_ls zi1wlE(-#qQijxUwT%u@BnElJ0*-w-2*z{A#GzG@YVsd_Ivp7Y5->j&ueM? z!J;a;xOzTHaeYNtrqihZKgA`6UPG|((|tk8u6VZS#iNiKH>$*}Du7diao(@O83HfE z#!$sNGLO7BX-l*mSfbH(fpKG(D;8*AImT9=ZIi`Bd}&VXElXPyT}aN7O{GTQQ`9U^MV_r$ zpqEQKp}yIPrvHjgAvA)HX~Ieq9b!(XFN?kLNbY)+M8vekTc+fs>BMGPs_cwMX;pH2ae zoRFlHByKcsT^^HUWL2Gk+{N21<%FFOuzrt>o1m5;+fq?iEN)|IjzV1oDUd;q94M;e zT2Bxb+BD4wlnIfWp_*l(j-Oy@dkHnxnyTht@M$sl7&0kIVDmI?rLGk-G1O}ToXRQ^ zl%m{dSJkutBc{^l8MdlWDPh$WxL9aa0gTfu2zoANBC&cah-}2giV%i935JDJFqG^= z>Li9RCPvjvvlyaTjB)ZJt^R)NUYs-*+lcLU7^v|2JacZFGh0&->b4y04b#LZwlPvW zCKVE1P!I`@fvKY{zL<>uX4Za8ea0`_H+&iF7hV|;FT~&qlVr?NMx>dJq&8Dm>>Lqu zY}l`^@4+a7xA=$Apn84dcipW{3k#7ynVZ>Gsv=%=4|1$BI#U`)zAF9A*->5skz%Q| ziUkaoaHRf>2#fNH)Qm(to>_;gWUerhSy5I6-*|hLR#2-W zFg8nbqeYVrphQWXP3-(g%^0k^Gth*_!E~NEvcVO5NJ+l+4{X-3jby6v_WAN#mN1Bv zJXy8*b45!1%8quU`am4oG~Wnldn3)IGQq1v%OwWMqe@`jrO^Rt1s+WZTxkjXm@M82*(pO+Q#cFgkv<8c+sn?OTD#SoFS{rT!Ha+SHn4w#6A9TS*E?8Fw=R@gy^E(IBV;c^drPNGg21M)EpfI*V>kH7;a)c8eH3D+EwmJT!LLpPd- zJ5P(yTtp3p-pcSUx@yzBH1=cDHa$kLC@N;NnRvEbGRZPp5(^ECe-K7Oo48}8 z<4;mKR55$nsHsy!`P)4Jl8OYG+Il=mk(|`RtjI!Kd-&Mt{X5D8S&g@|>qC86Oi)>t!od*>4KB((B?MW8It$r9K{;lm zDM!f`dMIZpazE~*rN|3(N{j7mSoO6&BeeuSb|PO#B0A%L>7tWTqxM~`bAlA6>3p-t zv$T)fE~yzxuYDz`3mtz-?dwNJp~@{u`>1*+NN0{i%TFbp*jg#K0{L~QTq4a=)j6QX^q6$9J1Ysr7%j! zL@Ua5tR)en$#s3OfrLveHoV4V1nN*g_@`vaK@-LeEPD!$eV{^wQe>w$Wb2dCVSfkYc4(5|}BDqM~Goo}x&(u9U$=u3qs%E<|>0lW`0rv#2$Znh2G}11pd? z{X}CYoE;X%5C^UX@XeQlu<4-_DFiDB-FDy}IB;nWW5_&LU{!K5P9>Fe5*|qj9X?4y zdZ6UzLVqLrN-M;;I5fh3eJOqa@eM zi0RC-Y$QzH)q?7==6`MN+%cBaqUM7M2=^jg8Hbcvqr)Nh(^Bq5=y=J^PYZG$+CG|0 z(w-hzhY==2xa_B}BiZ3bHs4A~px_DXL zlJaVE*@Dm2EnQ_UNax2~c1kW;qWEC5ImzMywc!u8z)%wgm43Vpi72$ObT6-4S$W4w zXBj1|B&LpY$I9i)mV7QzH>VP3W#!ay%#|ybuXJCHBI?A0m5FMT>~!}Om#h3ZtSD}R zPIa`Q*k`-zVaXx2B#&+?Lr}M+A&ELWaolFU;yEemM>}r&>pnAL;P_w8rEm%;ANOaT zqG6f(u&|IX)zU_z*&S^e`7tTl5MC&l#xo5bCNRtj&onBN@GLve zq@#`DdO*6DDjdN6Xp^`N*yr(gAO1-HHNZcC`Amg>3y^zpr|D(;pZ0*8qmqLF}3f`20^J3R6h|g^T#^(l#{+QnG6#U^7{2x;Ar-0vx@}n6)`TZ~@ zydU@mgx{vZj{*NNaF4>@0)7R`m-@)~IZ)Qw4txgixxmj>;aq#@kMiD-f-g(Ky(u_t zBJ{`j{uF#e3jW_x@ZBl+V=4GEDfkO1_`jy$gDLpyDfoLSxNIw_3{ZaB1K*8C^nJKl zelr|RjN!9@pNB*Fhf#(M=W7P~V|Yahep?F8_Ym|)`nyu__7pslg8vWT=VK!+fO=;7 z+;{ml?1^-J{|xwE2R;aVKk#m(Mfy?T73ct8P`C@aqd&@%mx5mcJOk-z{>8x0a^Rj6 z`sFEjHSll&?9{=V>E8qV72xc@iSx~&JJEhjg?9n}CUBjeZE#R;bXr#*mNa(;=uY!! zvi41}v+T46ez7yePevm8Gv%-&?GF586OL^or zNVQB2C6RT$Kma298ymdxka0ShrnYMB#B8@M&`8FPh+3i)>ry1;YujMp@(TVD)VFUI z(8|}6CK=c!9@u6m%wYAc7ONtar-l5b-op-d%G=VN^-aEpI>=k6XY+Nf-c5$(4QpO; z1Y7WWxXOQLpuvw9*c%)9$g@#bCsY4AdHtKukGETM@jA}ZZ3Ih`dS3!vkIOuXFih0( z!1t|cbX25%(c zK_yPq4bElUUEsiv`GJln3LDI4F9@ESS#s2TX9P42@A{t_?);|1?75ays? zrY$P%GYEMg>B5}zZbHl{dA38kzab9W-H5^;R5)!rY0E1%#hg@NyrNC%d4z~p2i$8n9}9u>Yy z;j0zCj?irwUnE4j&k!QrpAaJ5-w+~QjxS7i1|ZX2q+k{OuYm2b!b8L_$6XJF|5V{` z5Kg!5eK7vn7l@#QTo(61&A`UXJKHxmc_R|&!Q9|?;MsS3RrrJo&%vCR@y`Zid^aI%hUXEMV7^K?2X}51{;0x#q43ugo`<}=Gw$jj$!5hpz{Bb^1lpoYu9y{CljJPZz04Yv5gSw3)T0h#|r#F77M z;*g)~dCLC~;auDmBfP;d#uyIzKN1IhHr%8?6Oi=R5Mol`r$7Dz#G#iFh3_JM73TiL z5${pri1!`Bn{Y3N{`f1(1wJ1Sd=f$*zpL;M6}tM95(oV@;-K##4*Ks9-io^cgdWVDU`x*Q ziU<+E5|Hs16G!|S;)s7Iam3$1i1d01LH`uPLH}*ypnr}y=wBcX`Zo!Yo*R=nS2@;Q zgh=mhLd4$!$oSidBYrP&#QzF$%1em!{*@5)ydOmRC~?sLfjH^sFc+m>P6wo3?k2tn?U`^f@<%ua{i_PU2Xjx? z64=iYLe3sQrWYoT^u9_Q>3y9z(tC*z^aF&Te~aOuf0sDu|4bb8nV6H3zJzco^jX0c z1$O~bzV8x8f3{!Yyp+d&NlS~2c?5Y3q0t|ajenA!$!x+k9E+F2Zs91`{fjt3q6?KS}#UZ5bR0!n#Ze} z&Z^4lb{xHj@Sc>|fRRRT#dBNxdZ$N};~lMPhjL(Lh1dV_2wraFEBBM{Pd(vXbVzXi z)ahY1y_5CyCZ;fKT%sjBU5|o4X_dW*1B|Co#n?I&V%Gc#^4Wm%Q)IivV(8ekc7S z=1#H4Ko*C?ySl|^IBf0$wTt!=yGT8S%q$g@O*dnOEAUp(5FDts!xlJ#UK`kMVi9xq zJo8A`62M61j)!n=Cp?c;HMvqn-sHxS-aPYg0Pnql|IktM*x;J|$lp*LY>wf@v|e*J zj3rS5Lq^cUGa@vhscSP*OD^Gkdnw0r-8VQcN^p~~8|T~RC1{Ljc1@gE zo;03I;)yv9#Xvz=bv;>(mQ!K(PmmSIKJ(1{yq-tt=A%3LG@GB|Fbhv(z``uDbOhla zT=xErL~2IhL_?f&2#2{atDKdOBEmCec(JbOkrPP)^S3j%q6(1x{3hN#I$8GByKDA2 zDxykKd_&XGmD$H+6eE2Y9>^4}!d(JhvNC=-G|$ZGI^8lEelu~@hKKQTbGG7GJl6vw zJ2Mygf5jaGK|WqDq}33t$nX&0lQ<*`9e@Qbj^6RV^5kbykF~vQ)0vZXbrE&71pUC2 zS;oP=CH#qx?^RyQaGs}*(u1EE%zg%(2Wwx7eqZVrc7bKq>9d%xtrQJDQq^>BRc?2Z zl?#wa)oK_K%{l}VzdW3T9){OZ^YAgx8l0I%Jg{zh4lEOo#=rVUBokYqIi909CXRzo z$`XZ`hUK97lFC^TawcNqycZfjti^_Dt}Z*d&>%rp`ZPq*VLaz#mS9Y*vUJ?KxpCAy zKImD)n;L7xV>n!~T9TALO^!dgymsuNI1j$C^4E`%G~+-1!g!rZi*rW%i4wQtu@iR@ z&ev8gt6WgMq^@#RRo$v8)2wti`|AUEzXS_>bwV|(*p2_#s@~@=EyaZ!_oB~pN?SyZSnvFR8f85ut9?oVj(&%qim~jtd=WEm%~(Y?--a z6-E3A>CJ4gpN08o=}D0>vGjRUCxCKrcwZ3zmmUstofW|2Ulb_9WfKL@*60J_^!(D5 zmBqoq)sc6#9dm+;Sy_JDQgaz=N9VzggC}#;|N16U&2~3-cw2p)RlW}OHVtK+jdx~n zyuG}!dZXhso7@aT-iG-|_W}R92b7p?8th@QES8URTE1hgKTM_N!`6bFMJm)di1ii6 z1WtGupLCe9PCB1_+`$XMLPvcnA2cphJC{&M6y%w&bGx;K}4!HY^uTjOcdq8#&wB z!-BVbnxDosbozgs^GVHzkmrY3t{RK6CsPE-^FZg9?mW+}2!4+;=lQ`kjtI;b^+kWg zu{B_S#LI2WDhHOo{usVoBY?zf@W-?+Rq3qh=Rzodm?y}<*DMa}E*-&`*7uS4@?ALbZitj%2+4bpF9 zJNJE)2Lih{bRL!@{pX14eRZcN8po<(uHcY@rKk`3w*xYMkT~LV|C8~*NF4F`MnB(bxDd)t z`YQoRKbtt{%ZP*iX5yf~Q-$*-bB5om!g(&o@V_GjpQq>#KHnw|y61?4&kMvs_a7?! zw<`Qy75=^occUSaPYEFTTu&T)%87%|LgL`_0~P)+D!gBXA5`H(DqQwS5&s<({+( - -#include "portaudio.h" -#include "pa_host.h" - -#define CLIP( val, min, max ) { val = ((val) < (min)) ? min : (((val) < (max)) ? (max) : (val)); } - -/*************************************************************************/ -static void PaConvert_Float32_Int16( - float *sourceBuffer, int sourceStride, - short *targetBuffer, int targetStride, - int numSamples ) -{ - int i; - for( i=0; ipast_NativeInputSampleFormat = nativeInputSampleFormat; - past->past_InputConversionSourceStride = 1; - past->past_InputConversionTargetStride = 1; - - if( nativeInputSampleFormat != past->past_InputSampleFormat ) - { - int ifDither = (past->past_Flags & paDitherOff) == 0; - past->past_InputConversionProc = PaConvert_SelectProc( nativeInputSampleFormat, - past->past_InputSampleFormat, 0, ifDither ); - if( past->past_InputConversionProc == NULL ) return paSampleFormatNotSupported; - } - else - { - past->past_InputConversionProc = NULL; /* no conversion necessary */ - } - - return paNoError; -} - -/*************************************************************************/ -PaError PaConvert_SetupOutput( internalPortAudioStream *past, - PaSampleFormat nativeOutputSampleFormat ) -{ - - past->past_NativeOutputSampleFormat = nativeOutputSampleFormat; - past->past_OutputConversionSourceStride = 1; - past->past_OutputConversionTargetStride = 1; - - if( nativeOutputSampleFormat != past->past_OutputSampleFormat ) - { - int ifDither = (past->past_Flags & paDitherOff) == 0; - int ifClip = (past->past_Flags & paClipOff) == 0; - - past->past_OutputConversionProc = PaConvert_SelectProc( past->past_OutputSampleFormat, - nativeOutputSampleFormat, ifClip, ifDither ); - if( past->past_OutputConversionProc == NULL ) return paSampleFormatNotSupported; - } - else - { - past->past_OutputConversionProc = NULL; /* no conversion necessary */ - } - - return paNoError; -} - -/************************************************************************* -** Called by host code. -** Convert input from native format to user format, -** call user code, -** then convert output to native format. -** Returns result from user callback. -*/ -long PaConvert_Process( internalPortAudioStream *past, - void *nativeInputBuffer, - void *nativeOutputBuffer ) -{ - int userResult; - void *inputBuffer = NULL; - void *outputBuffer = NULL; - - /* Get native input data. */ - if( (past->past_NumInputChannels > 0) && (nativeInputBuffer != NULL) ) - { - if( past->past_InputSampleFormat == past->past_NativeInputSampleFormat ) - { - /* Already in native format so just read directly from native buffer. */ - inputBuffer = nativeInputBuffer; - } - else - { - inputBuffer = past->past_InputBuffer; - /* Convert input data to user format. */ - (*past->past_InputConversionProc)(nativeInputBuffer, past->past_InputConversionSourceStride, - inputBuffer, past->past_InputConversionTargetStride, - past->past_FramesPerUserBuffer * past->past_NumInputChannels ); - } - } - - /* Are we doing output? */ - if( (past->past_NumOutputChannels > 0) && (nativeOutputBuffer != NULL) ) - { - outputBuffer = (past->past_OutputConversionProc == NULL) ? - nativeOutputBuffer : past->past_OutputBuffer; - } - /* - AddTraceMessage("Pa_CallConvertInt16: inputBuffer = ", (int) inputBuffer ); - AddTraceMessage("Pa_CallConvertInt16: outputBuffer = ", (int) outputBuffer ); - */ - /* Call user callback routine. */ - userResult = past->past_Callback( - inputBuffer, - outputBuffer, - past->past_FramesPerUserBuffer, - past->past_FrameCount, - past->past_UserData ); - - /* Advance frame counter for timestamp. */ - past->past_FrameCount += past->past_FramesPerUserBuffer; // FIXME - should this be in here? - - /* Convert to native format if necessary. */ - if( (past->past_OutputConversionProc != NULL ) && (outputBuffer != NULL) ) - { - (*past->past_OutputConversionProc)( outputBuffer, past->past_OutputConversionSourceStride, - nativeOutputBuffer, past->past_OutputConversionTargetStride, - past->past_FramesPerUserBuffer * past->past_NumOutputChannels ); - } - - return userResult; -} diff --git a/branches/lydia/portaudio/pa_host.h b/branches/lydia/portaudio/pa_host.h deleted file mode 100644 index 9ff4dce..0000000 --- a/branches/lydia/portaudio/pa_host.h +++ /dev/null @@ -1,189 +0,0 @@ -#ifndef PA_HOST_H -#define PA_HOST_H - -/* - * $Id: pa_host.h 401 2004-07-23 17:41:54Z jaromil $ - * Host dependant internal API for PortAudio - * - * Author: Phil Burk - * - * PortAudio Portable Real-Time Audio Library - * Latest Version at: http://www.softsynth.com/portaudio/ - * DirectSound and Macintosh Implementation - * Copyright (c) 1999-2000 Phil Burk - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * Any person wishing to distribute modifications to the Software is - * requested to send the modifications to the original developer so that - * they can be incorporated into the canonical version. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include "portaudio.h" - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -#ifndef SUPPORT_AUDIO_CAPTURE -#define SUPPORT_AUDIO_CAPTURE (1) -#endif - -#ifndef int32 - typedef long int32; -#endif -#ifndef uint32 - typedef unsigned long uint32; -#endif -#ifndef int16 - typedef short int16; -#endif -#ifndef uint16 - typedef unsigned short uint16; -#endif - -/* Used to convert between various sample formats. */ -typedef void (PortAudioConverter)( - void *inputBuffer, int inputStride, - void *outputBuffer, int outputStride, - int numSamples ); - -#define PA_MAGIC (0x18273645) - -/************************************************************************************/ -/****************** Structures ******************************************************/ -/************************************************************************************/ - -typedef struct internalPortAudioStream -{ - uint32 past_Magic; /* ID for struct to catch bugs. */ - - /* Begin user specified information. */ - uint32 past_FramesPerUserBuffer; - uint32 past_NumUserBuffers; - double past_SampleRate; /* Closest supported sample rate. */ - int past_NumInputChannels; - int past_NumOutputChannels; - PaDeviceID past_InputDeviceID; - PaDeviceID past_OutputDeviceID; - PaSampleFormat past_InputSampleFormat; - PaSampleFormat past_OutputSampleFormat; - PortAudioCallback *past_Callback; - void *past_UserData; - uint32 past_Flags; - /* End user specified information. */ - - void *past_DeviceData; - PaSampleFormat past_NativeOutputSampleFormat; - PaSampleFormat past_NativeInputSampleFormat; - - /* Flags for communicating between foreground and background. */ - volatile int past_IsActive; /* Background is still playing. */ - volatile int past_StopSoon; /* Background should keep playing when buffers empty. */ - volatile int past_StopNow; /* Background should stop playing now. */ - /* These buffers are used when the native format does not match the user format. */ - void *past_InputBuffer; - uint32 past_InputBufferSize; /* Size in bytes of the input buffer. */ - void *past_OutputBuffer; - uint32 past_OutputBufferSize; - /* Measurements */ - uint32 past_NumCallbacks; - PaTimestamp past_FrameCount; /* Frames output to buffer. */ - /* For measuring CPU utilization. */ - double past_AverageInsideCount; - double past_AverageTotalCount; - double past_Usage; - int past_IfLastExitValid; - /* Format Conversion */ - /* These are setup by PaConversion_Setup() */ - PortAudioConverter *past_InputConversionProc; - int past_InputConversionSourceStride; - int past_InputConversionTargetStride; - PortAudioConverter *past_OutputConversionProc; - int past_OutputConversionSourceStride; - int past_OutputConversionTargetStride; -} -internalPortAudioStream; - -/************************************************************************************/ -/******** These functions must be provided by a platform implementation. ************/ -/************************************************************************************/ - -PaError PaHost_Init( void ); -PaError PaHost_Term( void ); - -PaError PaHost_OpenStream( internalPortAudioStream *past ); -PaError PaHost_CloseStream( internalPortAudioStream *past ); - -PaError PaHost_StartOutput( internalPortAudioStream *past ); -PaError PaHost_StopOutput( internalPortAudioStream *past, int abort ); -PaError PaHost_StartInput( internalPortAudioStream *past ); -PaError PaHost_StopInput( internalPortAudioStream *past, int abort ); -PaError PaHost_StartEngine( internalPortAudioStream *past ); -PaError PaHost_StopEngine( internalPortAudioStream *past, int abort ); -PaError PaHost_StreamActive( internalPortAudioStream *past ); - -void *PaHost_AllocateFastMemory( long numBytes ); -void PaHost_FreeFastMemory( void *addr, long numBytes ); - -/* This only called if PA_VALIDATE_RATE IS CALLED. */ -PaError PaHost_ValidateSampleRate( PaDeviceID id, double requestedFrameRate, - double *closestFrameRatePtr ); - -/**********************************************************************/ -/************ Common Utility Routines provided by PA ******************/ -/**********************************************************************/ - -/* PaHost_IsInitialized() returns non-zero if PA is initialized, 0 otherwise */ -int PaHost_IsInitialized( void ); - -internalPortAudioStream* PaHost_GetStreamRepresentation( PortAudioStream *stream ); - -int PaHost_FindClosestTableEntry( double allowableError, const double *rateTable, - int numRates, double frameRate ); - -long Pa_CallConvertInt16( internalPortAudioStream *past, - short *nativeInputBuffer, - short *nativeOutputBuffer ); - -/* Calculate 2 LSB dither signal with a triangular distribution. -** Ranged properly for adding to a 32 bit 1.31 fixed point value prior to >>15. -** Range of output is +/- 65535 -** Multiply by PA_DITHER_SCALE to get a float between -2.0 and 2.0. */ -#define PA_DITHER_BITS (15) -#define PA_DITHER_SCALE (1.0f / ((1< -#include -#include -#include - -/* PLB20010422 - "memory.h" doesn't work on CodeWarrior for PC. Thanks Mike Berry for the mod. */ -#ifdef _WIN32 -#ifndef __MWERKS__ -#include -#endif /* __MWERKS__ */ -#else /* !_WIN32 */ -#include -#endif /* _WIN32 */ - -#include "portaudio.h" -#include "pa_host.h" -#include "pa_trace.h" - -/* The reason we might NOT want to validate the rate before opening the stream - * is because many DirectSound drivers lie about the rates they actually support. - */ -#define PA_VALIDATE_RATE (0) /* If true validate sample rate against driver info. */ - -/* -O- maybe not allocate past_InputBuffer and past_OutputBuffer if not needed for conversion -*/ - -#ifndef FALSE - #define FALSE (0) - #define TRUE (!FALSE) -#endif - -#define PRINT(x) { printf x; fflush(stdout); } -#define ERR_RPT(x) PRINT(x) -#define DBUG(x) /* PRINT(x) */ -#define DBUGX(x) /* PRINT(x) */ - -static int gInitCount = 0; /* Count number of times Pa_Initialize() called to allow nesting and overlapping. */ - -static PaError Pa_KillStream( PortAudioStream *stream, int abort ); - -/***********************************************************************/ -int PaHost_FindClosestTableEntry( double allowableError, const double *rateTable, int numRates, double frameRate ) -{ - double err, minErr = allowableError; - int i, bestFit = -1; - - for( i=0; inumSampleRates == -1 ) - { - /* Is it out of range? */ - if( (requestedFrameRate < pdi->sampleRates[0]) || - (requestedFrameRate > pdi->sampleRates[1]) ) - { - return paInvalidSampleRate; - } - - *closestFrameRatePtr = requestedFrameRate; - } - else - { - bestRateIndex = PaHost_FindClosestTableEntry( 1.0, pdi->sampleRates, pdi->numSampleRates, requestedFrameRate ); - if( bestRateIndex < 0 ) return paInvalidSampleRate; - *closestFrameRatePtr = pdi->sampleRates[bestRateIndex]; - } - return paNoError; -} - -/*************************************************************************/ -PaError Pa_OpenStream( - PortAudioStream** streamPtrPtr, - PaDeviceID inputDeviceID, - int numInputChannels, - PaSampleFormat inputSampleFormat, - void *inputDriverInfo, - PaDeviceID outputDeviceID, - int numOutputChannels, - PaSampleFormat outputSampleFormat, - void *outputDriverInfo, - double sampleRate, - unsigned long framesPerBuffer, - unsigned long numberOfBuffers, - unsigned long streamFlags, - PortAudioCallback *callback, - void *userData ) -{ - internalPortAudioStream *past = NULL; - PaError result = paNoError; - int bitsPerInputSample; - int bitsPerOutputSample; - /* Print passed parameters. */ - DBUG(("Pa_OpenStream( %p, %d, %d, %d, %p, /* input */ \n", - streamPtrPtr, inputDeviceID, numInputChannels, - inputSampleFormat, inputDriverInfo )); - DBUG((" %d, %d, %d, %p, /* output */\n", - outputDeviceID, numOutputChannels, - outputSampleFormat, outputDriverInfo )); - DBUG((" %g, %d, %d, 0x%x, , %p )\n", - sampleRate, framesPerBuffer, numberOfBuffers, - streamFlags, userData )); - - /* Check for parameter errors. */ - if( (streamFlags & ~(paClipOff | paDitherOff)) != 0 ) return paInvalidFlag; - if( streamPtrPtr == NULL ) return paBadStreamPtr; - if( inputDriverInfo != NULL ) return paHostError; /* REVIEW */ - if( outputDriverInfo != NULL ) return paHostError; /* REVIEW */ - if( (inputDeviceID < 0) && ( outputDeviceID < 0) ) return paInvalidDeviceId; - if( (outputDeviceID >= Pa_CountDevices()) || (inputDeviceID >= Pa_CountDevices()) ) - { - return paInvalidDeviceId; - } - if( (numInputChannels <= 0) && ( numOutputChannels <= 0) ) return paInvalidChannelCount; - -#if SUPPORT_AUDIO_CAPTURE - if( inputDeviceID >= 0 ) - { - PaError size = Pa_GetSampleSize( inputSampleFormat ); - if( size < 0 ) return size; - bitsPerInputSample = 8 * size; - if( (numInputChannels <= 0) ) return paInvalidChannelCount; - } -#else - if( inputDeviceID >= 0 ) - { - return paInvalidChannelCount; - } -#endif /* SUPPORT_AUDIO_CAPTURE */ - else - { - if( numInputChannels > 0 ) return paInvalidChannelCount; - bitsPerInputSample = 0; - } - - if( outputDeviceID >= 0 ) - { - PaError size = Pa_GetSampleSize( outputSampleFormat ); - if( size < 0 ) return size; - bitsPerOutputSample = 8 * size; - if( (numOutputChannels <= 0) ) return paInvalidChannelCount; - } - else - { - if( numOutputChannels > 0 ) return paInvalidChannelCount; - bitsPerOutputSample = 0; - } - - if( callback == NULL ) return paNullCallback; - - /* Allocate and clear stream structure. */ - past = (internalPortAudioStream *) PaHost_AllocateFastMemory( sizeof(internalPortAudioStream) ); - if( past == NULL ) return paInsufficientMemory; - memset( past, 0, sizeof(internalPortAudioStream) ); - AddTraceMessage("Pa_OpenStream: past", (long) past ); - - past->past_Magic = PA_MAGIC; /* Set ID to catch bugs. */ - past->past_FramesPerUserBuffer = framesPerBuffer; - past->past_NumUserBuffers = numberOfBuffers; /* NOTE - PaHost_OpenStream() MUST CHECK FOR ZERO! */ - past->past_Callback = callback; - past->past_UserData = userData; - past->past_OutputSampleFormat = outputSampleFormat; - past->past_InputSampleFormat = inputSampleFormat; - past->past_OutputDeviceID = outputDeviceID; - past->past_InputDeviceID = inputDeviceID; - past->past_NumInputChannels = numInputChannels; - past->past_NumOutputChannels = numOutputChannels; - past->past_Flags = streamFlags; - - /* Check for absurd sample rates. */ - if( (sampleRate < 1000.0) || (sampleRate > 200000.0) ) - { - result = paInvalidSampleRate; - goto cleanup; - } - - /* Allocate buffers that may be used for format conversion from user to native buffers. */ - if( numInputChannels > 0 ) - { - -#if PA_VALIDATE_RATE - result = PaHost_ValidateSampleRate( inputDeviceID, sampleRate, &past->past_SampleRate ); - if( result < 0 ) - { - goto cleanup; - } -#else - past->past_SampleRate = sampleRate; -#endif - /* Allocate single Input buffer for passing formatted samples to user callback. */ - past->past_InputBufferSize = framesPerBuffer * numInputChannels * ((bitsPerInputSample+7) / 8); - past->past_InputBuffer = PaHost_AllocateFastMemory(past->past_InputBufferSize); - if( past->past_InputBuffer == NULL ) - { - result = paInsufficientMemory; - goto cleanup; - } - } - else - { - past->past_InputBuffer = NULL; - } - - /* Allocate single Output buffer. */ - if( numOutputChannels > 0 ) - { -#if PA_VALIDATE_RATE - result = PaHost_ValidateSampleRate( outputDeviceID, sampleRate, &past->past_SampleRate ); - if( result < 0 ) - { - goto cleanup; - } -#else - past->past_SampleRate = sampleRate; -#endif - past->past_OutputBufferSize = framesPerBuffer * numOutputChannels * ((bitsPerOutputSample+7) / 8); - past->past_OutputBuffer = PaHost_AllocateFastMemory(past->past_OutputBufferSize); - if( past->past_OutputBuffer == NULL ) - { - result = paInsufficientMemory; - goto cleanup; - } - } - else - { - past->past_OutputBuffer = NULL; - } - - result = PaHost_OpenStream( past ); - if( result < 0 ) goto cleanup; - - *streamPtrPtr = (void *) past; - - return result; - -cleanup: - if( past != NULL ) Pa_CloseStream( past ); - *streamPtrPtr = NULL; - return result; -} - - -/*************************************************************************/ -PaError Pa_OpenDefaultStream( PortAudioStream** stream, - int numInputChannels, - int numOutputChannels, - PaSampleFormat sampleFormat, - double sampleRate, - unsigned long framesPerBuffer, - unsigned long numberOfBuffers, - PortAudioCallback *callback, - void *userData ) -{ - return Pa_OpenStream( - stream, - ((numInputChannels > 0) ? Pa_GetDefaultInputDeviceID() : paNoDevice), - numInputChannels, sampleFormat, NULL, - ((numOutputChannels > 0) ? Pa_GetDefaultOutputDeviceID() : paNoDevice), - numOutputChannels, sampleFormat, NULL, - sampleRate, framesPerBuffer, numberOfBuffers, paNoFlag, callback, userData ); -} - -/*************************************************************************/ -PaError Pa_CloseStream( PortAudioStream* stream) -{ - PaError result; - internalPortAudioStream *past; - - DBUG(("Pa_CloseStream()\n")); - if( stream == NULL ) return paBadStreamPtr; - past = (internalPortAudioStream *) stream; - - Pa_AbortStream( past ); - result = PaHost_CloseStream( past ); - - if( past->past_InputBuffer ) PaHost_FreeFastMemory( past->past_InputBuffer, past->past_InputBufferSize ); - if( past->past_OutputBuffer ) PaHost_FreeFastMemory( past->past_OutputBuffer, past->past_OutputBufferSize ); - PaHost_FreeFastMemory( past, sizeof(internalPortAudioStream) ); - - return result; -} - -/*************************************************************************/ -PaError Pa_StartStream( PortAudioStream *stream ) -{ - PaError result = paHostError; - internalPortAudioStream *past; - - if( stream == NULL ) return paBadStreamPtr; - past = (internalPortAudioStream *) stream; - - past->past_FrameCount = 0.0; - - if( past->past_NumInputChannels > 0 ) - { - result = PaHost_StartInput( past ); - DBUG(("Pa_StartStream: PaHost_StartInput returned = 0x%X.\n", result)); - if( result < 0 ) goto error; - } - - if( past->past_NumOutputChannels > 0 ) - { - result = PaHost_StartOutput( past ); - DBUG(("Pa_StartStream: PaHost_StartOutput returned = 0x%X.\n", result)); - if( result < 0 ) goto error; - } - - result = PaHost_StartEngine( past ); - DBUG(("Pa_StartStream: PaHost_StartEngine returned = 0x%X.\n", result)); - if( result < 0 ) goto error; - - return paNoError; - -error: - return result; -} - -/*************************************************************************/ -PaError Pa_StopStream( PortAudioStream *stream ) -{ - return Pa_KillStream( stream, 0 ); -} - -/*************************************************************************/ -PaError Pa_AbortStream( PortAudioStream *stream ) -{ - return Pa_KillStream( stream, 1 ); -} - -/*************************************************************************/ -static PaError Pa_KillStream( PortAudioStream *stream, int abort ) -{ - PaError result = paNoError; - internalPortAudioStream *past; - - DBUG(("Pa_StopStream().\n")); - if( stream == NULL ) return paBadStreamPtr; - past = (internalPortAudioStream *) stream; - - if( (past->past_NumInputChannels > 0) || (past->past_NumOutputChannels > 0) ) - { - result = PaHost_StopEngine( past, abort ); - DBUG(("Pa_StopStream: PaHost_StopEngine returned = 0x%X.\n", result)); - if( result < 0 ) goto error; - } - - if( past->past_NumInputChannels > 0 ) - { - result = PaHost_StopInput( past, abort ); - DBUG(("Pa_StopStream: PaHost_StopInput returned = 0x%X.\n", result)); - if( result != paNoError ) goto error; - } - - if( past->past_NumOutputChannels > 0 ) - { - result = PaHost_StopOutput( past, abort ); - DBUG(("Pa_StopStream: PaHost_StopOutput returned = 0x%X.\n", result)); - if( result != paNoError ) goto error; - } - -error: - past->past_Usage = 0; - past->past_IfLastExitValid = 0; - - return result; -} - -/*************************************************************************/ -PaError Pa_StreamActive( PortAudioStream *stream ) -{ - internalPortAudioStream *past; - if( stream == NULL ) return paBadStreamPtr; - past = (internalPortAudioStream *) stream; - return PaHost_StreamActive( past ); -} - -/*************************************************************************/ -const char *Pa_GetErrorText( PaError errnum ) -{ - const char *msg; - - switch(errnum) - { - case paNoError: msg = "Success"; break; - case paHostError: msg = "Host error."; break; - case paInvalidChannelCount: msg = "Invalid number of channels."; break; - case paInvalidSampleRate: msg = "Invalid sample rate."; break; - case paInvalidDeviceId: msg = "Invalid device ID."; break; - case paInvalidFlag: msg = "Invalid flag."; break; - case paSampleFormatNotSupported: msg = "Sample format not supported"; break; - case paBadIODeviceCombination: msg = "Illegal combination of I/O devices."; break; - case paInsufficientMemory: msg = "Insufficient memory."; break; - case paBufferTooBig: msg = "Buffer too big."; break; - case paBufferTooSmall: msg = "Buffer too small."; break; - case paNullCallback: msg = "No callback routine specified."; break; - case paBadStreamPtr: msg = "Invalid stream pointer."; break; - case paTimedOut : msg = "Wait Timed Out."; break; - case paInternalError: msg = "Internal PortAudio Error."; break; - case paDeviceUnavailable: msg = "Device Unavailable."; break; - default: msg = "Illegal error number."; break; - } - return msg; -} - -/* - Get CPU Load as a fraction of total CPU time. - A value of 0.5 would imply that PortAudio and the sound generating - callback was consuming roughly 50% of the available CPU time. - The amount may vary depending on CPU load. - This function may be called from the callback function. -*/ -double Pa_GetCPULoad( PortAudioStream* stream) -{ - internalPortAudioStream *past; - if( stream == NULL ) return (double) paBadStreamPtr; - past = (internalPortAudioStream *) stream; - return past->past_Usage; -} - -/*************************************************************************/ -internalPortAudioStream* PaHost_GetStreamRepresentation( PortAudioStream *stream ) -{ - internalPortAudioStream* result = (internalPortAudioStream*) stream; - - if( result == NULL || result->past_Magic != PA_MAGIC ) - return NULL; - else - return result; -} - -/************************************************************* -** Calculate 2 LSB dither signal with a triangular distribution. -** Ranged properly for adding to a 32 bit integer prior to >>15. -** Range of output is +/- 32767 -*/ -#define PA_DITHER_BITS (15) -#define PA_DITHER_SCALE (1.0f / ((1<>DITHER_SHIFT) + (((long)randSeed2)>>DITHER_SHIFT); - /* High pass filter to reduce audibility. */ - highPass = current - previous; - previous = current; - return highPass; -} - -/************************************************************************* -** Called by host code. -** Convert input from Int16, call user code, then convert output -** to Int16 format for native use. -** Assumes host native format is paInt16. -** Returns result from user callback. -*/ -long Pa_CallConvertInt16( internalPortAudioStream *past, - short *nativeInputBuffer, - short *nativeOutputBuffer ) -{ - long temp; - int userResult; - unsigned int i; - void *inputBuffer = NULL; - void *outputBuffer = NULL; - -#if SUPPORT_AUDIO_CAPTURE - /* Get native data from DirectSound. */ - if( (past->past_NumInputChannels > 0) && (nativeInputBuffer != NULL) ) - { - /* Convert from native format to PA format. */ - unsigned int samplesPerBuffer = past->past_FramesPerUserBuffer * past->past_NumInputChannels; - switch(past->past_InputSampleFormat) - { - - case paFloat32: - { - float *inBufPtr = (float *) past->past_InputBuffer; - inputBuffer = past->past_InputBuffer; - for( i=0; ipast_InputBuffer; - inputBuffer = past->past_InputBuffer; - for( i=0; ipast_InputBuffer; - inputBuffer = past->past_InputBuffer; - if( past->past_Flags & paDitherOff ) - { - for( i=0; i> 8); - } - } - else - { - for( i=0; i> 8; /* PLB20010820 */ - temp = ((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp)); - inBufPtr[i] = (char)(temp >> 8); - } - } - break; - } - - case paUInt8: - { - /* Convert 16 bit data to 8 bit unsigned chars */ - unsigned char *inBufPtr = (unsigned char *) past->past_InputBuffer; - inputBuffer = past->past_InputBuffer; - if( past->past_Flags & paDitherOff ) - { - for( i=0; i> 8) + 0x80); - } - } - else - { - /* If you dither then you have to clip because dithering could push the signal out of range! */ - for( i=0; i> 8; /* PLB20010820 */ - temp = ((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp)); - inBufPtr[i] = (unsigned char)((temp>>8) + 0x80); /* PLB20010820 */ - } - } - break; - } - - default: - break; - } - } -#endif /* SUPPORT_AUDIO_CAPTURE */ - - /* Are we doing output time? */ - if( (past->past_NumOutputChannels > 0) && (nativeOutputBuffer != NULL) ) - { - /* May already be in native format so just write directly to native buffer. */ - outputBuffer = (past->past_OutputSampleFormat == paInt16) ? - (void*)nativeOutputBuffer : past->past_OutputBuffer; - } - /* - AddTraceMessage("Pa_CallConvertInt16: inputBuffer = ", (int) inputBuffer ); - AddTraceMessage("Pa_CallConvertInt16: outputBuffer = ", (int) outputBuffer ); - */ - /* Call user callback routine. */ - userResult = past->past_Callback( - inputBuffer, - outputBuffer, - past->past_FramesPerUserBuffer, - past->past_FrameCount, - past->past_UserData ); - - past->past_FrameCount += (PaTimestamp) past->past_FramesPerUserBuffer; - - /* Convert to native format if necessary. */ - if( outputBuffer != NULL ) - { - unsigned int samplesPerBuffer = past->past_FramesPerUserBuffer * past->past_NumOutputChannels; - switch(past->past_OutputSampleFormat) - { - case paFloat32: - { - float *outBufPtr = (float *) past->past_OutputBuffer; - if( past->past_Flags & paDitherOff ) - { - if( past->past_Flags & paClipOff ) /* NOTHING */ - { - for( i=0; i 0x7FFF) ? 0x7FFF : temp)); - } - } - } - else - { - /* If you dither then you have to clip because dithering could push the signal out of range! */ - for( i=0; i 0x7FFF) ? 0x7FFF : temp)); - } - } - break; - } - - case paInt32: - { - int *outBufPtr = (int *) past->past_OutputBuffer; - if( past->past_Flags & paDitherOff ) - { - for( i=0; i> 16 ); - } - } - else - { - for( i=0; i> 1) + PaConvert_TriangularDither(); - temp = temp >> 15; - *nativeOutputBuffer++ = (short)((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp)); - } - } - break; - } - - case paInt8: - { - char *outBufPtr = (char *) past->past_OutputBuffer; - for( i=0; ipast_OutputBuffer; - for( i=0; i 0 ) return paNoError; - ResetTraceMessages(); - return PaHost_Init(); -} - -PaError Pa_Terminate( void ) -{ - PaError result = paNoError; - - if( gInitCount == 0 ) return paNoError; - else if( --gInitCount == 0 ) - { - result = PaHost_Term(); - DumpTraceMessages(); - } - return result; -} - -int PaHost_IsInitialized() -{ - return gInitCount; -} - -/*************************************************************************/ -PaError Pa_GetSampleSize( PaSampleFormat format ) -{ - int size; - switch(format ) - { - - case paUInt8: - case paInt8: - size = 1; - break; - - case paInt16: - size = 2; - break; - - case paPackedInt24: - size = 3; - break; - - case paFloat32: - case paInt32: - case paInt24: - size = 4; - break; - - default: - size = paSampleFormatNotSupported; - break; - } - return (PaError) size; -} - - diff --git a/branches/lydia/portaudio/pa_trace.c b/branches/lydia/portaudio/pa_trace.c deleted file mode 100644 index 90bc0b9..0000000 --- a/branches/lydia/portaudio/pa_trace.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * $Id: pa_trace.c 401 2004-07-23 17:41:54Z jaromil $ - * Portable Audio I/O Library Trace Facility - * Store trace information in real-time for later printing. - * - * Based on the Open Source API proposed by Ross Bencina - * Copyright (c) 1999-2000 Phil Burk - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * Any person wishing to distribute modifications to the Software is - * requested to send the modifications to the original developer so that - * they can be incorporated into the canonical version. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include -#include "pa_trace.h" - -#if TRACE_REALTIME_EVENTS - -static char *traceTextArray[MAX_TRACE_RECORDS]; -static int traceIntArray[MAX_TRACE_RECORDS]; -static int traceIndex = 0; -static int traceBlock = 0; - -/*********************************************************************/ -void ResetTraceMessages() -{ - traceIndex = 0; -} - -/*********************************************************************/ -void DumpTraceMessages() -{ - int i; - int numDump = (traceIndex < MAX_TRACE_RECORDS) ? traceIndex : MAX_TRACE_RECORDS; - - printf("DumpTraceMessages: traceIndex = %d\n", traceIndex ); - for( i=0; i ;-) - added 24k and 16k to ratesToTry[] - fixed Pa_GetInternalDevice() - changed DEVICE_NAME_BASE from /dev/audio to /dev/dsp - handled SNDCTL_DSP_SPEED in Pq_QueryDevice() more graceful - fixed Pa_StreamTime() for paqa_errs.c - fixed numCannel=2 oddity and error handling in Pa_SetupDeviceFormat() - grep also for HP20010922 ... - PLB20010924 - Phil - merged Heiko's changes - removed sNumDevices and potential related bugs, - use getenv("PA_MIN_LATENCY_MSEC") to set desired latency, - simplify CPU Load calculation by comparing real-time to framesPerBuffer, - always close device when querying even if error occurs, - PLB20010927 - Phil - Improved negotiation for numChannels. - SG20011005 - Stewart Greenhill - set numChannels back to reasonable value after query. - DH20010115 - David Herring - fixed uninitialized handle. - - DM20020218 - Dominic Mazzoni - Try to open in nonblocking mode first, in case - the device is already open. New implementation of - Pa_StreamTime that uses SNDCTL_DSP_GETOPTR but - uses our own counter to avoid wraparound. - PLB20020222 - Phil Burk - Added WatchDog proc if audio running at high priority. - Check error return from read() and write(). - Check CPU endianness instead of assuming Little Endian. - 20020621 - pa_unix_oss.c split into pa_unix.c, pa_unix.h, pa_unix_oss.c by - Augustus Saunders. Return values from usleep() ignored by Sam Bayer - because not cross-platform compatible (at least until we get configure - going). Pa_SetupDeviceFormat split into input and output sides to - reflect capabilities of Solaris. - - 20030206 - Martin Rohrbach - various mods for Solaris - - 20030410 - Bjorn Dittmer-Roche - fixed numerous problems associated with pthread_t - - 20030630 - Thomas Richter - eliminated unused variable warnings. - -TODO -O- put semaphore lock around shared data? -O- handle native formats better -O- handle stereo-only device better ??? -O- what if input and output of a device capabilities differ (e.g. es1371) ??? -*/ - -#define HAVE_UNIX 1 - -#ifdef HAVE_UNIX - -#include "pa_unix.h" - -typedef void *(*pthread_function_t)(void *); - -/************************************************* Shared Data ********/ -/* FIXME - put Mutex around this shared data. */ -static internalPortAudioDevice *sDeviceList = NULL; -static int sDefaultInputDeviceID = paNoDevice; -static int sDefaultOutputDeviceID = paNoDevice; -static int sPaHostError = 0; - -/********************************* BEGIN CPU UTILIZATION MEASUREMENT ****/ -static void Pa_StartUsageCalculation( internalPortAudioStream *past ) -{ - PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; - if( pahsc == NULL ) return; - /* Query system timer for usage analysis and to prevent overuse of CPU. */ - gettimeofday( &pahsc->pahsc_EntryTime, NULL ); -} - -static long SubtractTime_AminusB( struct timeval *timeA, struct timeval *timeB ) -{ - long secs = timeA->tv_sec - timeB->tv_sec; - long usecs = secs * 1000000; - usecs += (timeA->tv_usec - timeB->tv_usec); - return usecs; -} - -/****************************************************************************** -** Measure fractional CPU load based on real-time it took to calculate -** buffers worth of output. -*/ -static void Pa_EndUsageCalculation( internalPortAudioStream *past ) -{ - struct timeval currentTime; - long usecsElapsed; - double newUsage; - -#define LOWPASS_COEFFICIENT_0 (0.95) -#define LOWPASS_COEFFICIENT_1 (0.99999 - LOWPASS_COEFFICIENT_0) - - PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; - if( pahsc == NULL ) return; - - if( gettimeofday( ¤tTime, NULL ) == 0 ) - { - usecsElapsed = SubtractTime_AminusB( ¤tTime, &pahsc->pahsc_EntryTime ); - /* Use inverse because it is faster than the divide. */ - newUsage = usecsElapsed * pahsc->pahsc_InverseMicrosPerBuffer; - - past->past_Usage = (LOWPASS_COEFFICIENT_0 * past->past_Usage) + - (LOWPASS_COEFFICIENT_1 * newUsage); - - } -} -/****************************************** END CPU UTILIZATION *******/ - -/********************************************************************* - * Determines the number of available devices by trying to open - * each "/dev/dsp#" or "/dsp/audio#" in order until it fails. - * Add each working device to a singly linked list of devices. - */ -PaError Pa_QueryDevices( void ) -{ - internalPortAudioDevice *pad, *lastPad; - int go = 1; - int numDevices = 0; - PaError testResult; - PaError result = paNoError; - char *envdev; - - sDefaultInputDeviceID = paNoDevice; - sDefaultOutputDeviceID = paNoDevice; - - lastPad = NULL; - - while( go ) - { - /* Allocate structure to hold device info. */ - pad = (internalPortAudioDevice *) - PaHost_AllocateFastMemory( sizeof(internalPortAudioDevice) ); - if( pad == NULL ) return paInsufficientMemory; - memset( pad, 0, sizeof(internalPortAudioDevice) ); - - /* Build name for device. */ - if( numDevices == 0 ) - { - sprintf( pad->pad_DeviceName, DEVICE_NAME_BASE); - } - else - { - sprintf( pad->pad_DeviceName, DEVICE_NAME_BASE "%d", numDevices ); - } - - DBUG(("Try device %s\n", pad->pad_DeviceName )); - testResult = Pa_QueryDevice( pad->pad_DeviceName, pad ); - DBUG(("Pa_QueryDevice returned %d\n", testResult )); - if( testResult != paNoError ) - { - if( lastPad == NULL ) - { - result = testResult; /* No good devices! */ - } - go = 0; - PaHost_FreeFastMemory( pad, sizeof(internalPortAudioDevice) ); - } - else - { - numDevices += 1; - /* Add to linked list of devices. */ - if( lastPad ) - { - lastPad->pad_Next = pad; - } - else - { - sDeviceList = pad; /* First element in linked list. */ - } - lastPad = pad; - } - } - - /* I'm sitting at a SunRay1 and I neither have /dev/audio# nor /dev/dsp#. - Instead, the correct audio device is stored in the environment variable - AUDIODEV and/or UTAUDIODEV, so check these devices as well if we haven't - checked them yet above - MR */ - - DBUG(("Checking for AUDIODEV and UTAUDIODEV\n")); - envdev = getenv("AUDIODEV"); - if (envdev != NULL && !strstr(envdev, DEVICE_NAME_BASE)) { - result = paNoError; - - /* Allocate structure to hold device info. */ - pad = (internalPortAudioDevice *) - PaHost_AllocateFastMemory( sizeof(internalPortAudioDevice) ); - if( pad == NULL ) return paInsufficientMemory; - memset( pad, 0, sizeof(internalPortAudioDevice) ); - - /* Build name for device. */ - strcpy(pad->pad_DeviceName, envdev); - - DBUG(("Try device %s\n", pad->pad_DeviceName )); - testResult = Pa_QueryDevice( pad->pad_DeviceName, pad ); - DBUG(("Pa_QueryDevice returned %d\n", testResult )); - if( testResult != paNoError ) - { - if( lastPad == NULL ) - { - result = testResult; /* No good devices! */ - } - PaHost_FreeFastMemory( pad, sizeof(internalPortAudioDevice) ); - } - else - { - numDevices += 1; - /* Add to linked list of devices. */ - if( lastPad ) - { - lastPad->pad_Next = pad; - } - else - { - sDeviceList = pad; /* First element in linked list. */ - } - lastPad = pad; - } - } - - envdev = getenv("UTAUDIODEV"); - if (envdev != NULL && !strstr(envdev, DEVICE_NAME_BASE) && getenv("AUDIODEV") != NULL && strcmp(envdev, getenv("AUDIODEV"))) { - result = paNoError; - - /* Allocate structure to hold device info. */ - pad = (internalPortAudioDevice *) - PaHost_AllocateFastMemory( sizeof(internalPortAudioDevice) ); - if( pad == NULL ) return paInsufficientMemory; - memset( pad, 0, sizeof(internalPortAudioDevice) ); - - /* Build name for device. */ - strcpy(pad->pad_DeviceName, envdev); - - DBUG(("Try device %s\n", pad->pad_DeviceName )); - testResult = Pa_QueryDevice( pad->pad_DeviceName, pad ); - DBUG(("Pa_QueryDevice returned %d\n", testResult )); - if( testResult != paNoError ) - { - if( lastPad == NULL ) - { - result = testResult; /* No good devices! */ - } - PaHost_FreeFastMemory( pad, sizeof(internalPortAudioDevice) ); - } - else - { - numDevices += 1; - /* Add to linked list of devices. */ - if( lastPad ) - { - lastPad->pad_Next = pad; - } - else - { - sDeviceList = pad; /* First element in linked list. */ - } - lastPad = pad; - } - } - - return result; -} - -/*************************************************************************/ -int Pa_CountDevices() -{ - int numDevices = 0; - internalPortAudioDevice *pad; - - if( sDeviceList == NULL ) Pa_Initialize(); - /* Count devices in list. */ - pad = sDeviceList; - while( pad != NULL ) - { - pad = pad->pad_Next; - numDevices++; - } - - return numDevices; -} - -/*************************************************************************/ -internalPortAudioDevice *Pa_GetInternalDevice( PaDeviceID id ) -{ - internalPortAudioDevice *pad; - if( (id < 0) || ( id >= Pa_CountDevices()) ) return NULL; - pad = sDeviceList; - while( id > 0 ) - { - pad = pad->pad_Next; - id--; - } - return pad; -} - -/*************************************************************************/ -const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID id ) -{ - internalPortAudioDevice *pad; - if( (id < 0) || ( id >= Pa_CountDevices()) ) return NULL; - pad = Pa_GetInternalDevice( id ); - return &pad->pad_Info ; -} - -static PaError Pa_MaybeQueryDevices( void ) -{ - if( sDeviceList == NULL ) - { - return Pa_QueryDevices(); - } - return 0; -} - -PaDeviceID Pa_GetDefaultInputDeviceID( void ) -{ - /* return paNoDevice; */ - return 0; -} - -PaDeviceID Pa_GetDefaultOutputDeviceID( void ) -{ - return 0; -} - -/********************************************************************** -** Make sure that we have queried the device capabilities. -*/ - -PaError PaHost_Init( void ) -{ - return Pa_MaybeQueryDevices(); -} - -/******************************************************************************************* - * The ol' Canary in a Coal Mine trick. - * Just update the time periodically. - * Runs at low priority so if audio thread runs wild, this thread will get starved - * and the watchdog will detect it. - */ - -#define SCHEDULER_POLICY SCHED_RR -#define WATCHDOG_MAX_SECONDS (3) -#define WATCHDOG_INTERVAL_USEC (1000000) - -static int PaHost_CanaryProc( PaHostSoundControl *pahsc ) -{ - int result = 0; - -#ifdef GNUSTEP - GSRegisterCurrentThread(); /* SB20010904 */ -#endif - - while( pahsc->pahsc_CanaryRun) { - usleep( WATCHDOG_INTERVAL_USEC ); - gettimeofday( &pahsc->pahsc_CanaryTime, NULL ); - } - - DBUG(("PaHost_CanaryProc: exiting.\n")); - -#ifdef GNUSTEP - GSUnregisterCurrentThread(); /* SB20010904 */ -#endif - - return result; -} - -/******************************************************************************************* - * Monitor audio thread and lower its it if it hogs the CPU. - * To prevent getting killed, the audio thread must update a - * variable with a timer value. - * If the value is not recent enough, then the - * thread will get killed. - */ - -static PaError PaHost_WatchDogProc( PaHostSoundControl *pahsc ) -{ - struct sched_param schp = { 0 }; - int maxPri; - -#ifdef GNUSTEP - GSRegisterCurrentThread(); /* SB20010904 */ -#endif - -/* Run at a priority level above audio thread so we can still run if it hangs. */ -/* Rise more than 1 because of rumored off-by-one scheduler bugs. */ - schp.sched_priority = pahsc->pahsc_AudioPriority + 4; - maxPri = sched_get_priority_max(SCHEDULER_POLICY); - if( schp.sched_priority > maxPri ) schp.sched_priority = maxPri; - - if (sched_setscheduler(0, SCHEDULER_POLICY, &schp) != 0) - { - ERR_RPT(("PaHost_WatchDogProc: cannot set watch dog priority!\n")); - goto killAudio; - } - - /* Compare watchdog time with audio and canary thread times. */ - /* Sleep for a while or until thread cancelled. */ - while( pahsc->pahsc_WatchDogRun ) - { - - int delta; - struct timeval currentTime; - - usleep( WATCHDOG_INTERVAL_USEC ); - gettimeofday( ¤tTime, NULL ); - - /* If audio thread is not advancing, then it must be hung so kill it. */ - delta = currentTime.tv_sec - pahsc->pahsc_EntryTime.tv_sec; - DBUG(("PaHost_WatchDogProc: audio delta = %d\n", delta )); - if( delta > WATCHDOG_MAX_SECONDS ) - { - goto killAudio; - } - - /* If canary died, then lower audio priority and halt canary. */ - delta = currentTime.tv_sec - pahsc->pahsc_CanaryTime.tv_sec; - if( delta > WATCHDOG_MAX_SECONDS ) - { - ERR_RPT(("PaHost_WatchDogProc: canary died!\n")); - goto lowerAudio; - } - } - - DBUG(("PaHost_WatchDogProc: exiting.\n")); -#ifdef GNUSTEP - GSUnregisterCurrentThread(); /* SB20010904 */ -#endif - return 0; - -lowerAudio: - { - struct sched_param schat = { 0 }; - if( sched_setscheduler(pahsc->pahsc_AudioThreadPID, SCHED_OTHER, &schat) != 0) - { - ERR_RPT(("PaHost_WatchDogProc: failed to lower audio priority. errno = %d\n", errno )); - /* Fall through into killing audio thread. */ - } - else - { - ERR_RPT(("PaHost_WatchDogProc: lowered audio priority to prevent hogging of CPU.\n")); - goto cleanup; - } - } - -killAudio: - ERR_RPT(("PaHost_WatchDogProc: killing hung audio thread!\n")); - pthread_kill( pahsc->pahsc_AudioThread, SIGKILL ); - -cleanup: - pahsc->pahsc_CanaryRun = 0; - DBUG(("PaHost_WatchDogProc: cancel Canary\n")); - pthread_cancel( pahsc->pahsc_CanaryThread ); - DBUG(("PaHost_WatchDogProc: join Canary\n")); - pthread_join( pahsc->pahsc_CanaryThread, NULL ); - DBUG(("PaHost_WatchDogProc: forget Canary\n")); - pahsc->pahsc_IsCanaryThreadValid = 0; - -#ifdef GNUSTEP - GSUnregisterCurrentThread(); /* SB20010904 */ -#endif - return 0; -} - -/*******************************************************************************************/ -static void PaHost_StopWatchDog( PaHostSoundControl *pahsc ) -{ -/* Cancel WatchDog thread if there is one. */ - if( pahsc->pahsc_IsWatchDogThreadValid ) - { - pahsc->pahsc_WatchDogRun = 0; - DBUG(("PaHost_StopWatchDog: cancel WatchDog\n")); - pthread_cancel( pahsc->pahsc_WatchDogThread ); - pthread_join( pahsc->pahsc_WatchDogThread, NULL ); - pahsc->pahsc_IsWatchDogThreadValid = 0; - } -/* Cancel Canary thread if there is one. */ - if( pahsc->pahsc_IsCanaryThreadValid ) - { - pahsc->pahsc_CanaryRun = 0; - DBUG(("PaHost_StopWatchDog: cancel Canary\n")); - pthread_cancel( pahsc->pahsc_CanaryThread ); - DBUG(("PaHost_StopWatchDog: join Canary\n")); - pthread_join( pahsc->pahsc_CanaryThread, NULL ); - pahsc->pahsc_IsCanaryThreadValid = 0; - } -} - -/*******************************************************************************************/ -static PaError PaHost_StartWatchDog( PaHostSoundControl *pahsc ) -{ - int hres; - PaError result = 0; - - /* The watch dog watches for these timer updates */ - gettimeofday( &pahsc->pahsc_EntryTime, NULL ); - gettimeofday( &pahsc->pahsc_CanaryTime, NULL ); - - /* Launch a canary thread to detect priority abuse. */ - pahsc->pahsc_CanaryRun = 1; - hres = pthread_create(&(pahsc->pahsc_CanaryThread), - NULL /*pthread_attr_t * attr*/, - (pthread_function_t)PaHost_CanaryProc, pahsc); - if( hres != 0 ) - { - pahsc->pahsc_IsCanaryThreadValid = 0; - result = paHostError; - sPaHostError = hres; - goto error; - } - pahsc->pahsc_IsCanaryThreadValid = 1; - - /* Launch a watchdog thread to prevent runaway audio thread. */ - pahsc->pahsc_WatchDogRun = 1; - hres = pthread_create(&(pahsc->pahsc_WatchDogThread), - NULL /*pthread_attr_t * attr*/, - (pthread_function_t)PaHost_WatchDogProc, pahsc); - if( hres != 0 ) - { - pahsc->pahsc_IsWatchDogThreadValid = 0; - result = paHostError; - sPaHostError = hres; - goto error; - } - pahsc->pahsc_IsWatchDogThreadValid = 1; - return result; - -error: - PaHost_StopWatchDog( pahsc ); - return result; -} - -/******************************************************************************************* - * Bump priority of audio thread if running with superuser priveledges. - * if priority bumped then launch a watchdog. - */ -static PaError PaHost_BoostPriority( internalPortAudioStream *past ) -{ - PaHostSoundControl *pahsc; - PaError result = paNoError; - struct sched_param schp = { 0 }; - - pahsc = (PaHostSoundControl *) past->past_DeviceData; - if( pahsc == NULL ) return paInternalError; - - pahsc->pahsc_AudioThreadPID = getpid(); - DBUG(("PaHost_BoostPriority: audio PID = %d\n", pahsc->pahsc_AudioThreadPID )); - - /* Choose a priority in the middle of the range. */ - pahsc->pahsc_AudioPriority = (sched_get_priority_max(SCHEDULER_POLICY) - - sched_get_priority_min(SCHEDULER_POLICY)) / 2; - schp.sched_priority = pahsc->pahsc_AudioPriority; - - if (sched_setscheduler(0, SCHEDULER_POLICY, &schp) != 0) - { - DBUG(("PortAudio: only superuser can use real-time priority.\n")); - } - else - { - DBUG(("PortAudio: audio callback priority set to level %d!\n", schp.sched_priority)); - /* We are running at high priority so we should have a watchdog in case audio goes wild. */ - result = PaHost_StartWatchDog( pahsc ); - } - - return result; -} - -/*******************************************************************************************/ -static PaError Pa_AudioThreadProc( internalPortAudioStream *past ) -{ - PaError result; - PaHostSoundControl *pahsc; - ssize_t bytes_read, bytes_written; - - pahsc = (PaHostSoundControl *) past->past_DeviceData; - if( pahsc == NULL ) return paInternalError; - -#ifdef GNUSTEP - GSRegisterCurrentThread(); /* SB20010904 */ -#endif - - result = PaHost_BoostPriority( past ); - if( result < 0 ) goto error; - - past->past_IsActive = 1; - DBUG(("entering thread.\n")); - - while( (past->past_StopNow == 0) && (past->past_StopSoon == 0) ) - { - /* Read data from device */ - if(pahsc->pahsc_NativeInputBuffer) - { - unsigned int totalread = 0; - DBUG(("Pa_AudioThreadProc: attempt to read %d bytes\n", pahsc->pahsc_BytesPerInputBuffer)); - do - { - bytes_read = read(pahsc->pahsc_InputHandle, - (char *)pahsc->pahsc_NativeInputBuffer + totalread, - pahsc->pahsc_BytesPerInputBuffer - totalread); - - if (bytes_read < 0) - { - ERR_RPT(("PortAudio: read interrupted!\n")); - break; - } - - totalread += bytes_read; - } while( totalread < pahsc->pahsc_BytesPerInputBuffer); - } - - /* Convert 16 bit native data to user data and call user routine. */ - DBUG(("converting...\n")); - Pa_StartUsageCalculation( past ); - result = Pa_CallConvertInt16( past, - pahsc->pahsc_NativeInputBuffer, - pahsc->pahsc_NativeOutputBuffer ); - Pa_EndUsageCalculation( past ); - if( result != 0) - { - DBUG(("hmm, Pa_CallConvertInt16() says: %d. i'm bailing.\n", - result)); - break; - } - - /* Write data to device. */ - if( pahsc->pahsc_NativeOutputBuffer ) - { - unsigned int totalwritten = 0; - do - { - bytes_written = write(pahsc->pahsc_OutputHandle, - (void *)pahsc->pahsc_NativeOutputBuffer, - pahsc->pahsc_BytesPerOutputBuffer); - if( bytes_written < 0 ) - { - ERR_RPT(("PortAudio: write interrupted!")); - break; - } - - totalwritten += bytes_written; - } while( totalwritten < pahsc->pahsc_BytesPerOutputBuffer); - } - - Pa_UpdateStreamTime(pahsc); - } - DBUG(("Pa_AudioThreadProc: left audio loop.\n")); - - past->past_IsActive = 0; - PaHost_StopWatchDog( pahsc ); - -error: - DBUG(("leaving audio thread.\n")); -#ifdef GNUSTEP - GSUnregisterCurrentThread(); /* SB20010904 */ -#endif - return result; -} - -/************************************************************************* -** Determine minimum number of buffers required for this host based -** on minimum latency. Latency can be optionally set by user by setting -** an environment variable. For example, to set latency to 200 msec, put: -** -** set PA_MIN_LATENCY_MSEC=200 -** -** in the cshrc file. -*/ -#define PA_LATENCY_ENV_NAME ("PA_MIN_LATENCY_MSEC") - -int Pa_GetMinNumBuffers( int framesPerBuffer, double framesPerSecond ) -{ - int minBuffers; - int minLatencyMsec = MIN_LATENCY_MSEC; - char *minLatencyText = getenv(PA_LATENCY_ENV_NAME); - if( minLatencyText != NULL ) - { - PRINT(("PA_MIN_LATENCY_MSEC = %s\n", minLatencyText )); - minLatencyMsec = atoi( minLatencyText ); - if( minLatencyMsec < 1 ) minLatencyMsec = 1; - else if( minLatencyMsec > 5000 ) minLatencyMsec = 5000; - } - - minBuffers = (int) ((minLatencyMsec * framesPerSecond) / ( 1000.0 * framesPerBuffer )); - if( minBuffers < 2 ) minBuffers = 2; - return minBuffers; -} - -/*******************************************************************/ -PaError PaHost_OpenStream( internalPortAudioStream *past ) -{ - PaError result = paNoError; - PaHostSoundControl *pahsc; - unsigned int minNumBuffers; - internalPortAudioDevice *pad; - DBUG(("PaHost_OpenStream() called.\n" )); - - /* Allocate and initialize host data. */ - pahsc = (PaHostSoundControl *) malloc(sizeof(PaHostSoundControl)); - if( pahsc == NULL ) - { - result = paInsufficientMemory; - goto error; - } - memset( pahsc, 0, sizeof(PaHostSoundControl) ); - past->past_DeviceData = (void *) pahsc; - - pahsc->pahsc_OutputHandle = BAD_DEVICE_ID; /* No device currently opened. */ - pahsc->pahsc_InputHandle = BAD_DEVICE_ID; - pahsc->pahsc_IsAudioThreadValid = 0; - pahsc->pahsc_IsWatchDogThreadValid = 0; - - /* Allocate native buffers. */ - pahsc->pahsc_BytesPerInputBuffer = past->past_FramesPerUserBuffer * - past->past_NumInputChannels * sizeof(short); - if( past->past_NumInputChannels > 0) - { - pahsc->pahsc_NativeInputBuffer = (short *) malloc(pahsc->pahsc_BytesPerInputBuffer); - if( pahsc->pahsc_NativeInputBuffer == NULL ) - { - result = paInsufficientMemory; - goto error; - } - } - pahsc->pahsc_BytesPerOutputBuffer = past->past_FramesPerUserBuffer * - past->past_NumOutputChannels * sizeof(short); - if( past->past_NumOutputChannels > 0) - { - pahsc->pahsc_NativeOutputBuffer = (short *) malloc(pahsc->pahsc_BytesPerOutputBuffer); - if( pahsc->pahsc_NativeOutputBuffer == NULL ) - { - result = paInsufficientMemory; - goto error; - } - } - - /* DBUG(("PaHost_OpenStream: pahsc_MinFramesPerHostBuffer = %d\n", pahsc->pahsc_MinFramesPerHostBuffer )); */ - minNumBuffers = Pa_GetMinNumBuffers( past->past_FramesPerUserBuffer, past->past_SampleRate ); - past->past_NumUserBuffers = ( minNumBuffers > past->past_NumUserBuffers ) ? minNumBuffers : past->past_NumUserBuffers; - - pahsc->pahsc_InverseMicrosPerBuffer = past->past_SampleRate / (1000000.0 * past->past_FramesPerUserBuffer); - DBUG(("past_SampleRate = %g\n", past->past_SampleRate )); - DBUG(("past_FramesPerUserBuffer = %d\n", past->past_FramesPerUserBuffer )); - DBUG(("pahsc_InverseMicrosPerBuffer = %g\n", pahsc->pahsc_InverseMicrosPerBuffer )); - - /* ------------------------- OPEN DEVICE -----------------------*/ - - /* just output */ - if (past->past_OutputDeviceID == past->past_InputDeviceID) - { - - if ((past->past_NumOutputChannels > 0) && (past->past_NumInputChannels > 0) ) - { - pad = Pa_GetInternalDevice( past->past_OutputDeviceID ); - DBUG(("PaHost_OpenStream: attempt to open %s for O_RDWR\n", pad->pad_DeviceName )); - - /* dmazzoni: test it first in nonblocking mode to - make sure the device is not busy */ - pahsc->pahsc_InputHandle = open(pad->pad_DeviceName,O_RDWR|O_NONBLOCK); - if(pahsc->pahsc_InputHandle==-1) - { - ERR_RPT(("PaHost_OpenStream: could not open %s for O_RDWR\n", pad->pad_DeviceName )); - result = paHostError; - goto error; - } - close(pahsc->pahsc_InputHandle); - - pahsc->pahsc_OutputHandle = pahsc->pahsc_InputHandle = - open(pad->pad_DeviceName,O_RDWR); - if(pahsc->pahsc_InputHandle==-1) - { - ERR_RPT(("PaHost_OpenStream: could not open %s for O_RDWR\n", pad->pad_DeviceName )); - result = paHostError; - goto error; - } - Pa_SetLatency( pahsc->pahsc_OutputHandle, - past->past_NumUserBuffers, past->past_FramesPerUserBuffer, - past->past_NumOutputChannels ); - result = Pa_SetupDeviceFormat( pahsc->pahsc_OutputHandle, - past->past_NumOutputChannels, (int)past->past_SampleRate ); - } - } - else - { - if (past->past_NumOutputChannels > 0) - { - pad = Pa_GetInternalDevice( past->past_OutputDeviceID ); - DBUG(("PaHost_OpenStream: attempt to open %s for O_WRONLY\n", pad->pad_DeviceName )); - /* dmazzoni: test it first in nonblocking mode to - make sure the device is not busy */ - pahsc->pahsc_OutputHandle = open(pad->pad_DeviceName,O_WRONLY|O_NONBLOCK); - if(pahsc->pahsc_OutputHandle==-1) - { - ERR_RPT(("PaHost_OpenStream: could not open %s for O_WRONLY\n", pad->pad_DeviceName )); - result = paHostError; - goto error; - } - close(pahsc->pahsc_OutputHandle); - - pahsc->pahsc_OutputHandle = open(pad->pad_DeviceName,O_WRONLY); - if(pahsc->pahsc_OutputHandle==-1) - { - ERR_RPT(("PaHost_OpenStream: could not open %s for O_WRONLY\n", pad->pad_DeviceName )); - result = paHostError; - goto error; - } - Pa_SetLatency( pahsc->pahsc_OutputHandle, - past->past_NumUserBuffers, past->past_FramesPerUserBuffer, - past->past_NumOutputChannels ); - result = Pa_SetupOutputDeviceFormat( pahsc->pahsc_OutputHandle, - past->past_NumOutputChannels, (int)past->past_SampleRate ); - } - - if (past->past_NumInputChannels > 0) - { - pad = Pa_GetInternalDevice( past->past_InputDeviceID ); - DBUG(("PaHost_OpenStream: attempt to open %s for O_RDONLY\n", pad->pad_DeviceName )); - /* dmazzoni: test it first in nonblocking mode to - make sure the device is not busy */ - pahsc->pahsc_InputHandle = open(pad->pad_DeviceName,O_RDONLY|O_NONBLOCK); - if(pahsc->pahsc_InputHandle==-1) - { - ERR_RPT(("PaHost_OpenStream: could not open %s for O_RDONLY\n", pad->pad_DeviceName )); - result = paHostError; - goto error; - } - close(pahsc->pahsc_InputHandle); - - pahsc->pahsc_InputHandle = open(pad->pad_DeviceName,O_RDONLY); - if(pahsc->pahsc_InputHandle==-1) - { - ERR_RPT(("PaHost_OpenStream: could not open %s for O_RDONLY\n", pad->pad_DeviceName )); - result = paHostError; - goto error; - } - Pa_SetLatency( pahsc->pahsc_InputHandle, /* DH20010115 - was OutputHandle! */ - past->past_NumUserBuffers, past->past_FramesPerUserBuffer, - past->past_NumInputChannels ); - result = Pa_SetupInputDeviceFormat( pahsc->pahsc_InputHandle, - past->past_NumInputChannels, (int)past->past_SampleRate ); - } - } - - - DBUG(("PaHost_OpenStream: SUCCESS - result = %d\n", result )); - return result; - -error: - ERR_RPT(("PaHost_OpenStream: ERROR - result = %d\n", result )); - PaHost_CloseStream( past ); - return result; -} - -/*************************************************************************/ -PaError PaHost_StartOutput( internalPortAudioStream *past ) -{ - past = past; /* unused */ - return paNoError; -} - -/*************************************************************************/ -PaError PaHost_StartInput( internalPortAudioStream *past ) -{ - past = past; /* unused */ - return paNoError; -} - -/*************************************************************************/ -PaError PaHost_StartEngine( internalPortAudioStream *past ) -{ - PaHostSoundControl *pahsc; - PaError result = paNoError; - int hres; - - pahsc = (PaHostSoundControl *) past->past_DeviceData; - - past->past_StopSoon = 0; - past->past_StopNow = 0; - past->past_IsActive = 1; - - /* Use pthread_create() instead of __clone() because: - * - pthread_create also works for other UNIX systems like Solaris, - * - the Java HotSpot VM crashes in pthread_setcanceltype() when using __clone() - */ - hres = pthread_create(&(pahsc->pahsc_AudioThread), - NULL /*pthread_attr_t * attr*/, - (pthread_function_t)Pa_AudioThreadProc, past); - if( hres != 0 ) - { - result = paHostError; - sPaHostError = hres; - pahsc->pahsc_IsAudioThreadValid = 0; - goto error; - } - pahsc->pahsc_IsAudioThreadValid = 1; - -error: - return result; -} - -/*************************************************************************/ -PaError PaHost_StopEngine( internalPortAudioStream *past, int abort ) -{ - int hres; - PaError result = paNoError; - PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; - - if( pahsc == NULL ) return paNoError; - - /* Tell background thread to stop generating more data and to let current data play out. */ - past->past_StopSoon = 1; - /* If aborting, tell background thread to stop NOW! */ - if( abort ) past->past_StopNow = 1; - - /* Join thread to recover memory resources. */ - if( pahsc->pahsc_IsAudioThreadValid ) - { - /* This check is needed for GNUSTEP - SB20010904 */ - if ( !pthread_equal( pahsc->pahsc_AudioThread, pthread_self() ) ) - { - hres = pthread_join( pahsc->pahsc_AudioThread, NULL ); - } - else - { - DBUG(("Play thread was stopped from itself - can't do pthread_join()\n")); - hres = 0; - } - - if( hres != 0 ) - { - result = paHostError; - sPaHostError = hres; - } - pahsc->pahsc_IsAudioThreadValid = 0; - } - - past->past_IsActive = 0; - - return result; -} - -/*************************************************************************/ -PaError PaHost_StopInput( internalPortAudioStream *past, int abort ) -{ - past = past; /* unused */ - abort = abort; /* unused */ - return paNoError; -} - -/*************************************************************************/ -PaError PaHost_StopOutput( internalPortAudioStream *past, int abort ) -{ - past = past; /* unused */ - abort = abort; /* unused */ - return paNoError; -} - -/*******************************************************************/ -PaError PaHost_CloseStream( internalPortAudioStream *past ) -{ - PaHostSoundControl *pahsc; - - if( past == NULL ) return paBadStreamPtr; - pahsc = (PaHostSoundControl *) past->past_DeviceData; - if( pahsc == NULL ) return paNoError; - - if( pahsc->pahsc_OutputHandle != BAD_DEVICE_ID ) - { - int err = 0; - DBUG(("PaHost_CloseStream: attempt to close output device handle = %d\n", - pahsc->pahsc_OutputHandle )); - - Pa_FlushStream(pahsc->pahsc_OutputHandle); - - err = close(pahsc->pahsc_OutputHandle); - if( err < 0 ) - { - ERR_RPT(("PaHost_CloseStream: warning, closing output device failed.\n")); - } - } - - if( (pahsc->pahsc_InputHandle != BAD_DEVICE_ID) && - (pahsc->pahsc_InputHandle != pahsc->pahsc_OutputHandle) ) - { - int err = 0; - DBUG(("PaHost_CloseStream: attempt to close input device handle = %d\n", - pahsc->pahsc_InputHandle )); - - Pa_FlushStream(pahsc->pahsc_InputHandle); - - err = close(pahsc->pahsc_InputHandle); - if( err < 0 ) - { - ERR_RPT(("PaHost_CloseStream: warning, closing input device failed.\n")); - } - } - pahsc->pahsc_OutputHandle = BAD_DEVICE_ID; - pahsc->pahsc_InputHandle = BAD_DEVICE_ID; - - if( pahsc->pahsc_NativeInputBuffer ) - { - free( pahsc->pahsc_NativeInputBuffer ); - pahsc->pahsc_NativeInputBuffer = NULL; - } - if( pahsc->pahsc_NativeOutputBuffer ) - { - free( pahsc->pahsc_NativeOutputBuffer ); - pahsc->pahsc_NativeOutputBuffer = NULL; - } - - free( pahsc ); - past->past_DeviceData = NULL; - return paNoError; -} - -/*************************************************************************/ -PaError PaHost_Term( void ) -{ - /* Free all of the linked devices. */ - internalPortAudioDevice *pad, *nextPad; - pad = sDeviceList; - while( pad != NULL ) - { - nextPad = pad->pad_Next; - DBUG(("PaHost_Term: freeing %s\n", pad->pad_DeviceName )); - PaHost_FreeFastMemory( pad, sizeof(internalPortAudioDevice) ); - pad = nextPad; - } - sDeviceList = NULL; - return 0; -} - -/************************************************************************* - * Sleep for the requested number of milliseconds. - */ -void Pa_Sleep( long msec ) -{ -#if 0 - struct timeval timeout; - timeout.tv_sec = msec / 1000; - timeout.tv_usec = (msec % 1000) * 1000; - select( 0, NULL, NULL, NULL, &timeout ); -#else - long usecs = msec * 1000; - usleep( usecs ); -#endif -} - -/************************************************************************* - * Allocate memory that can be accessed in real-time. - * This may need to be held in physical memory so that it is not - * paged to virtual memory. - * This call MUST be balanced with a call to PaHost_FreeFastMemory(). - */ -void *PaHost_AllocateFastMemory( long numBytes ) -{ - void *addr = malloc( numBytes ); /* FIXME - do we need physical, wired, non-virtual memory? */ - if( addr != NULL ) memset( addr, 0, numBytes ); - return addr; -} - -/************************************************************************* - * Free memory that could be accessed in real-time. - * This call MUST be balanced with a call to PaHost_AllocateFastMemory(). - */ -void PaHost_FreeFastMemory( void *addr, long numBytes ) -{ - numBytes = numBytes; /* unused */ - if( addr != NULL ) free( addr ); -} - - -/***********************************************************************/ -PaError PaHost_StreamActive( internalPortAudioStream *past ) -{ - PaHostSoundControl *pahsc; - if( past == NULL ) return paBadStreamPtr; - pahsc = (PaHostSoundControl *) past->past_DeviceData; - if( pahsc == NULL ) return paInternalError; - return (PaError) (past->past_IsActive != 0); -} - -/***********************************************************************/ -long Pa_GetHostError( void ) -{ - return (long) sPaHostError; -} - - -#endif // HAVE_LINUX diff --git a/branches/lydia/portaudio/pa_unix.h b/branches/lydia/portaudio/pa_unix.h deleted file mode 100644 index 55b16d5..0000000 --- a/branches/lydia/portaudio/pa_unix.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * PortAudio Portable Real-Time Audio Library - * Latest Version at: http://www.portaudio.com - * Linux OSS Implementation by douglas repetto and Phil Burk - * - * Copyright (c) 1999-2000 Phil Burk - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * Any person wishing to distribute modifications to the Software is - * requested to send the modifications to the original developer so that - * they can be incorporated into the canonical version. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -/* Modification history: - 20020621: pa_unix_oss.c split into pa_unix.c, pa_unix.h, pa_unix_oss.c by - Augustus Saunders. See pa_unix.c for previous history. */ - -/* - PROPOSED - should we add this to "portaudio.h". Problem with - Pa_QueryDevice() not having same driver name os Pa_OpenStream(). - - A PaDriverInfo structure can be passed to the underlying device - on the Pa_OpenStream() call. The contents and interpretation of - the structure is determined by the PA implementation. -*/ -typedef struct PaDriverInfo /* PROPOSED */ -{ - /* Size of structure. Allows driver to extend the structure without breaking existing applications. */ - int size; - /* Can be used to request a specific device name. */ - const char *name; - unsigned long data; -} -PaDriverInfo; - -#include -#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "portaudio.h" -#include "pa_host.h" -#include "pa_trace.h" - -#define PRINT(x) { printf x; fflush(stdout); } -#define ERR_RPT(x) PRINT(x) -#define DBUG(x) /* PRINT(x) */ -#define DBUGX(x) /* PRINT(x) */ - -#define BAD_DEVICE_ID (-1) - -#define MIN_LATENCY_MSEC (100) -#define MIN_TIMEOUT_MSEC (100) -#define MAX_TIMEOUT_MSEC (1000) - -/************************************************* Definitions ********/ -#ifdef __linux__ - #define DEVICE_NAME_BASE "/dev/dsp" -#else - #define DEVICE_NAME_BASE "/dev/audio" -#endif - -#define MAX_CHARS_DEVNAME (32) -#define MAX_SAMPLE_RATES (10) -typedef struct internalPortAudioDevice -{ - struct internalPortAudioDevice *pad_Next; /* Singly linked list. */ - double pad_SampleRates[MAX_SAMPLE_RATES]; /* for pointing to from pad_Info */ - char pad_DeviceName[MAX_CHARS_DEVNAME]; - PaDeviceInfo pad_Info; -} -internalPortAudioDevice; - -/* Define structure to contain all OSS and Linux specific data. */ -typedef struct PaHostSoundControl -{ - int pahsc_OutputHandle; - int pahsc_InputHandle; - int pahsc_AudioPriority; /* priority of background audio thread */ - pthread_t pahsc_AudioThread; /* background audio thread */ - int pahsc_IsAudioThreadValid; /* Is pahsc_AudioThread valid?*/ pid_t pahsc_AudioThreadPID; /* background audio thread */ - pthread_t pahsc_WatchDogThread; /* highest priority thread that protects system */ - int pahsc_IsWatchDogThreadValid; /* Is pahsc_WatchDogThread valid?*/ - int pahsc_WatchDogRun; /* Ask WatchDog to stop. */ - pthread_t pahsc_CanaryThread; /* low priority thread that detects abuse by audio */ - int pahsc_IsCanaryThreadValid; /* Is pahsc_CanaryThread valid?*/ - struct timeval pahsc_CanaryTime; - int pahsc_CanaryRun; /* Ask Canary to stop. */ - short *pahsc_NativeInputBuffer; - short *pahsc_NativeOutputBuffer; - unsigned int pahsc_BytesPerInputBuffer; /* native buffer size in bytes */ - unsigned int pahsc_BytesPerOutputBuffer; /* native buffer size in bytes */ - /* For measuring CPU utilization. */ - struct timeval pahsc_EntryTime; - double pahsc_InverseMicrosPerBuffer; /* 1/Microseconds of real-time audio per user buffer. */ - - /* For calculating stream time */ - int pahsc_LastPosPtr; - double pahsc_LastStreamBytes; -} -PaHostSoundControl; - -/************************************************* Prototypes **********/ - -internalPortAudioDevice *Pa_GetInternalDevice( PaDeviceID id ); -PaError Pa_QueryDevices( void ); -PaError Pa_QueryDevice( const char *deviceName, internalPortAudioDevice *pad ); -PaError Pa_SetupDeviceFormat( int devHandle, int numChannels, int sampleRate ); -PaError Pa_SetupInputDeviceFormat( int devHandle, int numChannels, int sampleRate ); -PaError Pa_SetupOutputDeviceFormat( int devHandle, int numChannels, int sampleRate ); -void Pa_SetLatency( int devHandle, int numBuffers, int framesPerBuffer, int channelsPerFrame ); -void Pa_UpdateStreamTime(PaHostSoundControl *pahsc); -int Pa_FlushStream(int devHandle); diff --git a/branches/lydia/portaudio/pa_unix_oss.c b/branches/lydia/portaudio/pa_unix_oss.c deleted file mode 100644 index 01f93d8..0000000 --- a/branches/lydia/portaudio/pa_unix_oss.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * PortAudio Portable Real-Time Audio Library - * Latest Version at: http://www.portaudio.com - * Linux OSS Implementation by douglas repetto and Phil Burk - * - * Copyright (c) 1999-2000 Phil Burk - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * Any person wishing to distribute modifications to the Software is - * requested to send the modifications to the original developer so that - * they can be incorporated into the canonical version. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -/* Modification history: - 20020621: pa_unix_oss.c split into pa_unix.c, pa_unix.h, pa_unix_oss.c by - Augustus Saunders. See pa_unix.c for previous history. Pa_FlushStream - added by Augustus Saunders for Solaris compatibility. - PLB20021018 - Fill device info table with actual sample rates instead of wished for rates. - - Allow stream to open if sample rate within 10% of desired rate. - 20030630 - Thomas Richter - eliminated unused variable warnings. -*/ - -#define HAVE_UNIX 1 -#define HAVE_LINUX 1 - -#ifdef HAVE_UNIX - -#include "pa_unix.h" - -#ifdef HAVE_LINUX -#include -#else - -#ifdef HAVE_BSD -#include -#else -#include /* JH20010905 */ -#endif - -#endif - -#ifndef AFMT_S16_NE -#define AFMT_S16_NE Get_AFMT_S16_NE() -/********************************************************************* - * Some versions of OSS do not define AFMT_S16_NE. So check CPU. - * PowerPC is Big Endian. X86 is Little Endian. - */ -int Get_AFMT_S16_NE( void ) -{ - long testData = 1; - char *ptr = (char *) &testData; - int isLittle = ( *ptr == 1 ); /* Does address point to least significant byte? */ - return isLittle ? AFMT_S16_LE : AFMT_S16_BE; -} -#endif /* AFMT_S16_NE */ - - -/********************************************************************* - * Try to open the named device. - * If it opens, try to set various rates and formats and fill in - * the device info structure. - */ -PaError Pa_QueryDevice( const char *deviceName, internalPortAudioDevice *pad ) -{ - int result = paHostError; - int tempDevHandle; - int numChannels, maxNumChannels; - int format; - int numSampleRates; - int sampleRate; - int numRatesToTry; - int lastRate; - int ratesToTry[9] = {96000, 48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000}; - int i; - - /* douglas: - we have to do this querying in a slightly different order. apparently - some sound cards will give you different info based on their settings. - e.g. a card might give you stereo at 22kHz but only mono at 44kHz. - the correct order for OSS is: format, channels, sample rate - - */ - if ( (tempDevHandle = open(deviceName,O_WRONLY|O_NONBLOCK)) == -1 ) - { - DBUG(("Pa_QueryDevice: could not open %s\n", deviceName )); - return paHostError; - } - - /* Ask OSS what formats are supported by the hardware. */ - pad->pad_Info.nativeSampleFormats = 0; - - if (ioctl(tempDevHandle, SNDCTL_DSP_GETFMTS, &format) == -1) - { - ERR_RPT(("Pa_QueryDevice: could not get format info\n" )); - goto error; - } - if( format & AFMT_U8 ) pad->pad_Info.nativeSampleFormats |= paUInt8; - if( format & AFMT_S16_NE ) pad->pad_Info.nativeSampleFormats |= paInt16; - - /* Negotiate for the maximum number of channels for this device. PLB20010927 - * Consider up to 16 as the upper number of channels. - * Variable numChannels should contain the actual upper limit after the call. - * Thanks to John Lazzaro and Heiko Purnhagen for suggestions. - */ - maxNumChannels = 0; - for( numChannels = 1; numChannels <= 16; numChannels++ ) - { - int temp = numChannels; - DBUG(("Pa_QueryDevice: use SNDCTL_DSP_CHANNELS, numChannels = %d\n", numChannels )) - if(ioctl(tempDevHandle, SNDCTL_DSP_CHANNELS, &temp) < 0 ) - { - /* ioctl() failed so bail out if we already have stereo */ - if( numChannels > 2 ) break; - } - else - { - /* ioctl() worked but bail out if it does not support numChannels. - * We don't want to leave gaps in the numChannels supported. - */ - if( (numChannels > 2) && (temp != numChannels) ) break; - DBUG(("Pa_QueryDevice: temp = %d\n", temp )) - if( temp > maxNumChannels ) maxNumChannels = temp; /* Save maximum. */ - } - } - - /* The above negotiation may fail for an old driver so try this older technique. */ - if( maxNumChannels < 1 ) - { - int stereo = 1; - if(ioctl(tempDevHandle, SNDCTL_DSP_STEREO, &stereo) < 0) - { - maxNumChannels = 1; - } - else - { - maxNumChannels = (stereo) ? 2 : 1; - } - DBUG(("Pa_QueryDevice: use SNDCTL_DSP_STEREO, maxNumChannels = %d\n", maxNumChannels )) - } - - pad->pad_Info.maxOutputChannels = maxNumChannels; - DBUG(("Pa_QueryDevice: maxNumChannels = %d\n", maxNumChannels)) - - /* During channel negotiation, the last ioctl() may have failed. This can - * also cause sample rate negotiation to fail. Hence the following, to return - * to a supported number of channels. SG20011005 */ - { - int temp = maxNumChannels; - if( temp > 2 ) temp = 2; /* use most reasonable default value */ - ioctl(tempDevHandle, SNDCTL_DSP_CHANNELS, &temp); - } - - /* FIXME - for now, assume maxInputChannels = maxOutputChannels. - * Eventually do separate queries for O_WRONLY and O_RDONLY - */ - pad->pad_Info.maxInputChannels = pad->pad_Info.maxOutputChannels; - - DBUG(("Pa_QueryDevice: maxInputChannels = %d\n", - pad->pad_Info.maxInputChannels)) - - - /* Determine available sample rates by trying each one and seeing result. - * OSS often supports funky rates such as 44188 instead of 44100! - */ - numSampleRates = 0; - lastRate = 0; - numRatesToTry = sizeof(ratesToTry)/sizeof(int); - for (i = 0; i < numRatesToTry; i++) - { - sampleRate = ratesToTry[i]; - - if (ioctl(tempDevHandle, SNDCTL_DSP_SPEED, &sampleRate) >= 0 ) /* PLB20010817 */ - { - /* Use whatever rate OSS tells us. PLB20021018 */ - if (sampleRate != lastRate) - { - DBUG(("Pa_QueryDevice: adding sample rate: %d\n", sampleRate)) - pad->pad_SampleRates[numSampleRates] = (float)sampleRate; - numSampleRates++; - lastRate = sampleRate; - } - else - { - DBUG(("Pa_QueryDevice: dang - got sample rate %d again!\n", sampleRate)) - } - } - } - - DBUG(("Pa_QueryDevice: final numSampleRates = %d\n", numSampleRates)) - if (numSampleRates==0) /* HP20010922 */ - { - /* Desparate attempt to keep running even though no good rates found! */ - ERR_RPT(("Pa_QueryDevice: no supported sample rate (or SNDCTL_DSP_SPEED ioctl call failed). Force 44100 Hz\n" )); - pad->pad_SampleRates[numSampleRates++] = 44100; - } - - pad->pad_Info.numSampleRates = numSampleRates; - pad->pad_Info.sampleRates = pad->pad_SampleRates; /* use pointer to embedded array */ - - pad->pad_Info.name = deviceName; - - result = paNoError; - -error: - /* We MUST close the handle here or we won't be able to reopen it later!!! */ - close(tempDevHandle); - - return result; -} - -/*******************************************************************************************/ -PaError Pa_SetupDeviceFormat( int devHandle, int numChannels, int sampleRate ) -{ - PaError result = paNoError; - int tmp; - - /* Set format, channels, and rate in this order to keep OSS happy. */ - /* Set data format. FIXME - handle more native formats. */ - tmp = AFMT_S16_NE; - if( ioctl(devHandle,SNDCTL_DSP_SETFMT,&tmp) == -1) - { - ERR_RPT(("Pa_SetupDeviceFormat: could not SNDCTL_DSP_SETFMT\n" )); - return paHostError; - } - if( tmp != AFMT_S16_NE ) - { - ERR_RPT(("Pa_SetupDeviceFormat: HW does not support AFMT_S16_NE\n" )); - return paHostError; - } - - - /* Set number of channels. */ - tmp = numChannels; - if (ioctl(devHandle, SNDCTL_DSP_CHANNELS, &numChannels) == -1) - { - ERR_RPT(("Pa_SetupDeviceFormat: could not SNDCTL_DSP_CHANNELS\n" )); - return paHostError; - } - if( tmp != numChannels) - { - ERR_RPT(("Pa_SetupDeviceFormat: HW does not support %d channels\n", numChannels )); - return paHostError; - } - - /* Set playing frequency. */ - tmp = sampleRate; - if( ioctl(devHandle,SNDCTL_DSP_SPEED,&tmp) == -1) - { - ERR_RPT(("Pa_SetupDeviceFormat: could not SNDCTL_DSP_SPEED\n" )); - return paHostError; - } - else if( tmp != sampleRate ) - { - int percentError = abs( (100 * (sampleRate - tmp)) / sampleRate ); - PRINT(("Pa_SetupDeviceFormat: warning - requested sample rate = %d Hz - closest = %d\n", - sampleRate, tmp )); - /* Allow sample rate within 10% off of requested rate. PLB20021018 - * Sometimes OSS uses a funky rate like 44188 instead of 44100. - */ - if( percentError > 10 ) - { - ERR_RPT(("Pa_SetupDeviceFormat: HW does not support %d Hz sample rate\n",sampleRate )); - return paHostError; - } - } - - return result; -} - -PaError Pa_SetupOutputDeviceFormat( int devHandle, int numChannels, int sampleRate ) -{ - return Pa_SetupDeviceFormat(devHandle, numChannels, sampleRate); -} - -PaError Pa_SetupInputDeviceFormat( int devHandle, int numChannels, int sampleRate ) -{ - return Pa_SetupDeviceFormat(devHandle, numChannels, sampleRate); -} - - -/******************************************************************************************* -** Set number of fragments and size of fragments to achieve desired latency. -*/ - -static int CalcHigherLogTwo( int n ) -{ - int log2 = 0; - while( (1< 8 ) - { - numBuffers = (numBuffers + 1) >> 1; - framesPerBuffer = framesPerBuffer << 1; - } - - /* calculate size of buffers in bytes */ - bufferSize = framesPerBuffer * channelsPerFrame * sizeof(short); /* FIXME - other sizes? */ - - /* Calculate next largest power of two */ - powerOfTwo = CalcHigherLogTwo( bufferSize ); - DBUG(("Pa_SetLatency: numBuffers = %d, framesPerBuffer = %d, powerOfTwo = %d\n", - numBuffers, framesPerBuffer, powerOfTwo )); - - /* Encode info into a single int */ - tmp=(numBuffers<<16) + powerOfTwo; - - if(ioctl(devHandle,SNDCTL_DSP_SETFRAGMENT,&tmp) == -1) - { - ERR_RPT(("Pa_SetLatency: could not SNDCTL_DSP_SETFRAGMENT\n" )); - /* Don't return an error. Best to just continue and hope for the best. */ - ERR_RPT(("Pa_SetLatency: numBuffers = %d, framesPerBuffer = %d, powerOfTwo = %d\n", - numBuffers, framesPerBuffer, powerOfTwo )); - } -} - -/***********************************************************************/ -PaTimestamp Pa_StreamTime( PortAudioStream *stream ) -{ - internalPortAudioStream *past = (internalPortAudioStream *) stream; - PaHostSoundControl *pahsc; - - count_info info; - int delta; - - if( past == NULL ) return paBadStreamPtr; - - pahsc = (PaHostSoundControl *) past->past_DeviceData; - - if( pahsc->pahsc_NativeOutputBuffer ) - { - ioctl(pahsc->pahsc_OutputHandle, SNDCTL_DSP_GETOPTR, &info); - delta = (info.bytes - pahsc->pahsc_LastPosPtr) & 0x000FFFFF; - return (pahsc->pahsc_LastStreamBytes + delta) / (past->past_NumOutputChannels * sizeof(short)); - } - else - { - ioctl(pahsc->pahsc_InputHandle, SNDCTL_DSP_GETIPTR, &info); - delta = (info.bytes - pahsc->pahsc_LastPosPtr) & 0x000FFFFF; - return (pahsc->pahsc_LastStreamBytes + delta) / (past->past_NumInputChannels * sizeof(short)); - } -} - -void Pa_UpdateStreamTime(PaHostSoundControl *pahsc) -{ - count_info info; - int delta; - - /* Update current stream time (using a double so that - we don't wrap around like info.bytes does) */ - if( pahsc->pahsc_NativeOutputBuffer ) - { - ioctl(pahsc->pahsc_OutputHandle, SNDCTL_DSP_GETOPTR, &info); - } - else - { - ioctl(pahsc->pahsc_InputHandle, SNDCTL_DSP_GETIPTR, &info); - } - delta = (info.bytes - pahsc->pahsc_LastPosPtr) & 0x000FFFFF; - pahsc->pahsc_LastStreamBytes += delta; - pahsc->pahsc_LastPosPtr = info.bytes; -} - -PaError Pa_FlushStream(int devHandle) -{ - /* AS: This doesn't do anything under OSS; it was added for Solaris.*/ - devHandle = devHandle; /* unused */ - return paNoError; -} - -#endif // HAVE_LINUX diff --git a/branches/lydia/portaudio/portaudio.h b/branches/lydia/portaudio/portaudio.h deleted file mode 100644 index 87d4ed3..0000000 --- a/branches/lydia/portaudio/portaudio.h +++ /dev/null @@ -1,463 +0,0 @@ -#ifndef PORT_AUDIO_H -#define PORT_AUDIO_H - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -/* - * $Id: portaudio.h 401 2004-07-23 17:41:54Z jaromil $ - * PortAudio Portable Real-Time Audio Library - * PortAudio API Header File - * Latest version available at: http://www.audiomulch.com/portaudio/ - * - * Copyright (c) 1999-2000 Ross Bencina and Phil Burk - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * Any person wishing to distribute modifications to the Software is - * requested to send the modifications to the original developer so that - * they can be incorporated into the canonical version. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -typedef int PaError; -typedef enum { - paNoError = 0, - - paHostError = -10000, - paInvalidChannelCount, - paInvalidSampleRate, - paInvalidDeviceId, - paInvalidFlag, - paSampleFormatNotSupported, - paBadIODeviceCombination, - paInsufficientMemory, - paBufferTooBig, - paBufferTooSmall, - paNullCallback, - paBadStreamPtr, - paTimedOut, - paInternalError, - paDeviceUnavailable -} PaErrorNum; - -/* - Pa_Initialize() is the library initialisation function - call this before - using the library. - -*/ - -PaError Pa_Initialize( void ); - -/* - Pa_Terminate() is the library termination function - call this after - using the library. - -*/ - -PaError Pa_Terminate( void ); - -/* - Pa_GetHostError() returns a host specific error code. - This can be called after receiving a PortAudio error code of paHostError. - -*/ - -long Pa_GetHostError( void ); - -/* - Pa_GetErrorText() translates the supplied PortAudio error number - into a human readable message. - -*/ - -const char *Pa_GetErrorText( PaError errnum ); - -/* - Sample formats - - These are formats used to pass sound data between the callback and the - stream. Each device has a "native" format which may be used when optimum - efficiency or control over conversion is required. - - Formats marked "always available" are supported (emulated) by all - PortAudio implementations. - - The floating point representation (paFloat32) uses +1.0 and -1.0 as the - maximum and minimum respectively. - - paUInt8 is an unsigned 8 bit format where 128 is considered "ground" - -*/ - -typedef unsigned long PaSampleFormat; -#define paFloat32 ((PaSampleFormat) (1<<0)) /*always available*/ -#define paInt16 ((PaSampleFormat) (1<<1)) /*always available*/ -#define paInt32 ((PaSampleFormat) (1<<2)) /*always available*/ -#define paInt24 ((PaSampleFormat) (1<<3)) -#define paPackedInt24 ((PaSampleFormat) (1<<4)) -#define paInt8 ((PaSampleFormat) (1<<5)) -#define paUInt8 ((PaSampleFormat) (1<<6)) -#define paCustomFormat ((PaSampleFormat) (1<<16)) - -/* - Device enumeration mechanism. - - Device ids range from 0 to Pa_CountDevices()-1. - - Devices may support input, output or both. - -*/ - -typedef int PaDeviceID; -#define paNoDevice -1 - -int Pa_CountDevices( void ); - -typedef struct -{ - int structVersion; - const char *name; - int maxInputChannels; - int maxOutputChannels; - /* Number of discrete rates, or -1 if range supported. */ - int numSampleRates; - /* Array of supported sample rates, or {min,max} if range supported. */ - const double *sampleRates; - PaSampleFormat nativeSampleFormats; -} -PaDeviceInfo; - -/* - Pa_GetDefaultInputDeviceID(), Pa_GetDefaultOutputDeviceID() return the - default device ids for input and output respectively, or paNoDevice if - no device is available. - The result can be passed to Pa_OpenStream(). - - On the PC, the user can specify a default device by - setting an environment variable. For example, to use device #1. - - set PA_RECOMMENDED_OUTPUT_DEVICE=1 - - The user should first determine the available device ids by using - the supplied application "pa_devs". - -*/ - -PaDeviceID Pa_GetDefaultInputDeviceID( void ); -PaDeviceID Pa_GetDefaultOutputDeviceID( void ); - - - -/* - Pa_GetDeviceInfo() returns a pointer to an immutable PaDeviceInfo structure - for the device specified. - If the device parameter is out of range the function returns NULL. - - PortAudio manages the memory referenced by the returned pointer, the client - must not manipulate or free the memory. The pointer is only guaranteed to be - valid between calls to Pa_Initialize() and Pa_Terminate(). - -*/ - -const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID device ); - -/* - PaTimestamp is used to represent a continuous sample clock with arbitrary - start time that can be used for syncronization. The type is used for the - outTime argument to the PortAudioCallback and as the result of Pa_StreamTime() - -*/ - -typedef double PaTimestamp; - -/* - PortAudioCallback is implemented by PortAudio clients. - - inputBuffer and outputBuffer are arrays of interleaved samples, - the format, packing and number of channels used by the buffers are - determined by parameters to Pa_OpenStream() (see below). - - framesPerBuffer is the number of sample frames to be processed by the callback. - - outTime is the time in samples when the buffer(s) processed by - this callback will begin being played at the audio output. - See also Pa_StreamTime() - - userData is the value of a user supplied pointer passed to Pa_OpenStream() - intended for storing synthesis data etc. - - return value: - The callback can return a non-zero value to stop the stream. This may be - useful in applications such as soundfile players where a specific duration - of output is required. However, it is not necessary to utilise this mechanism - as StopStream() will also terminate the stream. A callback returning a - non-zero value must fill the entire outputBuffer. - - NOTE: None of the other stream functions may be called from within the - callback function except for Pa_GetCPULoad(). - -*/ - -typedef int (PortAudioCallback)( - void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, - PaTimestamp outTime, void *userData ); - - -/* - Stream flags - - These flags may be supplied (ored together) in the streamFlags argument to - the Pa_OpenStream() function. - -*/ - -#define paNoFlag (0) -#define paClipOff (1<<0) /* disable default clipping of out of range samples */ -#define paDitherOff (1<<1) /* disable default dithering */ -#define paPlatformSpecificFlags (0x00010000) -typedef unsigned long PaStreamFlags; - -/* - A single PortAudioStream provides multiple channels of real-time - input and output audio streaming to a client application. - Pointers to PortAudioStream objects are passed between PortAudio functions. -*/ - -typedef void PortAudioStream; -#define PaStream PortAudioStream - -/* - Pa_OpenStream() opens a stream for either input, output or both. - - stream is the address of a PortAudioStream pointer which will receive - a pointer to the newly opened stream. - - inputDevice is the id of the device used for input (see PaDeviceID above.) - inputDevice may be paNoDevice to indicate that an input device is not required. - - numInputChannels is the number of channels of sound to be delivered to the - callback. It can range from 1 to the value of maxInputChannels in the - PaDeviceInfo record for the device specified by the inputDevice parameter. - If inputDevice is paNoDevice numInputChannels is ignored. - - inputSampleFormat is the sample format of inputBuffer provided to the callback - function. inputSampleFormat may be any of the formats described by the - PaSampleFormat enumeration (see above). PortAudio guarantees support for - the device's native formats (nativeSampleFormats in the device info record) - and additionally 16 and 32 bit integer and 32 bit floating point formats. - Support for other formats is implementation defined. - - inputDriverInfo is a pointer to an optional driver specific data structure - containing additional information for device setup or stream processing. - inputDriverInfo is never required for correct operation. If not used - inputDriverInfo should be NULL. - - outputDevice is the id of the device used for output (see PaDeviceID above.) - outputDevice may be paNoDevice to indicate that an output device is not required. - - numOutputChannels is the number of channels of sound to be supplied by the - callback. See the definition of numInputChannels above for more details. - - outputSampleFormat is the sample format of the outputBuffer filled by the - callback function. See the definition of inputSampleFormat above for more - details. - - outputDriverInfo is a pointer to an optional driver specific data structure - containing additional information for device setup or stream processing. - outputDriverInfo is never required for correct operation. If not used - outputDriverInfo should be NULL. - - sampleRate is the desired sampleRate. For full-duplex streams it is the - sample rate for both input and output - - framesPerBuffer is the length in sample frames of all internal sample buffers - used for communication with platform specific audio routines. Wherever - possible this corresponds to the framesPerBuffer parameter passed to the - callback function. - - numberOfBuffers is the number of buffers used for multibuffered communication - with the platform specific audio routines. If you pass zero, then an optimum - value will be chosen for you internally. This parameter is provided only - as a guide - and does not imply that an implementation must use multibuffered - i/o when reliable double buffering is available (such as SndPlayDoubleBuffer() - on the Macintosh.) - - streamFlags may contain a combination of flags ORed together. - These flags modify the behaviour of the streaming process. Some flags may only - be relevant to certain buffer formats. - - callback is a pointer to a client supplied function that is responsible - for processing and filling input and output buffers (see above for details.) - - userData is a client supplied pointer which is passed to the callback - function. It could for example, contain a pointer to instance data necessary - for processing the audio buffers. - - return value: - Upon success Pa_OpenStream() returns PaNoError and places a pointer to a - valid PortAudioStream in the stream argument. The stream is inactive (stopped). - If a call to Pa_OpenStream() fails a non-zero error code is returned (see - PaError above) and the value of stream is invalid. - -*/ - -PaError Pa_OpenStream( PortAudioStream** stream, - PaDeviceID inputDevice, - int numInputChannels, - PaSampleFormat inputSampleFormat, - void *inputDriverInfo, - PaDeviceID outputDevice, - int numOutputChannels, - PaSampleFormat outputSampleFormat, - void *outputDriverInfo, - double sampleRate, - unsigned long framesPerBuffer, - unsigned long numberOfBuffers, - PaStreamFlags streamFlags, - PortAudioCallback *callback, - void *userData ); - - -/* - Pa_OpenDefaultStream() is a simplified version of Pa_OpenStream() that opens - the default input and/or output devices. Most parameters have identical meaning - to their Pa_OpenStream() counterparts, with the following exceptions: - - If either numInputChannels or numOutputChannels is 0 the respective device - is not opened. This has the same effect as passing paNoDevice in the device - arguments to Pa_OpenStream(). - - sampleFormat applies to both the input and output buffers. - -*/ - -PaError Pa_OpenDefaultStream( PortAudioStream** stream, - int numInputChannels, - int numOutputChannels, - PaSampleFormat sampleFormat, - double sampleRate, - unsigned long framesPerBuffer, - unsigned long numberOfBuffers, - PortAudioCallback *callback, - void *userData ); - -/* - Pa_CloseStream() closes an audio stream, flushing any pending buffers. - -*/ - -PaError Pa_CloseStream( PortAudioStream* ); - -/* - Pa_StartStream() and Pa_StopStream() begin and terminate audio processing. - Pa_StopStream() waits until all pending audio buffers have been played. - Pa_AbortStream() stops playing immediately without waiting for pending - buffers to complete. - -*/ - -PaError Pa_StartStream( PortAudioStream *stream ); - -PaError Pa_StopStream( PortAudioStream *stream ); - -PaError Pa_AbortStream( PortAudioStream *stream ); - -/* - Pa_StreamActive() returns one (1) when the stream is active (ie playing - or recording audio), zero (0) when not playing, or a negative error number - if the stream is invalid. - The stream is active between calls to Pa_StartStream() and Pa_StopStream(), - but may also become inactive if the callback returns a non-zero value. - In the latter case, the stream is considered inactive after the last - buffer has finished playing. - -*/ - -PaError Pa_StreamActive( PortAudioStream *stream ); - -/* - Pa_StreamTime() returns the current output time in samples for the stream. - This time may be used as a time reference (for example synchronizing audio to - MIDI). - -*/ - -PaTimestamp Pa_StreamTime( PortAudioStream *stream ); - -/* - Pa_GetCPULoad() returns the CPU Load for the stream. - The "CPU Load" is a fraction of total CPU time consumed by the stream's - audio processing routines including, but not limited to the client supplied - callback. - A value of 0.5 would imply that PortAudio and the sound generating - callback was consuming roughly 50% of the available CPU time. - This function may be called from the callback function or the application. - -*/ - -double Pa_GetCPULoad( PortAudioStream* stream ); - -/* - Pa_GetMinNumBuffers() returns the minimum number of buffers required by - the current host based on minimum latency. - On the PC, for the DirectSound implementation, latency can be optionally set - by user by setting an environment variable. - For example, to set latency to 200 msec, put: - - set PA_MIN_LATENCY_MSEC=200 - - in the AUTOEXEC.BAT file and reboot. - If the environment variable is not set, then the latency will be determined - based on the OS. Windows NT has higher latency than Win95. - -*/ - -int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate ); - -/* - Pa_Sleep() puts the caller to sleep for at least 'msec' milliseconds. - You may sleep longer than the requested time so don't rely on this for - accurate musical timing. - - Pa_Sleep() is provided as a convenience for authors of portable code (such as - the tests and examples in the PortAudio distribution.) - -*/ - -void Pa_Sleep( long msec ); - -/* - Pa_GetSampleSize() returns the size in bytes of a single sample in the - supplied PaSampleFormat, or paSampleFormatNotSupported if the format is - no supported. - -*/ - -PaError Pa_GetSampleSize( PaSampleFormat format ); - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* PORT_AUDIO_H */ diff --git a/branches/lydia/sndfile_decoder.cpp b/branches/lydia/sndfile_decoder.cpp deleted file mode 100644 index 958e011..0000000 --- a/branches/lydia/sndfile_decoder.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* MuSE - Multiple Streaming Engine - * Copyright (C) 2004 Angelo Michele, Failla aka pallotron - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - */ - -#include - -#include -#include - -/* ----- LibSndFile input channel ----- */ - -MuseDecSndFile::MuseDecSndFile () - : MuseDec(), Entry() { - - D("MuseDecSndFile::MuseDecSndFile()"); - set_name("Snd"); - memset(&sf_info_struct, 0, sizeof(sf_info_struct)); - -} - -MuseDecSndFile::~MuseDecSndFile (){ - - D ("MuseDecSndFile::~MuseSndFile()"); - sf_close (sf); - -} - -int MuseDecSndFile::load (char *file) { - - int res; - /* 0 => error - * 1 => success && seekable - * 2 => success && !seekable - */ - - /* all the info about the audio file into the sf_info_struct struct */ - if(!(sf = sf_open(file, SFM_READ, &sf_info_struct))) { - W("MuseDecSndFile:_load(): cannot open input file"); - return (0); - } - /* - * this is sndfile file info structure - * - * typedef struct - * { sf_count_t frames ; // used to be called samples - * int samplerate ; - * int channels ; - * int format ; - * int sections ; - * int seekable ; - * } SF_INFO ; - */ - samplerate = sf_info_struct.samplerate; - channels = sf_info_struct.channels; - seekable = sf_info_struct.seekable ? true : false; - - D("Opened audio file: samplerate => %d, channels => %d, seekable => %s", - samplerate, channels, seekable ? "true" : "false"); - - framepos = 0; - - if(seekable) { - frametot = sf_info_struct.frames; - D("Audio file is seekable: total frames: %d", frametot); - res = 1; - } - else res = 2; - - loaded = true; - - return (res); - -} - -IN_DATATYPE *MuseDecSndFile::get_audio () { - - frames = sf_read_short(sf, snd_buffer, IN_CHUNK); - - if(frames!=0) { - - framepos += frames/channels; - fps = samplerate; - // D("MuseDecSndFile::get_audio => Frames readed: %d/%d", framepos, frametot); - return ((IN_DATATYPE *) snd_buffer); - - } else { framepos=0; eos = true; return (NULL); } -} - - -bool MuseDecSndFile::seek (float pos) { - - if(pos==0.0) { - - framepos = 0; - sf_seek(sf, 0, SEEK_SET); - D("MuseDecSndFile::seek => rewinded to the beginning of the track"); - - } else { - - if((framepos = sf_seek(sf, (sf_count_t)(frametot * pos), SEEK_SET))==-1) { - D("MuseDecSndFile::seek error"); //,sf_strerror(sf)); - return false; - } - D("MuseDecSndFile::seek at position %d/%d", framepos, frametot); - - } - - return true; -} - diff --git a/branches/lydia/sndfile_decoder.h b/branches/lydia/sndfile_decoder.h deleted file mode 100644 index 76fbb1e..0000000 --- a/branches/lydia/sndfile_decoder.h +++ /dev/null @@ -1,60 +0,0 @@ -/* MuSE - Multiple Streaming Engine - * Copyright (C) 2004 Angelo Michele Failla aka pallotron - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/** - @file dec_ogg.h libsnd decoder - @desc input channel: decoder implemenation -*/ - -#ifndef __IN_SND_H__ -#define __IN_SND_H__ - -#include -#include - -/* libsndfile inclusion */ -#include - -/** - TODO: commento da scrivere - @class MuseDecSndFile - @brief SndFile decoder -*/ -class MuseDecSndFile: public MuseDec, Entry { - - public: - /* TODO: scrivere il commento per la doc */ - MuseDecSndFile (); /* constructor */ - ~MuseDecSndFile (); /* destructor */ - - int load (char *file); - bool seek (float pos); - - IN_DATATYPE *get_audio (); - - private: - /* pointer to data */ - SNDFILE *sf; - /* file information struct */ - SF_INFO sf_info_struct; - short snd_buffer[IN_CHUNK]; - -}; - -#endif diff --git a/branches/lydia/sound_decoder.cpp b/branches/lydia/sound_decoder.cpp deleted file mode 100644 index e284ccb..0000000 --- a/branches/lydia/sound_decoder.cpp +++ /dev/null @@ -1,59 +0,0 @@ - -// "$Id: decoder.cpp 328 2004-02-13 16:58:16Z jaromil $" - -#include -#include -#include - -MuseDec::MuseDec() - : Thread() { - bitrate = samplerate = channels = frames = 0; - seekable = false; err = false; eos = false; - loaded = false; - - device = NULL; -} - -MuseDec::~MuseDec() { } - -bool MuseDec::play_once(SoundDevice *dev) { - seek(0.0); - replay = true; - eos = false; - device = dev; - launch(); - return true; -} - -void MuseDec::run() { - D("Sound file decoder thread launched"); - IN_DATATYPE *buf; - - if(!device) { - E("no device configured for decoder"); - return; - } - - while(true) { - - while(!replay) { jsleep(0,500); } - - while(!eos) { - - buf = get_audio(); - - if(!buf) break; - - device->write(buf, IN_CHUNK); - - // device->flush_output(); - - } - replay = false; - eos = false; - seek(0.0); - - } - - return; -} diff --git a/branches/lydia/sound_decoder.h b/branches/lydia/sound_decoder.h deleted file mode 100644 index 037e395..0000000 --- a/branches/lydia/sound_decoder.h +++ /dev/null @@ -1,174 +0,0 @@ -/* MuSE - Multiple Streaming Engine - * Copyright (C) 2000-2006 Denis Rojo aka jaromil - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/** - @file decoder.h MuSE decoder abstraction - @desc header file to be included by decoder implementations -*/ - -#ifndef __SOUND_DECODER_H__ -#define __SOUND_DECODER_H__ - -#include - -#include -#include - -#define IN_DATATYPE int16_t -#define MIX_CHUNK 1152 //2048 -#define IN_CHUNK MIX_CHUNK -#define IN_PIPESIZE IN_CHUNK*(sizeof(IN_DATATYPE))*64 - -/** - This class should be inherited by every decoder implementation: - it is the decoder parent class giving some common functionalities - to its childs. - - Most important thing for making decoders is to implement the pure - virtual functions of this class, inheriting all the rest. - The pure virtual functions to be carefully implemented in a decoder are: - - MuseDec::load - - the destructor class for closing - - MuseDec::seek - - MuseDec::get_audio - Then the decoder must also take care to set properly the following - variables inside the load function: - - MuseDec::samplerate - - MuseDec::channels - - MuseDec::bitrate - - MuseDec::frametot - - MuseDec::seekable - And the following variables in the get_audio function: - - MuseDec::frames - - MuseDec::fps - - MuseDec::eos - - MuseDec::err - - For example decoder implementations, please refer to: - - MuseDecMp3 class implemented in dec_mp3.h and dec_mp3.cpp - - MuseDecOgg class implemented in dec_ogg.h and dec_ogg.cpp - - MuseDecSnd class implemented in dec_snd.h and dec_snd.cpp - - @brief decoder parent abstraction class -*/ - -class SoundDevice; - -class MuseDec: public Thread { - - public: - - /** - The decoder implementations inheriting from this class can - use their constructor to initialize their variables and to - fill up the MuseDec::name buffer with their identification. - - @brief decoder parent class constructor */ - MuseDec(); - - /** - - A decoder implementation should take care to close all files and - free all buffers in the destructor. - - @brief decoder parent class destructor */ - virtual ~MuseDec(); - - /** - Open up a filename (full path) and makes it ready for decoding, - the filename or url can be formed in different ways, depending - on the decoder implementation. - - This is a pure virtual function: needs to be implemented in decoders. - - @brief open file in decoder - @param file full pathname for file, or url accepted by the decoder - @return 0 on error, otherwise - - 1 = success, channel is seekable - - 2 = success, channel is not seekable - */ - virtual int load(char *file) = 0; /* open filename */ - - bool loaded; ///< should be set to true by the implemention on succesful load - - /** - Seek position over the audio data available to an opened channel. - - This operation is only possible if the channel is seekable (see the - flag in this class and the return code of MuseDec::load). - - This is a pure virtual function: needs to be implemented in decoders. - - @brief seek to a position - @param pos floating point value from 0.0 to 1.0 - @return true on success, false otherwise */ - virtual bool seek(float pos) = 0; /* seek to position from 0.0 1.0 */ - - /** - Decode another chunk of audio for the channel at the current position, - this function is implementing the low-level decoder functionalities - to obtain the audio pcm to be mixed. - - The audio will be then resampled at a common rate and mixed by MuSE. - - This is a pure virtual function: needs to be implemented in decoders. - - @brief decode a chunk of channel audio - @return pointer to decoded pcm buffer */ - virtual IN_DATATYPE *get_audio() = 0; /* decode audio */ - - - - // ===================================================================== - // DECODER PARENT FUNCTIONS - - void run(); ///< thread runner - - /** - Playback once the loaded file on a device, spawning a thread - - @brief playback once the audio file - @return true on success, false otherwise */ - bool play_once(SoundDevice *dev); - bool replay; - - SoundDevice *device; - - /** - * the following variables describe the audio returned by - * MuseDec::get_audio and must be setted up by the decoder implementation. - */ - int samplerate; ///< samplerate of audio decoded - int channels; ///< number of audio channels decoded - int bitrate; ///< bitrate of the compressed audio being decoded - int frames; ///< quantity of audio frames (16bit words) decoded - int framepos; ///< position offset on the frames - int frametot; ///< total frames in opened audio (if seekable, othwrwise 0) - int fps; ///< samplerate / frames quantity - bool seekable; ///< true if the channel audio is seekable - bool eos; ///< true on end of stream reached - bool err; ///< true when an error occurred during audio decoding - /////////////////////////////////////////////////////////// - - - - -}; - -#endif diff --git a/branches/lydia/sound_device.cpp b/branches/lydia/sound_device.cpp deleted file mode 100644 index 20b4089..0000000 --- a/branches/lydia/sound_device.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* MuSE - Multiple Streaming Engine - * SoundDevice class interfacing Portaudio PABLIO library - * Copyright (C) 2004-2005 Denis Roio aka jaromil - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - "$Id: dev_sound.cpp 760 2006-03-16 23:37:40Z xant $" - - */ - -#include - -#include -#include - -/* settings (take care!) */ -#define IN_DATATYPE int16_t -#define OUT_DATATYPE int16_t -#define MIX_CHUNK 1152 //2048 -#define IN_CHUNK MIX_CHUNK -#define IN_PIPESIZE IN_CHUNK*(sizeof(IN_DATATYPE))*64 -#define SAMPLE_RATE 44100 // 44100 - -#define PA_SAMPLE_TYPE paFloat32 -#define PA_SAMPLES_PER_FRAME 2 -#define PA_NUM_SECONDS 5 -#define FRAMES_PER_BUFFER (64) -#define PA_PIPE_SIZE MIX_CHUNK*sizeof(PA_SAMPLE_TYPE)*64 - -#define INPUT_DEVICE Pa_GetDefaultInputDeviceID() -#define OUTPUT_DEVICE Pa_GetDefaultOutputDeviceID() - - -SoundDevice::SoundDevice() { - memset(&input_device,0,sizeof(input_device)); - memset(&output_device,0,sizeof(output_device)); - pa_dev.input = &input_device; - pa_dev.output = &output_device; - input_device.pipe = new Pipe(PA_PIPE_SIZE); - input_device.pipe->set_block(false,false); - output_device.pipe = new Pipe(PA_PIPE_SIZE); - output_device.pipe->set_block(true,false); - input_device.pipe->set_output_type("copy_float_to_int16"); - output_device.pipe->set_input_type("copy_int16_to_float"); -} - -SoundDevice::~SoundDevice() { -close(); -} - -static int pa_process( void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, - PaTimestamp outTime, void *userData ) -{ - unsigned int i,n; - void *rBuf; - int readBytes; - PaDevices *dev = (PaDevices *)userData; - long len = framesPerBuffer * (PA_SAMPLES_PER_FRAME*sizeof(PA_SAMPLE_TYPE)); - if(inputBuffer != NULL) { /* handle input from soundcard */ - if(dev->input->info) { - if(dev->input->info->maxInputChannels>1) { - readBytes = dev->input->pipe->write(len,inputBuffer); - } - else { - rBuf = malloc(len); - n=0; - for(i=0;i<(len/sizeof(PA_SAMPLE_TYPE))/2;i++) { - ((float *)rBuf)[n]=((float *)inputBuffer)[i]; - ((float *)rBuf)[n+1]=((float *)inputBuffer)[i]; - n+=2; - } - readBytes = dev->input->pipe->write(len,rBuf); - free(rBuf); - } - if(readBytes <= 0) memset(inputBuffer,0,len); - } - } - if(outputBuffer != NULL) { /* handle output to soundcard */ - if(dev->output->info) { - if(dev->output->info->maxOutputChannels>1) { - readBytes = dev->output->pipe->read(len,outputBuffer); - } - else { - rBuf = malloc(len); - readBytes = dev->output->pipe->read(len,rBuf); - n=0; - for(i=0; i < (len / sizeof(PA_SAMPLE_TYPE)) /2 ;i++) { - ((float *)outputBuffer)[n]=((float *)rBuf)[i]; - ((float *)outputBuffer)[n+1]=((float *)rBuf)[i]; - n+=2; - } - free(rBuf); - } - if(readBytes <= 0) memset(outputBuffer,0,len); - } - } - return 0; -} - -bool SoundDevice::input(bool state) { - bool res = false; - if(!res) res = pa_open(state,PaInput); - return res; -} - -PaError SoundDevice::pa_real_open(int mode) { - return Pa_OpenStream( ((mode & PaInput) == PaInput)?&input_device.stream:&output_device.stream, - ((mode & PaInput) == PaInput)?input_device.id:paNoDevice, - ((mode & PaInput) == PaInput)?(input_device.info->maxInputChannels>1?2:1):0, - PA_SAMPLE_TYPE, - NULL, - ((mode & PaOutput) == PaOutput)?output_device.id:paNoDevice, - ((mode & PaOutput) == PaOutput)?(output_device.info->maxOutputChannels>1?2:1):0, - PA_SAMPLE_TYPE, - NULL, - SAMPLE_RATE, - FRAMES_PER_BUFFER, - 0, /* number of buffers, if zero then use default minimum */ - 0, // paClipOff, /* we won't output out of range samples so don't bother clipping them */ - pa_process, - &pa_dev ); -} - -bool SoundDevice::pa_open(bool state,int mode) { - PaDevInfo *dev,*other; - int creq,oreq; - char dir[7]; - - // PaDeviceInfo *k=NULL; - // int i=0; - // do { -// k=Pa_GetDeviceInfo(i); -// i++; -/// if(k) printf("KKK %d - %s \n",i,k->name); -// } while (k!=NULL); - - if(mode == PaInput) { // input requested - dev = &input_device; - other = &output_device; - creq = PaInput; - oreq = PaOutput; - strcpy(dir,"input"); - dev->id = Pa_GetDefaultInputDeviceID(); - } - else if(mode == PaOutput) { // output requested - dev = &output_device; - other = &input_device; - creq = PaOutput; - oreq = PaInput; - strcpy(dir,"output"); - dev->id = Pa_GetDefaultOutputDeviceID(); - } - if(state && ((pa_mode & creq) != creq)) { - dev->info = (PaDeviceInfo*)Pa_GetDeviceInfo( dev->id ); - if(dev->info) N("Opening %s device: %s",dir,dev->info->name); - else { - E("%s device not available",dir); - return false; - } - if((pa_mode & oreq) == oreq) { - /* input device is already opened...check if we are trying to open the same device */ - if(other->info) { - Pa_StopStream( other->stream ); - Pa_CloseStream( other->stream ); - err = pa_real_open(PaInput|PaOutput); - if(err == paNoError ) output_device.stream = input_device.stream; - } - else { - E("Full duplex has been requested but we don't have portaudio information"); - return false; - } - } - else { - err = pa_real_open(mode); - } - if( err != paNoError) { - Pa_Terminate(); - E("error opening %s sound device: %s",dir,Pa_GetErrorText( err ) ); - return false; - } - else { - err = Pa_StartStream(dev->stream); - if(err != paNoError) { - E("error starting %s audio stream: %s",dir,Pa_GetErrorText( err ) ); - return false; - } - pa_mode = pa_mode | creq; - } - } else if(!state && dev->stream) { // XXX - i have to check if this is still right - if(dev->info) N("Closing %s device: %s",dir,dev->info->name); - if((pa_mode & creq) == creq) { - if((pa_mode & oreq) == oreq) { - pa_mode = oreq; - } - else { - Pa_StopStream(dev->stream); - Pa_CloseStream(dev->stream); - pa_mode = PaNull; - } - } - dev->stream = NULL; - dev->info = NULL; - dev->pipe->flush(); - //delete dev->pipe; - } - return true; -} - -bool SoundDevice::output(bool state) { - bool res = false; - if(!res) res = pa_open(state,PaOutput); - return res; -} - -bool SoundDevice::open(bool read, bool write) { - - N("open sound device"); - - if( ! output(write) ) return false; - - if( ! input(read) ) return false; - - return true; -} - - - -void SoundDevice::close() { - if((pa_mode&PaInput) == PaInput) { - if((pa_mode&PaOutput) == PaOutput) { - pa_mode = PaOutput; - if(output_device.stream == input_device.stream) - output_device.stream = NULL; - } - else pa_mode = PaNull; - if(input_device.stream) { - Pa_StopStream( input_device.stream); - Pa_CloseStream( input_device.stream ); - input_device.stream = NULL; - } - input_device.pipe->flush(); - //delete input_device.pipe; - } - - if((pa_mode&PaOutput) == PaOutput) { - if(output_device.stream) { - Pa_StopStream( output_device.stream); - Pa_CloseStream( output_device.stream ); - output_device.stream = NULL; - } - output_device.pipe->flush(); - if((pa_mode&PaInput) == PaInput) - pa_mode = PaInput; - else pa_mode = PaNull; - } - //delete output_device.pipe; -} - -int SoundDevice::read(void *buf, int len) { - // len is in samples: 4*2 32bit stereo - int res = -1; - - // takes number of left and right frames (stereo / 2) - res = input_device.pipe->read(len*2,buf); - - return res; -} - -int SoundDevice::write(void *buf, int len) { - // len is in samples, for bytes must *2 (16bit) - int res = -1; - - res = output_device.pipe->write(len,buf); - //func("dspout available pipe space: %d \n",output_device.pipe->space()); - - return res; -} - -void SoundDevice::flush_output() { - output_device.pipe->flush(); -} -void SoundDevice::flush_input() { - input_device.pipe->flush(); -} diff --git a/branches/lydia/sound_device.h b/branches/lydia/sound_device.h deleted file mode 100644 index 3694d64..0000000 --- a/branches/lydia/sound_device.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef __DEV_SOUND_H__ -#define __DEV_SOUND_H__ - -#include - -#include - -typedef struct { - PaDeviceID id; - PortAudioStream *stream; - PaDeviceInfo *info; - Pipe *pipe; -} PaDevInfo; - -typedef struct { - PaDevInfo *input; - PaDevInfo *output; -} PaDevices; -///< the PortAudio device descriptor , this struct just group some data used by PortAudio framework - -class SoundDevice { - public: - SoundDevice(); - ///< the SoundDevice class constructor - ~SoundDevice(); - ///< the SoundDevice class destructor - - /** - Tries to open the sound device for read and/or write - if full-duplex is requested but not supported, it returns error - and must be called again to fallback on half-duplex mode - - @param read true if device is opened for reading audio - @param write true if device is opened for writing audio - @return true in case of success, false otherwise - */ - bool open(bool read, bool write); - ///< open the sound device - - bool input(bool state); ///< activate sound input - bool output(bool state); ///< activate sound output - - void close(); ///< close the sound device - - int read(void *buf, int len); ///< reads audio data from the device in a buffer, len is samples - - int write(void *buf, int len); ///< writes audio data from a buffer to the device, len is samples - void flush_input(); - void flush_output(); - - /* TODO - should be private */ - PaDevInfo input_device; ///< portaudio input device - PaDevInfo output_device; ///< portaudio output device - private: - bool pa_open(bool state,int mode); - PaError pa_real_open(int mode); - - PaError err; - - PaDevices pa_dev; - - int pa_mode; ///< a switch to represent portaudio mode currently using (for noaudio,input,output or both) -#define PaNull 0 -#define PaInput 1 -#define PaOutput 2 - - -}; - -#endif diff --git a/branches/lydia/thread.cpp b/branches/lydia/thread.cpp deleted file mode 100644 index fa1c0ef..0000000 --- a/branches/lydia/thread.cpp +++ /dev/null @@ -1,46 +0,0 @@ - -#include -#include - -static void *kickoff(void *arg) { - ((Thread*)arg)->run(); - return NULL; -} - -Thread::Thread() { - if(pthread_mutex_init(&mutex,NULL) == -1) - E("error initializing thread mutex"); - if(pthread_attr_init(&attr) == -1) - E("error initializing thread attribute"); - - pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE); - - running = false; - quit = false; -} - -Thread::~Thread() { - if(pthread_mutex_destroy(&mutex) == -1) - E("error destroying thread mutex"); - if(pthread_attr_destroy(&attr) == -1) - E("error destroying thread attribute"); -} - -bool Thread::launch() { - lock(); // the runner will unlock when ready - return pthread_create(&thread,&attr,&kickoff, this); - lock(); // wait until the thread is ready - unlock(); -} - -void Thread::lock() { - pthread_mutex_lock(&mutex); -} - -void Thread::unlock() { - pthread_mutex_unlock(&mutex); -} - -void Thread::join() { - pthread_join(thread,NULL); -} diff --git a/branches/lydia/thread.h b/branches/lydia/thread.h deleted file mode 100644 index 8c8a4bf..0000000 --- a/branches/lydia/thread.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Pthread handling class - * (c) Copyright 2001 - 2006 Denis Rojo - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - -#ifndef __THREAD_H__ -#define __THREAD_H__ - -class Thread { - - public: - Thread(); - virtual ~Thread(); - - bool launch(); - bool running; - bool quit; - - virtual void run() =0; - - void lock(); - void unlock(); - void join(); - - private: - - pthread_t thread; - pthread_attr_t attr; - pthread_mutex_t mutex; -}; - -#endif diff --git a/branches/lydia/utils.cpp b/branches/lydia/utils.cpp deleted file mode 100644 index bfda08d..0000000 --- a/branches/lydia/utils.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* Generic utils - * (c) Copyright 2001-2006 Denis Roio aka jaromil - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include - -#include - -#define MAX_DEBUG 3 - -#define FUNC 2 // se il debug level e' questo ci sono le funzioni chiamate -#define WARN 1 // se il debug level e' >= a questo ci sono i warning - -static char msg[255]; - -static int verbosity = 0; - -void set_debug(int lev) { - lev = lev<0 ? 0 : lev; - lev = lev>MAX_DEBUG ? MAX_DEBUG : lev; - verbosity = lev; -} - -int get_debug() { - return(verbosity); -} - -void N(char *format, ...) { - va_list arg; - va_start(arg, format); - - vsnprintf(msg, 254, format, arg); - fprintf(stderr,"[*] %s\n",msg); - - va_end(arg); -} - -void D(char *format, ...) { - if(verbosity>=FUNC) { - va_list arg; - va_start(arg, format); - - vsnprintf(msg, 254, format, arg); - fprintf(stderr,"[F] %s\n",msg); - - va_end(arg); - } -} - -void E(char *format, ...) { - va_list arg; - va_start(arg, format); - - vsnprintf(msg, 254, format, arg); - fprintf(stderr,"[!] %s\n",msg); - - va_end(arg); -} - -void A(char *format, ...) { - va_list arg; - va_start(arg, format); - - vsnprintf(msg, 254, format, arg); - fprintf(stderr," . %s\n",msg); - - va_end(arg); -} - -void W(char *format, ...) { - if(verbosity>=WARN) { - va_list arg; - va_start(arg, format); - - vsnprintf(msg, 254, format, arg); - fprintf(stderr,"[W] %s\n",msg); - - va_end(arg); - } -} - -void jsleep(int sec, long nsec) { - struct timespec timelap; - timelap.tv_sec = sec; - timelap.tv_nsec = nsec; - nanosleep(&timelap,NULL); -} - -// jaromil's chomp -#define MAX_CHOMP_SIZE 1024 -void chomp(char *str) { - size_t len; //, ilen; - char tmp[MAX_CHOMP_SIZE], *p = str; - - memset(tmp,'\0',MAX_CHOMP_SIZE); - - /* eliminate space and tabs at the beginning */ - while (*p == ' ' || *p == '\t') p++; - strncpy(tmp, p, MAX_CHOMP_SIZE); - - /* point *p at the end of string */ - len = strlen(tmp); - p = &tmp[len-1]; - - while ((*p == ' ' || *p == '\t' || *p == '\n') && len) { - *p = '\0'; p--; len--; - } - - strncpy(str, tmp, MAX_CHOMP_SIZE); -} - -void get_time(char *f, struct tm *tt) { - strptime(f,"%d%b%y-%H%M",tt); - return; -} - -char *mark_time() { - static char dm[32]; - struct tm *tm; - time_t now; - - now = time(NULL); - tm = localtime(&now); - strftime(dm,31,"%d%b%y-%H%M",tm); - return(dm); -} - -#ifdef linux -#include -/* sets the process to "policy" policy, if max=1 then set at max priority, - else use min priority */ - -bool set_rtpriority(bool max) { - struct sched_param schp; - // set the process to realtime privs - - memset(&schp, 0, sizeof(schp)); - - if(max) - schp.sched_priority = sched_get_priority_max(SCHED_RR); - else - schp.sched_priority = sched_get_priority_min(SCHED_RR); - - if (sched_setscheduler(0, SCHED_RR, &schp) != 0) - return false; - else - return true; -} -#endif diff --git a/branches/lydia/utils.h b/branches/lydia/utils.h deleted file mode 100644 index 30684bd..0000000 --- a/branches/lydia/utils.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Generic utils - * (c) Copyright 2001-2006 Denis Roio aka jaromil - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __UTILS_H__ -#define __UTILS_H__ - -#include - -void set_debug(int lev); -int get_debug(); - -void N(char *format, ...); -void A(char *format, ...); -void W(char *format, ...); -void E(char *format, ...); -void D(char *format, ...); - -void jsleep(int sec, long nsec); - -void chomp(char *str); - -char *mark_time(); -void get_time(char *f, struct tm *tt); - -bool set_rtpriority(bool max); - -#endif - - diff --git a/branches/lydia/xmlrpc++/Doxyfile b/branches/lydia/xmlrpc++/Doxyfile deleted file mode 100644 index 2d8a346..0000000 --- a/branches/lydia/xmlrpc++/Doxyfile +++ /dev/null @@ -1,1041 +0,0 @@ -# Doxyfile 1.3-rc3 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# General configuration options -#--------------------------------------------------------------------------- - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = XmlRpc++ - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = 0.7 - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = ../doc - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, -# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en -# (Japanese with english messages), Korean, Norwegian, Polish, Portuguese, -# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish and Ukrainian. - -OUTPUT_LANGUAGE = English - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these class will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = YES - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited -# members of a class in the documentation of that class as if those members were -# ordinary class members. Constructors, destructors and assignment operators of -# the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = NO - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. It is allowed to use relative paths in the argument list. - -STRIP_FROM_PATH = - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower case letters. If set to YES upper case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# users are adviced to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like the Qt-style comments (thus requiring an -# explict @brief command for a brief description. - -JAVADOC_AUTOBRIEF = YES - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the DETAILS_AT_TOP tag is set to YES then Doxygen -# will output the detailed description near the top, like JavaDoc. -# If set to NO, the detailed description appears after the member -# documentation. - -DETAILS_AT_TOP = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# reimplements. - -INHERIT_DOCS = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consist of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. -# For instance some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources -# only. Doxygen will then generate output that is more tailored for Java. -# For instance namespaces will be presented as packages, qualified scopes -# will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp -# *.h++ *.idl *.odl - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = NO - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = base64.h - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories -# that are symbolic links (a Unix filesystem feature) are excluded from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. - -EXCLUDE_PATTERNS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. - -INPUT_FILTER = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES (the default) -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = YES - -# If the REFERENCES_RELATION tag is set to YES (the default) -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output dir. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non empty doxygen will try to run -# the html help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the Html help documentation and to the tree view. - -TOC_EXPAND = NO - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = NO - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = NO - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimised for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assigments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_XML = NO - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. This is useful -# if you want to understand what is going on. On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_PREDEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse the -# parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::addtions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES tag can be used to specify one or more tagfiles. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or -# super classes. Setting the tag to NO turns the diagrams off. Note that this -# option is superceded by the HAVE_DOT option below. This is only a fallback. It is -# recommended to install and use dot, since it yield more powerful graphs. - -CLASS_DIAGRAMS = YES - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found on the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. - -MAX_DOT_GRAPH_WIDTH = 1024 - -# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. - -MAX_DOT_GRAPH_HEIGHT = 1024 - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermedate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Configuration::addtions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO - -# The CGI_NAME tag should be the name of the CGI script that -# starts the search engine (doxysearch) with the correct parameters. -# A script with this name will be generated by doxygen. - -CGI_NAME = search.cgi - -# The CGI_URL tag should be the absolute URL to the directory where the -# cgi binaries are located. See the documentation of your http daemon for -# details. - -CGI_URL = - -# The DOC_URL tag should be the absolute URL to the directory where the -# documentation is located. If left blank the absolute path to the -# documentation, with file:// prepended to it, will be used. - -DOC_URL = - -# The DOC_ABSPATH tag should be the absolute path to the directory where the -# documentation is located. If left blank the directory on the local machine -# will be used. - -DOC_ABSPATH = - -# The BIN_ABSPATH tag must point to the directory where the doxysearch binary -# is installed. - -BIN_ABSPATH = /usr/local/bin/ - -# The EXT_DOC_PATHS tag can be used to specify one or more paths to -# documentation generated for other projects. This allows doxysearch to search -# the documentation for these projects as well. - -EXT_DOC_PATHS = diff --git a/branches/lydia/xmlrpc++/Makefile b/branches/lydia/xmlrpc++/Makefile deleted file mode 100644 index bc8080a..0000000 --- a/branches/lydia/xmlrpc++/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# makefile written for gnu make -CXX = g++ -CXXFLAGS = -Wall -ggdb -VERSION = 0.8 -LIB = ./libxmlrpc++.a - -# Add your system-dependent network libs here. These are -# only used to build the tests (your application will need them too). -# Linux: none -# Solaris: -lsocket -lnsl -#SYSTEMLIBS = -lsocket -lnsl -SYSTEMLIBS = -LDLIBS = $(LIB) $(SYSTEMLIBS) - -OBJ = XmlRpcClient.o XmlRpcDispatch.o \ - XmlRpcServer.o XmlRpcServerConnection.o \ - XmlRpcServerMethod.o XmlRpcSocket.o XmlRpcSource.o \ - XmlRpcUtil.o XmlRpcValue.o - -all: $(LIB) - -$(LIB): $(OBJ) - $(AR) $(ARFLAGS) $(LIB) $(OBJ) - -doc doxygen: - doxygen Doxyfile - -distclean: clean - -clean: - rm -f *.o - rm -f *~ - rm -f $(LIB) - diff --git a/branches/lydia/xmlrpc++/README b/branches/lydia/xmlrpc++/README deleted file mode 100644 index c5cb7d1..0000000 --- a/branches/lydia/xmlrpc++/README +++ /dev/null @@ -1,102 +0,0 @@ - XmlRpc++ Library - - This is version 0.7 of XmlRpc++, an implementation of the [1]XmlRpc - protocol written in C++, based upon Shilad Sen's excellent - [2]py-xmlrpc library. XmlRpc++ is designed to make it easy to - incorporate XmlRpc client and server support into C++ applications. Or - use both client and server objects in your app for easy peer-to-peer - support. - - Features - - * Easy This library is easy to incorporate into C++ applications. - No other libraries are required, other than your system's socket - libraries. Simple XML parsing and HTTP support are built in. - * Fast All IO is non-blocking, so a slow client or network will - not slow down the server. - * Portable Written in standard C++ to the POSIX and Windows sockets - APIs. You do need a fairly recent compiler (g++ 3.1 or MSVC++ .Net - or MSVC++ 6 with the [3]STL patches.) - * Free This library is released under the [4]GNU [5]LGPL. - - - Changes - - * Better handling of fault responses: server methods can throw an - XmlRpcException to return a fault and XmlRpcClient has a new - method to test whether the last response was a fault. - * Support for system.listMethods and system.methodHelp from the - introspection API. - * Support for system.multicall to process multiple requests in a - single transaction. - * Fixed a problem in the XmlRpcServer destructor (it should not have - been deleting the methods). - * The server ensures a valid result value is returned even if the - method does not set the result. The default result is an empty - string. - * Doxygen comments in header files and a doc target in the makefile. - - - Installation - - There are VC++ 6 and VC++ .Net project files building on Windows. If - you are using VC++ 6, you should apply SP3 and the fixes at - [6]http://www.dinkumware.com/vc_fixes.html. Be sure to set the - appropriate code generation switches. In particular, ensure that the - runtime library (single/multi-threaded, static library/DLL) used is - the same for the XmlRpc++ code and whatever application it will be - linked to. - - For Linux, Solaris, and other Unix-like platforms there is a GNU - Makefile which can be edited to suit your system. Specify your C++ - compiler, compiler flags, and your system's socket libraries. - - In the test directory there are various test programs that are built - by default. To verify that the library built correctly, you can start - the HelloServer example: -HelloServer 8000 - - and the HelloClient example in another terminal window: -HelloClient localhost 8000 - - You should see two Hello messages and a sum displayed (amongst a bunch - of debug output). You can also try the XML server validator program - (eg, "Validator 80") and then attempt to connect to it from - [7]http://validator.xmlrpc.com (if you have access to the internet and - are not behind a firewall etc). - - Author - - [8]Chris Morley - - Although no code was re-used, the design and structure of the library - is based upon the py-xmlrpc library implementation. - The base64 decoder/encoder is by [9]Konstantin Pilipchuk. - - License - - A full copy of the LGPL license is included in the file COPYING. The - source code is Copyright (c) 2002-2003 by Chris Morley. This library - is free software; you can redistribute it and/or modify it under the - terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (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 Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA - -References - - 1. http://www.xmlrpc.org/ - 2. http://py-xmlrpc.sourceforge.net/ - 3. http://www.dinkumware.com/vc_fixes.html - 4. http://www.gnu.org/ - 5. http://www.gnu.org/copyleft/lesser.html - 6. http://www.dinkumware.com/vc_fixes.html - 7. http://validator.xmlrpc.com/ - 8. mailto:cmorley@users.sourceforge.net - 9. mailto:lostd@ukr.net diff --git a/branches/lydia/xmlrpc++/XmlRpc.h b/branches/lydia/xmlrpc++/XmlRpc.h deleted file mode 100644 index aa761f9..0000000 --- a/branches/lydia/xmlrpc++/XmlRpc.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef _XMLRPC_H_ -#define _XMLRPC_H_ -// -// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (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 -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -// -// The XmlRpc++ home page is http://xmlrpcpp.sourceforge.net/ -// My home page is http://www.vermontel.net/~cmorley/ -// - -#if defined(_MSC_VER) -# pragma warning(disable:4786) // identifier was truncated in debug info -#endif - -#ifndef MAKEDEPEND -# include -#endif - -#include "XmlRpcClient.h" -#include "XmlRpcException.h" -#include "XmlRpcServer.h" -#include "XmlRpcServerMethod.h" -#include "XmlRpcValue.h" -#include "XmlRpcUtil.h" - -namespace XmlRpc { - - - //! An interface allowing custom handling of error message reporting. - class XmlRpcErrorHandler { - public: - //! Returns a pointer to the currently installed error handling object. - static XmlRpcErrorHandler* getErrorHandler() - { return _errorHandler; } - - //! Specifies the error handler. - static void setErrorHandler(XmlRpcErrorHandler* eh) - { _errorHandler = eh; } - - //! Report an error. Custom error handlers should define this method. - virtual void error(const char* msg) = 0; - - protected: - static XmlRpcErrorHandler* _errorHandler; - }; - - //! An interface allowing custom handling of informational message reporting. - class XmlRpcLogHandler { - public: - //! Returns a pointer to the currently installed message reporting object. - static XmlRpcLogHandler* getLogHandler() - { return _logHandler; } - - //! Specifies the message handler. - static void setLogHandler(XmlRpcLogHandler* lh) - { _logHandler = lh; } - - //! Returns the level of verbosity of informational messages. 0 is no output, 5 is very verbose. - static int getVerbosity() - { return _verbosity; } - - //! Specify the level of verbosity of informational messages. 0 is no output, 5 is very verbose. - static void setVerbosity(int v) - { _verbosity = v; } - - //! Output a message. Custom error handlers should define this method. - virtual void log(int level, const char* msg) = 0; - - protected: - static XmlRpcLogHandler* _logHandler; - static int _verbosity; - }; - - //! Returns log message verbosity. This is short for XmlRpcLogHandler::getVerbosity() - int getVerbosity(); - //! Sets log message verbosity. This is short for XmlRpcLogHandler::setVerbosity(level) - void setVerbosity(int level); - - - //! Version identifier - extern const char XMLRPC_VERSION[]; - -} // namespace XmlRpc - -#endif // _XMLRPC_H_ diff --git a/branches/lydia/xmlrpc++/XmlRpcClient.cpp b/branches/lydia/xmlrpc++/XmlRpcClient.cpp deleted file mode 100644 index af70715..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcClient.cpp +++ /dev/null @@ -1,547 +0,0 @@ - -#include "XmlRpcClient.h" - -#include "XmlRpcSocket.h" -#include "XmlRpc.h" - -#include "base64.h" // For HTTP authentication encoding - -#include -#include -#include - -using namespace XmlRpc; -using namespace std; - -// Static data -const char XmlRpcClient::REQUEST_BEGIN[] = - "\r\n" - ""; -const char XmlRpcClient::REQUEST_END_METHODNAME[] = "\r\n"; -const char XmlRpcClient::PARAMS_TAG[] = ""; -const char XmlRpcClient::PARAMS_ETAG[] = ""; -const char XmlRpcClient::PARAM_TAG[] = ""; -const char XmlRpcClient::PARAM_ETAG[] = ""; -const char XmlRpcClient::REQUEST_END[] = "\r\n"; -const char XmlRpcClient::METHODRESPONSE_TAG[] = ""; -const char XmlRpcClient::FAULT_TAG[] = ""; - - - -XmlRpcClient::XmlRpcClient(const char* host, int port, const char* uri/*=0*/) -{ - XmlRpcUtil::log(1, "XmlRpcClient new client: host %s, port %d.", host, port); - - _host = host; - _port = port; - if (uri && *uri) - _uri = uri; - else - _uri = "/RPC2"; - _connectionState = NO_CONNECTION; - _executing = false; - _eof = false; - _ssl = false; _ssl_ssl = (SSL *) NULL; - - // Default to keeping the connection open until an explicit close is done - setKeepOpen(); -} -XmlRpcClient::XmlRpcClient(const char* host, int port, const char* uri, bool ssl) -{ - XmlRpcUtil::log(1, "XmlRpcClient new client: host %s, port %d.", host, port); - - _host = host; - _port = port; - if (uri && *uri) - _uri = uri; - else - _uri = "/RPC2"; - _connectionState = NO_CONNECTION; - _executing = false; - _eof = false; - _ssl = ssl; - if (!_ssl) { _ssl_ssl = (SSL *) NULL; } - - // Default to keeping the connection open until an explicit close is done - setKeepOpen(); -} - - -XmlRpcClient::XmlRpcClient(const char* host, int port, - const char* login, const char* password, const char* uri/*=0*/) -{ - XmlRpcUtil::log(1, "XmlRpcClient new client: host %s, port %d, login %s.", host, port, login); - - _host = host; - _port = port; - if (uri) - _uri = uri; - else - _uri = "/RPC2"; - - _login = login; - _password = password; - - _connectionState = NO_CONNECTION; - _executing = false; - _eof = false; - - // Default to keeping the connection open until an explicit close is done - setKeepOpen(); -} - -XmlRpcClient::XmlRpcClient(const char* host, int port, - const char* login, const char* password, - const char* uri/*=0*/, bool ssl) -{ - XmlRpcUtil::log(1, "XmlRpcClient new client: host %s, port %d, login %s.", host, port, login); - - _host = host; - _port = port; - if (uri) - _uri = uri; - else - _uri = "/RPC2"; - - _login = login; - _password = password; - - _connectionState = NO_CONNECTION; - _executing = false; - _eof = false; - _ssl = ssl; - if (!_ssl) { _ssl_ssl = (SSL *) NULL; } - - // Default to keeping the connection open until an explicit close is done - setKeepOpen(); -} - - -XmlRpcClient::~XmlRpcClient() -{ - XmlRpcUtil::log(1, "XmlRpcClient dtor client: host %s, port %d.", _host.c_str(), _port); - if (_connectionState != NO_CONNECTION) close(); -} - - -// Close the owned fd -void -XmlRpcClient::close() -{ - XmlRpcUtil::log(4, "XmlRpcClient::close: fd %d.", getfd()); - _connectionState = NO_CONNECTION; - _disp.exit(); - _disp.removeSource(this); - if (_ssl) { - // Pre-socket shutdown - XmlRpcUtil::log(4, "XmlRpcClient::close: before SSL_shutdown"); - SSL_shutdown(_ssl_ssl); - XmlRpcUtil::log(4, "XmlRpcClient::close: after SSL_shutdown"); - } - XmlRpcSource::close(); - if (_ssl) { - // Post-socket shutdown - XmlRpcUtil::log(4, "XmlRpcClient::close: before SSL_free(_ssl_ssl)"); - SSL_free(_ssl_ssl); - XmlRpcUtil::log(4, "XmlRpcClient::close: before SSL_CTX_free(_ssl_ctx)"); - SSL_CTX_free(_ssl_ctx); - XmlRpcUtil::log(4, "XmlRpcClient::close: SSL shutdown successful!"); - } -} - - -// Clear the referenced flag even if exceptions or errors occur. -struct ClearFlagOnExit { - ClearFlagOnExit(bool& flag) : _flag(flag) {} - ~ClearFlagOnExit() { _flag = false; } - bool& _flag; -}; - -// Execute the named procedure on the remote server. -// Params should be an array of the arguments for the method. -// Returns true if the request was sent and a result received (although the result -// might be a fault). -bool -XmlRpcClient::execute(const char* method, XmlRpcValue const& params, XmlRpcValue& result) -{ - XmlRpcUtil::log(1, "XmlRpcClient::execute: method %s (_connectionState %d).", method, _connectionState); - - // This is not a thread-safe operation, if you want to do multithreading, use separate - // clients for each thread. If you want to protect yourself from multiple threads - // accessing the same client, replace this code with a real mutex. - if (_executing) - return false; - - _executing = true; - ClearFlagOnExit cf(_executing); - - _sendAttempts = 0; - _isFault = false; - - if ( ! setupConnection()) - return false; - - if ( ! generateRequest(method, params)) - return false; - - result.clear(); - double msTime = -1.0; // Process until exit is called - _disp.work(msTime); - - if (_connectionState != IDLE || ! parseResponse(result)) - return false; - - XmlRpcUtil::log(1, "XmlRpcClient::execute: method %s completed.", method); - _response = ""; - return true; -} - -// XmlRpcSource interface implementation -// Handle server responses. Called by the event dispatcher during execute. -unsigned -XmlRpcClient::handleEvent(unsigned eventType) -{ - if (eventType == XmlRpcDispatch::Exception) - { - //if (XmlRpcSocket::nonFatalError()) - // return (_connectionState == WRITE_REQUEST) - // ? XmlRpcDispatch::WritableEvent : XmlRpcDispatch::ReadableEvent; - - if (_connectionState == WRITE_REQUEST && _bytesWritten == 0) - XmlRpcUtil::error("Error in XmlRpcClient::handleEvent: could not connect to server (%s).", - XmlRpcSocket::getErrorMsg().c_str()); - else - XmlRpcUtil::error("Error in XmlRpcClient::handleEvent (state %d): %s.", - _connectionState, XmlRpcSocket::getErrorMsg().c_str()); - return 0; - } - - if (_connectionState == WRITE_REQUEST) - if ( ! writeRequest()) return 0; - - if (_connectionState == READ_HEADER) - if ( ! readHeader()) return 0; - - if (_connectionState == READ_RESPONSE) - if ( ! readResponse()) return 0; - - // This should probably always ask for Exception events too - return (_connectionState == WRITE_REQUEST) - ? XmlRpcDispatch::WritableEvent : XmlRpcDispatch::ReadableEvent; -} - - -// Create the socket connection to the server if necessary -bool -XmlRpcClient::setupConnection() -{ - // If an error occurred last time through, or if the server closed the connection, close our end - if ((_connectionState != NO_CONNECTION && _connectionState != IDLE) || _eof) - close(); - - _eof = false; - if (_connectionState == NO_CONNECTION) - if (! doConnect()) - return false; - - // Prepare to write the request - _connectionState = WRITE_REQUEST; - _bytesWritten = 0; - - // Notify the dispatcher to listen on this source (calls handleEvent when the socket is writable) - _disp.removeSource(this); // Make sure nothing is left over - _disp.addSource(this, XmlRpcDispatch::WritableEvent | XmlRpcDispatch::Exception); - - return true; -} - - -// Connect to the xmlrpc server -bool -XmlRpcClient::doConnect() -{ - int fd = XmlRpcSocket::socket(); - if (fd < 0) - { - XmlRpcUtil::error("Error in XmlRpcClient::doConnect: Could not create socket (%s).", XmlRpcSocket::getErrorMsg().c_str()); - return false; - } - - XmlRpcUtil::log(3, "XmlRpcClient::doConnect: fd %d.", fd); - this->setfd(fd); - - // Don't block on connect/reads/writes - if ( ! XmlRpcSocket::setNonBlocking(fd)) - { - this->close(); - XmlRpcUtil::error("Error in XmlRpcClient::doConnect: Could not set socket to non-blocking IO mode (%s).", XmlRpcSocket::getErrorMsg().c_str()); - return false; - } - - if ( ! XmlRpcSocket::connect(fd, _host, _port)) - { - this->close(); - XmlRpcUtil::error("Error in XmlRpcClient::doConnect: Could not connect to server (%s).", XmlRpcSocket::getErrorMsg().c_str()); - return false; - } - - // Perform SSL if needed - if (_ssl) { - SSLeay_add_ssl_algorithms(); - _ssl_meth = SSLv23_client_method(); - SSL_load_error_strings(); - _ssl_ctx = SSL_CTX_new (_ssl_meth); - _ssl_ssl = SSL_new (_ssl_ctx); - SSL_set_fd (_ssl_ssl, fd); - int err = SSL_connect (_ssl_ssl); - } - - return true; -} - -// Encode the request to call the specified method with the specified parameters into xml -bool -XmlRpcClient::generateRequest(const char* methodName, XmlRpcValue const& params) -{ - std::string body = REQUEST_BEGIN; - body += methodName; - body += REQUEST_END_METHODNAME; - - // If params is an array, each element is a separate parameter - if (params.valid()) { - body += PARAMS_TAG; - if (params.getType() == XmlRpcValue::TypeArray) - { - for (int i=0; i base64data; - int iostatus = 0; - base64 encoder; - std::back_insert_iterator > ins = - std::back_inserter(base64data); - - std::string authBuf = _login + ":" + _password; - - encoder.put(authBuf.begin(), authBuf.end(), ins, iostatus, - base64<>::crlf()); - - header += "Authorization: Basic "; - std::string authEnc(base64data.begin(), base64data.end()); - // handle pesky linefeed characters - string::size_type lf; - while ( (lf = authEnc.find("\r")) != string::npos ) { - authEnc.erase(lf, 1); - } - while ( (lf = authEnc.find("\n")) != string::npos ) { - authEnc.erase(lf, 1); - } - header += authEnc; - header += "\r\n"; - } - - header += "Content-Type: text/xml\r\nContent-length: "; - - sprintf(buff,"%d\r\n\r\n", body.size()); - - return header + buff; -} - -bool -XmlRpcClient::writeRequest() -{ - if (_bytesWritten == 0) - XmlRpcUtil::log(5, "XmlRpcClient::writeRequest (attempt %d):\n%s\n", _sendAttempts+1, _request.c_str()); - - // Try to write the request - if ( ! XmlRpcSocket::nbWrite(this->getfd(), _request, &_bytesWritten, _ssl_ssl)) { - XmlRpcUtil::error("Error in XmlRpcClient::writeRequest: write error (%s).",XmlRpcSocket::getErrorMsg().c_str()); - return false; - } - - XmlRpcUtil::log(3, "XmlRpcClient::writeRequest: wrote %d of %d bytes.", _bytesWritten, _request.length()); - - // Wait for the result - if (_bytesWritten == int(_request.length())) { - _header = ""; - _response = ""; - _connectionState = READ_HEADER; - } - return true; -} - - -// Read the header from the response -bool -XmlRpcClient::readHeader() -{ - // Read available data - if ( ! XmlRpcSocket::nbRead(this->getfd(), _header, &_eof, _ssl_ssl) || - (_eof && _header.length() == 0)) { - - // If we haven't read any data yet and this is a keep-alive connection, the server may - // have timed out, so we try one more time. - if (getKeepOpen() && _header.length() == 0 && _sendAttempts++ == 0) { - XmlRpcUtil::log(4, "XmlRpcClient::readHeader: re-trying connection"); - XmlRpcSource::close(); - _connectionState = NO_CONNECTION; - _eof = false; - return setupConnection(); - } - - XmlRpcUtil::error("Error in XmlRpcClient::readHeader: error while reading header (%s) on fd %d.", - XmlRpcSocket::getErrorMsg().c_str(), getfd()); - return false; - } - - XmlRpcUtil::log(4, "XmlRpcClient::readHeader: client has read %d bytes", _header.length()); - - char *hp = (char*)_header.c_str(); // Start of header - char *ep = hp + _header.length(); // End of string - char *bp = 0; // Start of body - char *lp = 0; // Start of content-length value - - for (char *cp = hp; (bp == 0) && (cp < ep); ++cp) { - if ((ep - cp > 16) && (strncasecmp(cp, "Content-length: ", 16) == 0)) - lp = cp + 16; - else if ((ep - cp > 4) && (strncmp(cp, "\r\n\r\n", 4) == 0)) - bp = cp + 4; - else if ((ep - cp > 2) && (strncmp(cp, "\n\n", 2) == 0)) - bp = cp + 2; - } - - // If we haven't gotten the entire header yet, return (keep reading) - if (bp == 0) { - if (_eof) // EOF in the middle of a response is an error - { - XmlRpcUtil::error("Error in XmlRpcClient::readHeader: EOF while reading header"); - return false; // Close the connection - } - - return true; // Keep reading - } - - // Decode content length - if (lp == 0) { - XmlRpcUtil::error("Error XmlRpcClient::readHeader: No Content-length specified"); - return false; // We could try to figure it out by parsing as we read, but for now... - } - - _contentLength = atoi(lp); - if (_contentLength <= 0) { - XmlRpcUtil::error("Error in XmlRpcClient::readHeader: Invalid Content-length specified (%d).", _contentLength); - return false; - } - - XmlRpcUtil::log(4, "client read content length: %d", _contentLength); - - // Otherwise copy non-header data to response buffer and set state to read response. - _response = bp; - _header = ""; // should parse out any interesting bits from the header (connection, etc)... - _connectionState = READ_RESPONSE; - return true; // Continue monitoring this source -} - - -bool -XmlRpcClient::readResponse() -{ - // If we dont have the entire response yet, read available data - if (int(_response.length()) < _contentLength) { - if ( ! XmlRpcSocket::nbRead(this->getfd(), _response, &_eof, _ssl_ssl)) { - XmlRpcUtil::error("Error in XmlRpcClient::readResponse: read error (%s).",XmlRpcSocket::getErrorMsg().c_str()); - return false; - } - - // If we haven't gotten the entire _response yet, return (keep reading) - if (int(_response.length()) < _contentLength) { - if (_eof) { - XmlRpcUtil::error("Error in XmlRpcClient::readResponse: EOF while reading response"); - return false; - } - return true; - } - } - - // Otherwise, parse and return the result - XmlRpcUtil::log(3, "XmlRpcClient::readResponse (read %d bytes)", _response.length()); - XmlRpcUtil::log(5, "response:\n%s", _response.c_str()); - - _connectionState = IDLE; - - return false; // Stop monitoring this source (causes return from work) -} - - -// Convert the response xml into a result value -bool -XmlRpcClient::parseResponse(XmlRpcValue& result) -{ - // Parse response xml into result - int offset = 0; - if ( ! XmlRpcUtil::findTag(METHODRESPONSE_TAG,_response,&offset)) { - XmlRpcUtil::error("Error in XmlRpcClient::parseResponse: Invalid response - no methodResponse. Response:\n%s", _response.c_str()); - return false; - } - - // Expect either ... or ... - if ((XmlRpcUtil::nextTagIs(PARAMS_TAG,_response,&offset) && - XmlRpcUtil::nextTagIs(PARAM_TAG,_response,&offset)) || - XmlRpcUtil::nextTagIs(FAULT_TAG,_response,&offset) && (_isFault = true)) - { - if ( ! result.fromXml(_response, &offset)) { - XmlRpcUtil::error("Error in XmlRpcClient::parseResponse: Invalid response value. Response:\n%s", _response.c_str()); - _response = ""; - return false; - } - } else { - XmlRpcUtil::error("Error in XmlRpcClient::parseResponse: Invalid response - no param or fault tag. Response:\n%s", _response.c_str()); - _response = ""; - return false; - } - - _response = ""; - return result.valid(); -} - diff --git a/branches/lydia/xmlrpc++/XmlRpcClient.h b/branches/lydia/xmlrpc++/XmlRpcClient.h deleted file mode 100644 index 433e012..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcClient.h +++ /dev/null @@ -1,148 +0,0 @@ - -#ifndef _XMLRPCCLIENT_H_ -#define _XMLRPCCLIENT_H_ -// -// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley -// -#if defined(_MSC_VER) -# pragma warning(disable:4786) // identifier was truncated in debug info -#endif - - -#ifndef MAKEDEPEND -# include -#endif - -#include "XmlRpcDispatch.h" -#include "XmlRpcSource.h" - -namespace XmlRpc { - - // Arguments and results are represented by XmlRpcValues - class XmlRpcValue; - - //! A class to send XML RPC requests to a server and return the results. - class XmlRpcClient : public XmlRpcSource { - public: - // Static data - static const char REQUEST_BEGIN[]; - static const char REQUEST_END_METHODNAME[]; - static const char PARAMS_TAG[]; - static const char PARAMS_ETAG[]; - static const char PARAM_TAG[]; - static const char PARAM_ETAG[]; - static const char REQUEST_END[]; - // Result tags - static const char METHODRESPONSE_TAG[]; - static const char FAULT_TAG[]; - - //! Construct a client to connect to the server at the specified host:port address - //! @param host The name of the remote machine hosting the server, eg "myserver.mycompany.com" - //! @param port The port on the remote machine where the server is listening - //! @param uri An optional string to be sent as the URI in the HTTP GET header - //! Note that the host is not a URL, do not prepend "http://" or other protocol specifiers. - XmlRpcClient(const char* host, int port, const char* uri=0); - XmlRpcClient(const char* host, int port, const char* uri=0, bool ssl=false); - - //! Construct a client to connect to the server at the specified host:port address including HTTP authentication - //! @param host The name of the remote machine hosting the server - //! @param port The port on the remote machine where the server is listening - //! @param login The username passed to the server - //! @param pass The password passed to the server - //! @param uri An optional string to be sent as the URI in the HTTP GET header - XmlRpcClient(const char* host, int port, const char* login, const char* password, const char* uri=0); - XmlRpcClient(const char* host, int port, const char* login, const char* password, const char* uri=0, bool ssl=false); - - //! Destructor - virtual ~XmlRpcClient(); - - //! Execute the named procedure on the remote server. - //! @param method The name of the remote procedure to execute - //! @param params An array of the arguments for the method - //! @param result The result value to be returned to the client - //! @return true if the request was sent and a result received - //! (although the result might be a fault). - //! - //! Currently this is a synchronous (blocking) implementation (execute - //! does not return until it receives a response or an error). Use isFault() - //! to determine whether the result is a fault response. - bool execute(const char* method, XmlRpcValue const& params, XmlRpcValue& result); - - //! Returns true if the result of the last execute() was a fault response. - bool isFault() const { return _isFault; } - - //! Return the host name of the server - const char* const host() const { return _host.c_str(); } - - //! Return the port - int port() const { return _port; } - - //! Return the URI - const char* const uri() const { return _uri.c_str(); } - - // XmlRpcSource interface implementation - //! Close the connection - virtual void close(); - - //! Handle server responses. Called by the event dispatcher during execute. - //! @param eventType The type of event that occurred. - //! @see XmlRpcDispatch::EventType - virtual unsigned handleEvent(unsigned eventType); - - protected: - // Execution processing helpers - virtual bool doConnect(); - virtual bool setupConnection(); - - virtual bool generateRequest(const char* method, XmlRpcValue const& params); - virtual std::string generateHeader(std::string const& body); - virtual bool writeRequest(); - virtual bool readHeader(); - virtual bool readResponse(); - virtual bool parseResponse(XmlRpcValue& result); - - // Possible IO states for the connection - enum ClientConnectionState { NO_CONNECTION, CONNECTING, WRITE_REQUEST, READ_HEADER, READ_RESPONSE, IDLE }; - ClientConnectionState _connectionState; - - // Server location - std::string _host; - std::string _uri; - int _port; - - // Login information for HTTP authentication - std::string _login; - std::string _password; - - // The xml-encoded request, http header of response, and response xml - std::string _request; - std::string _header; - std::string _response; - - // Number of times the client has attempted to send the request - int _sendAttempts; - - // Number of bytes of the request that have been written to the socket so far - int _bytesWritten; - - // True if we are currently executing a request. If you want to multithread, - // each thread should have its own client. - bool _executing; - - // True if the server closed the connection - bool _eof; - - // True if a fault response was returned by the server - bool _isFault; - - // Number of bytes expected in the response body (parsed from response header) - int _contentLength; - - // Event dispatcher - XmlRpcDispatch _disp; - - }; // class XmlRpcClient - -} // namespace XmlRpc - -#endif // _XMLRPCCLIENT_H_ diff --git a/branches/lydia/xmlrpc++/XmlRpcDispatch.cpp b/branches/lydia/xmlrpc++/XmlRpcDispatch.cpp deleted file mode 100644 index 9d675dc..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcDispatch.cpp +++ /dev/null @@ -1,268 +0,0 @@ - -#include "XmlRpcDispatch.h" -#include "XmlRpcSource.h" -#include "XmlRpcUtil.h" - -#include -#include -#include - -#if defined(_WINDOWS) -# include - -# define USE_FTIME -# if defined(_MSC_VER) -# define timeb _timeb -# define ftime _ftime -# endif -#else -# include -#endif // _WINDOWS - - -using namespace XmlRpc; - - -XmlRpcDispatch::XmlRpcDispatch() -{ - _endTime = -1.0; - _doClear = false; - _inWork = false; -} - - -XmlRpcDispatch::~XmlRpcDispatch() -{ -} - -// Monitor this source for the specified events and call its event handler -// when the event occurs -void -XmlRpcDispatch::addSource(XmlRpcSource* source, unsigned mask) -{ - _sources.push_back(MonitoredSource(source, mask)); -} - -// Stop monitoring this source. Does not close the source. -void -XmlRpcDispatch::removeSource(XmlRpcSource* source) -{ - for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it) - if (it->getSource() == source) - { - _sources.erase(it); - break; - } -} - - -// Modify the types of events to watch for on this source -void -XmlRpcDispatch::setSourceEvents(XmlRpcSource* source, unsigned eventMask) -{ - for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it) - if (it->getSource() == source) - { - it->getMask() = eventMask; - break; - } -} - - - -// Watch current set of sources and process events -void -XmlRpcDispatch::work(double timeout) -{ - // Compute end time - double timeNow = getTime(); - _endTime = (timeout < 0.0) ? -1.0 : (timeNow + timeout); - _doClear = false; - _inWork = true; - - // Only work while there is something to monitor - while (_sources.size() > 0) { - - // Wait for and dispatch events - if ( ! waitForAndProcessEvents(timeout)) - { - _inWork = false; - return; - } - - - // Check whether to clear all sources - if (_doClear) - { - SourceList closeList = _sources; - _sources.clear(); - for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) { - XmlRpcSource *src = it->getSource(); - src->close(); - } - - _doClear = false; - } - - // Check whether end time has passed or exit has been called - if (_endTime == 0.0) // Exit - break; - else if (_endTime > 0.0) // Check for timeout - { - double t = getTime(); - if (t > _endTime) - break; - - // Decrement timeout by elapsed time - timeout -= (t - timeNow); - if (timeout < 0.0) - timeout = 0.0; // Shouldn't happen but its fp math... - timeNow = t; - } - } - - _inWork = false; -} - - - -// Exit from work routine. Presumably this will be called from -// one of the source event handlers. -void -XmlRpcDispatch::exit() -{ - _endTime = 0.0; // Return from work asap -} - - -// Clear all sources from the monitored sources list -void -XmlRpcDispatch::clear() -{ - if (_inWork) - _doClear = true; // Finish reporting current events before clearing - else - { - SourceList closeList = _sources; - _sources.clear(); - for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) - it->getSource()->close(); - } -} - - -// Time utility -double -XmlRpcDispatch::getTime() -{ -#ifdef USE_FTIME - struct timeb tbuff; - - ftime(&tbuff); - return ((double) tbuff.time + ((double)tbuff.millitm / 1000.0) + - ((double) tbuff.timezone * 60)); -#else - struct timeval tv; - struct timezone tz; - - gettimeofday(&tv, &tz); - return (tv.tv_sec + tv.tv_usec / 1000000.0); -#endif /* USE_FTIME */ -} - - -// Wait for I/O on any source, timeout, or interrupt signal. -bool -XmlRpcDispatch::waitForAndProcessEvents(double timeout) -{ -#if defined(_WINDOWS) && 0 - - int nHandles = 0; - SourceList::iterator it; - for (it=_sources.begin(); it!=_sources.end(); ++it) { - int fd = it->getSource()->getfd(); - int mask = 0; - if (it->getMask() & ReadableEvent) mask = (FD_READ | FD_CLOSE | FD_ACCEPT); - if (it->getMask() & WritableEvent) mask |= (FD_WRITE | FD_CLOSE); - -#else // Posix - - // Construct the sets of descriptors we are interested in - fd_set inFd, outFd, excFd; - FD_ZERO(&inFd); - FD_ZERO(&outFd); - FD_ZERO(&excFd); - - int maxFd = -1; - SourceList::iterator it; - for (it=_sources.begin(); it!=_sources.end(); ++it) { - int fd = it->getSource()->getfd(); - if (it->getMask() & ReadableEvent) FD_SET(fd, &inFd); - if (it->getMask() & WritableEvent) FD_SET(fd, &outFd); - if (it->getMask() & Exception) FD_SET(fd, &excFd); - if (it->getMask() && fd > maxFd) maxFd = fd; - } - - // Check for events - int nEvents; - if (_endTime < 0.0) - nEvents = select(maxFd+1, &inFd, &outFd, &excFd, NULL); - else - { - struct timeval tv; - tv.tv_sec = (int)floor(timeout); - tv.tv_usec = ((int)floor(1000000.0 * (timeout-floor(timeout)))) % 1000000; - nEvents = select(maxFd+1, &inFd, &outFd, &excFd, &tv); - } - - if (nEvents < 0 && errno != EINTR) - { - XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents); - return false; - } - - // Process events - for (it=_sources.begin(); it != _sources.end(); ) - { - SourceList::iterator thisIt = it++; - XmlRpcSource* src = thisIt->getSource(); - int fd = src->getfd(); - - if (fd <= maxFd) { - // handleEvent is called once per event type signalled - unsigned newMask = 0; - int nset = 0; - if (FD_ISSET(fd, &inFd)) - { - newMask |= src->handleEvent(ReadableEvent); - ++nset; - } - if (FD_ISSET(fd, &outFd)) - { - newMask |= src->handleEvent(WritableEvent); - ++nset; - } - if (FD_ISSET(fd, &excFd)) - { - newMask |= src->handleEvent(Exception); - ++nset; - } - - // Some event occurred - if (nset) - { - if (newMask) - thisIt->getMask() = newMask; - else // Stop monitoring this one - { - _sources.erase(thisIt); - if ( ! src->getKeepOpen()) - src->close(); - } - } - } - } -#endif - - return true; -} diff --git a/branches/lydia/xmlrpc++/XmlRpcDispatch.h b/branches/lydia/xmlrpc++/XmlRpcDispatch.h deleted file mode 100644 index 88fd657..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcDispatch.h +++ /dev/null @@ -1,93 +0,0 @@ - -#ifndef _XMLRPCDISPATCH_H_ -#define _XMLRPCDISPATCH_H_ -// -// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley -// -#if defined(_MSC_VER) -# pragma warning(disable:4786) // identifier was truncated in debug info -#endif - -#ifndef MAKEDEPEND -# include -#endif - -namespace XmlRpc { - - // An RPC source represents a file descriptor to monitor - class XmlRpcSource; - - //! An object which monitors file descriptors for events and performs - //! callbacks when interesting events happen. - class XmlRpcDispatch { - public: - //! Constructor - XmlRpcDispatch(); - ~XmlRpcDispatch(); - - //! Values indicating the type of events a source is interested in - enum EventType { - ReadableEvent = 1, //!< data available to read - WritableEvent = 2, //!< connected/data can be written without blocking - Exception = 4 //!< uh oh - }; - - //! Monitor this source for the event types specified by the event mask - //! and call its event handler when any of the events occur. - //! @param source The source to monitor - //! @param eventMask Which event types to watch for. \see EventType - void addSource(XmlRpcSource* source, unsigned eventMask); - - //! Stop monitoring this source. - //! @param source The source to stop monitoring - //! The source socket is not closed. - void removeSource(XmlRpcSource* source); - - //! Modify the types of events to watch for on this source - void setSourceEvents(XmlRpcSource* source, unsigned eventMask); - - - //! Watch current set of sources and process events for the specified - //! duration (in ms, -1 implies wait forever, or until exit is called) - void work(double msTime); - - //! Exit from work routine - void exit(); - - //! Clear all sources from the monitored sources list. Sources are closed. - void clear(); - - protected: - - //! Wait for I/O on any source, timeout, or interrupt signal. - bool waitForAndProcessEvents(double timeout); - - - // helper - double getTime(); - - // A source to monitor and what to monitor it for - struct MonitoredSource { - MonitoredSource(XmlRpcSource* src, unsigned mask) : _src(src), _mask(mask) {} - XmlRpcSource* getSource() const { return _src; } - unsigned& getMask() { return _mask; } - XmlRpcSource* _src; - unsigned _mask; - }; - - // A list of sources to monitor - typedef std::list< MonitoredSource > SourceList; - - // Sources being monitored - SourceList _sources; - - // When work should stop (-1 implies wait forever, or until exit is called) - double _endTime; - - bool _doClear; - bool _inWork; - - }; -} // namespace XmlRpc - -#endif // _XMLRPCDISPATCH_H_ diff --git a/branches/lydia/xmlrpc++/XmlRpcException.h b/branches/lydia/xmlrpc++/XmlRpcException.h deleted file mode 100644 index 6090450..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcException.h +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef _XMLRPCEXCEPTION_H_ -#define _XMLRPCEXCEPTION_H_ -// -// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley -// -#if defined(_MSC_VER) -# pragma warning(disable:4786) // identifier was truncated in debug info -#endif - -#ifndef MAKEDEPEND -# include -#endif - - -namespace XmlRpc { - - //! A class representing an error. - //! If server methods throw this exception, a fault response is returned - //! to the client. - class XmlRpcException { - public: - //! Constructor - //! @param message A descriptive error message - //! @param code An integer error code - XmlRpcException(const std::string& message, int code=-1) : - _message(message), _code(code) {} - - //! Return the error message. - const std::string& getMessage() const { return _message; } - - //! Return the error code. - int getCode() const { return _code; } - - private: - std::string _message; - int _code; - }; - -} - -#endif // _XMLRPCEXCEPTION_H_ diff --git a/branches/lydia/xmlrpc++/XmlRpcMutex.cpp b/branches/lydia/xmlrpc++/XmlRpcMutex.cpp deleted file mode 100644 index b29455d..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcMutex.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#if defined(XMLRPC_THREADS) - -#include "XmlRpcMutex.h" - -#if defined(_WINDOWS) -# define WIN32_LEAN_AND_MEAN -# include -#else -# include -#endif - -using namespace XmlRpc; - - -//! Destructor. -XmlRpcMutex::~XmlRpcMutex() -{ - if (_pMutex) - { -#if defined(_WINDOWS) - ::CloseHandle((HANDLE)_pMutex); -#else - ::pthread_mutex_destroy((pthread_mutex_t*)_pMutex); - delete _pMutex; -#endif - _pMutex = 0; - } -} - -//! Wait for the mutex to be available and then acquire the lock. -void XmlRpcMutex::acquire() -{ -#if defined(_WINDOWS) - if ( ! _pMutex) - _pMutex = ::CreateMutex(0, TRUE, 0); - else - ::WaitForSingleObject(_pMutex, INFINITE); -#else - if ( ! _pMutex) - { - _pMutex = new pthread_mutex_t; - ::pthread_mutex_init((pthread_mutex_t*)_pMutex, 0); - } - ::pthread_mutex_lock((pthread_mutex_t*)_pMutex); -#endif -} - -//! Release the mutex. -void XmlRpcMutex::release() -{ - if (_pMutex) -#if defined(_WINDOWS) - ::ReleaseMutex(_pMutex); -#else - ::pthread_mutex_unlock((pthread_mutex_t*)_pMutex); -#endif -} - -#endif // XMLRPC_THREADS - diff --git a/branches/lydia/xmlrpc++/XmlRpcMutex.h b/branches/lydia/xmlrpc++/XmlRpcMutex.h deleted file mode 100644 index f46373d..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcMutex.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _XMLRPCMUTEX_H_ -#define _XMLRPCMUTEX_H_ -// -// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley -// -#if defined(_MSC_VER) -# pragma warning(disable:4786) // identifier was truncated in debug info -#endif - -namespace XmlRpc { - - //! A simple platform-independent mutex API implemented for posix and windows. - class XmlRpcMutex { - public: - //! Construct a Mutex object. - XmlRpcMutex() : _pMutex(0) {} - - //! Destroy a Mutex object. - ~XmlRpcMutex(); - - //! Wait for the mutex to be available and then acquire the lock. - void acquire(); - - //! Release the mutex. - void release(); - - //! Utility class to acquire a mutex at construction and release it when destroyed. - struct AutoLock { - //! Acquire the mutex at construction - AutoLock(XmlRpcMutex& m) : _m(m) { _m.acquire(); } - //! Release at destruction - ~AutoLock() { _m.release(); } - //! The mutex being held - XmlRpcMutex& _m; - }; - - private: - - //! Native Mutex object - void* _pMutex; - - }; // class XmlRpcMutex - -} // namespace XmlRpc - -#endif // _XMLRPCMUTEX_H_ diff --git a/branches/lydia/xmlrpc++/XmlRpcServer.cpp b/branches/lydia/xmlrpc++/XmlRpcServer.cpp deleted file mode 100644 index a32604f..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcServer.cpp +++ /dev/null @@ -1,494 +0,0 @@ - - -#include "XmlRpcServer.h" -#include "XmlRpcServerConnection.h" -#include "XmlRpcServerMethod.h" -#include "XmlRpcSocket.h" -#include "XmlRpcUtil.h" -#include "XmlRpcException.h" -#include "XmlRpc.h" - - -using namespace XmlRpc; - - -// Static data -const char XmlRpcServer::METHODNAME_TAG[] = ""; -const char XmlRpcServer::PARAMS_TAG[] = ""; -const char XmlRpcServer::PARAMS_ETAG[] = ""; -const char XmlRpcServer::PARAM_TAG[] = ""; -const char XmlRpcServer::PARAM_ETAG[] = ""; - -const std::string XmlRpcServer::METHODNAME = "methodName"; -const std::string XmlRpcServer::PARAMS = "params"; - -const std::string XmlRpcServer::FAULTCODE = "faultCode"; -const std::string XmlRpcServer::FAULTSTRING = "faultString"; - - - -XmlRpcServer::XmlRpcServer() -{ - _introspectionEnabled = false; - _listMethods = 0; - _methodHelp = 0; -} - - -XmlRpcServer::~XmlRpcServer() -{ - this->shutdown(); - _methods.clear(); - delete _listMethods; - delete _methodHelp; -} - - -// Add a command to the RPC server -void -XmlRpcServer::addMethod(XmlRpcServerMethod* method) -{ - _methods[method->name()] = method; -} - -// Remove a command from the RPC server -void -XmlRpcServer::removeMethod(XmlRpcServerMethod* method) -{ - MethodMap::iterator i = _methods.find(method->name()); - if (i != _methods.end()) - _methods.erase(i); -} - -// Remove a command from the RPC server by name -void -XmlRpcServer::removeMethod(const std::string& methodName) -{ - MethodMap::iterator i = _methods.find(methodName); - if (i != _methods.end()) - _methods.erase(i); -} - - -// Look up a method by name -XmlRpcServerMethod* -XmlRpcServer::findMethod(const std::string& name) const -{ - MethodMap::const_iterator i = _methods.find(name); - if (i == _methods.end()) - return 0; - return i->second; -} - - -// Create a socket, bind to the specified port, and -// set it in listen mode to make it available for clients. -bool -XmlRpcServer::bindAndListen(int port, int backlog /*= 5*/) -{ - int fd = XmlRpcSocket::socket(); - if (fd < 0) - { - XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not create socket (%s).", XmlRpcSocket::getErrorMsg().c_str()); - return false; - } - - this->setfd(fd); - - // Don't block on reads/writes - if ( ! XmlRpcSocket::setNonBlocking(fd)) - { - this->close(); - XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not set socket to non-blocking input mode (%s).", XmlRpcSocket::getErrorMsg().c_str()); - return false; - } - - // Allow this port to be re-bound immediately so server re-starts are not delayed - if ( ! XmlRpcSocket::setReuseAddr(fd)) - { - this->close(); - XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not set SO_REUSEADDR socket option (%s).", XmlRpcSocket::getErrorMsg().c_str()); - return false; - } - - // Bind to the specified port on the default interface - if ( ! XmlRpcSocket::bind(fd, port)) - { - this->close(); - XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not bind to specified port (%s).", XmlRpcSocket::getErrorMsg().c_str()); - return false; - } - - // Set in listening mode - if ( ! XmlRpcSocket::listen(fd, backlog)) - { - this->close(); - XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not set socket in listening mode (%s).", XmlRpcSocket::getErrorMsg().c_str()); - return false; - } - - XmlRpcUtil::log(2, "XmlRpcServer::bindAndListen: server listening on port %d fd %d", port, fd); - - // Notify the dispatcher to listen on this source when we are in work() - _disp.addSource(this, XmlRpcDispatch::ReadableEvent); - - return true; -} - - -// Get port number that this server is listening on -int -XmlRpcServer::getPort(void) const -{ - return XmlRpcSocket::getPort(getfd()); -} - - - -// Process client requests for the specified time -void -XmlRpcServer::work(double msTime) -{ - XmlRpcUtil::log(2, "XmlRpcServer::work: waiting for a connection"); - _disp.work(msTime); -} - - - -// Handle input on the server socket by accepting the connection -// and reading the rpc request. -unsigned -XmlRpcServer::handleEvent(unsigned mask) -{ - acceptConnection(); - return XmlRpcDispatch::ReadableEvent; // Continue to monitor this fd -} - - -// Accept a client connection request and create a connection to -// handle method calls from the client. -void -XmlRpcServer::acceptConnection() -{ - int s = XmlRpcSocket::accept(this->getfd()); - XmlRpcUtil::log(2, "XmlRpcServer::acceptConnection: socket %d", s); - if (s < 0) - { - //this->close(); - XmlRpcUtil::error("XmlRpcServer::acceptConnection: Could not accept connection (%s).", XmlRpcSocket::getErrorMsg().c_str()); - } - else if ( ! XmlRpcSocket::setNonBlocking(s)) - { - XmlRpcSocket::close(s); - XmlRpcUtil::error("XmlRpcServer::acceptConnection: Could not set socket to non-blocking input mode (%s).", XmlRpcSocket::getErrorMsg().c_str()); - } - else // Notify the dispatcher to listen for input on this source when we are in work() - { - XmlRpcUtil::log(2, "XmlRpcServer::acceptConnection: creating a connection"); - XmlRpcServerConnection* c = this->createConnection(s); - if (c) this->dispatchConnection(c); - } -} - - -// Create a new connection object for processing requests from a specific client. -XmlRpcServerConnection* -XmlRpcServer::createConnection(int s) -{ - // Specify that the connection object be deleted when it is closed - return new XmlRpcServerConnection(s, this, true); -} - - -// Hand off a new connection to a dispatcher -void -XmlRpcServer::dispatchConnection(XmlRpcServerConnection* sc) -{ - _disp.addSource(sc, XmlRpcDispatch::ReadableEvent); -} - - -// Remove a connection. Called by the connection when it closes down. -void -XmlRpcServer::removeConnection(XmlRpcServerConnection* sc) -{ - _disp.removeSource(sc); -} - - -// Stop processing client requests -void -XmlRpcServer::exit() -{ - _disp.exit(); -} - - -// Close the server socket file descriptor and stop monitoring connections -void -XmlRpcServer::shutdown() -{ - // This closes and destroys all connections as well as closing this socket - _disp.clear(); -} - - -// Introspection support -static const std::string LIST_METHODS("system.listMethods"); -static const std::string METHOD_HELP("system.methodHelp"); -static const std::string MULTICALL("system.multicall"); - - -// List all methods available on a server -class ListMethods : public XmlRpcServerMethod -{ -public: - ListMethods(XmlRpcServer* s) : XmlRpcServerMethod(LIST_METHODS, s) {} - - void execute(XmlRpcValue& params, XmlRpcValue& result) - { - _server->listMethods(result); - } - - std::string help() { return std::string("List all methods available on a server as an array of strings"); } -}; - - -// Retrieve the help string for a named method -class MethodHelp : public XmlRpcServerMethod -{ -public: - MethodHelp(XmlRpcServer* s) : XmlRpcServerMethod(METHOD_HELP, s) {} - - void execute(XmlRpcValue& params, XmlRpcValue& result) - { - if (params[0].getType() != XmlRpcValue::TypeString) - throw XmlRpcException(METHOD_HELP + ": Invalid argument type"); - - XmlRpcServerMethod* m = _server->findMethod(params[0]); - if ( ! m) - throw XmlRpcException(METHOD_HELP + ": Unknown method name"); - - result = m->help(); - } - - std::string help() { return std::string("Retrieve the help string for a named method"); } -}; - - -// Specify whether introspection is enabled or not. Default is enabled. -void -XmlRpcServer::enableIntrospection(bool enabled) -{ - if (_introspectionEnabled == enabled) - return; - - _introspectionEnabled = enabled; - - if (enabled) - { - if ( ! _listMethods) - { - _listMethods = new ListMethods(this); - _methodHelp = new MethodHelp(this); - } else { - addMethod(_listMethods); - addMethod(_methodHelp); - } - } - else - { - removeMethod(LIST_METHODS); - removeMethod(METHOD_HELP); - } -} - - -void -XmlRpcServer::listMethods(XmlRpcValue& result) -{ - int i = 0; - result.setSize(_methods.size()+1); - for (MethodMap::iterator it=_methods.begin(); it != _methods.end(); ++it) - result[i++] = it->first; - - // Multicall support is built into XmlRpcServer::executeRequest - result[i] = MULTICALL; -} - - - -// Parse the request, run the method, generate a response string. -std::string -XmlRpcServer::executeRequest(std::string const& request) -{ - XmlRpcValue params, resultValue; - std::string methodName = parseRequest(request, params); - XmlRpcUtil::log(2, "XmlRpcServer::executeRequest: server calling method '%s'", - methodName.c_str()); - - std::string response; - try { - - if ( ! executeMethod(methodName, params, resultValue) && - ! executeMulticall(methodName, params, resultValue)) - response = generateFaultResponse(methodName + ": unknown method name"); - else - response = generateResponse(resultValue.toXml()); - - } catch (const XmlRpcException& fault) { - XmlRpcUtil::log(2, "XmlRpcServer::executeRequest: fault %s.", - fault.getMessage().c_str()); - response = generateFaultResponse(fault.getMessage(), fault.getCode()); - } - - return response; -} - -// Parse the method name and the argument values from the request. -std::string -XmlRpcServer::parseRequest(std::string const& request, XmlRpcValue& params) -{ - int offset = 0; // Number of chars parsed from the request - - std::string methodName = XmlRpcUtil::parseTag(METHODNAME_TAG, request, &offset); - - if (methodName.size() > 0 && XmlRpcUtil::findTag(PARAMS_TAG, request, &offset)) - { - int nArgs = 0; - while (XmlRpcUtil::nextTagIs(PARAM_TAG, request, &offset)) { - params[nArgs++] = XmlRpcValue(request, &offset); - (void) XmlRpcUtil::nextTagIs(PARAM_ETAG, request, &offset); - } - - (void) XmlRpcUtil::nextTagIs(PARAMS_ETAG, request, &offset); - } - - return methodName; -} - -// Execute a named method with the specified params. -bool -XmlRpcServer::executeMethod(const std::string& methodName, - XmlRpcValue& params, - XmlRpcValue& result) -{ - XmlRpcServerMethod* method = findMethod(methodName); - - if ( ! method) return false; - - method->execute(params, result); - - // Ensure a valid result value - if ( ! result.valid()) - result = std::string(); - - return true; -} - -// Execute multiple calls and return the results in an array. -bool -XmlRpcServer::executeMulticall(const std::string& methodName, - XmlRpcValue& params, - XmlRpcValue& result) -{ - if (methodName != MULTICALL) return false; - - // There ought to be 1 parameter, an array of structs - if (params.size() != 1 || params[0].getType() != XmlRpcValue::TypeArray) - throw XmlRpcException(MULTICALL + ": Invalid argument (expected an array)"); - - int nc = params[0].size(); - result.setSize(nc); - - for (int i=0; i\r\n" - "\r\n\t"; - const char RESPONSE_2[] = - "\r\n\r\n"; - - std::string body = RESPONSE_1 + resultXml + RESPONSE_2; - std::string header = generateHeader(body); - std::string response = header + body; - - XmlRpcUtil::log(5, "XmlRpcServer::generateResponse:\n%s\n", response.c_str()); - return response; -} - - -// Prepend http headers -std::string -XmlRpcServer::generateHeader(std::string const& body) -{ - std::string header = - "HTTP/1.1 200 OK\r\n" - "Server: "; - header += XMLRPC_VERSION; - header += "\r\n" - "Content-Type: text/xml\r\n" - "Content-length: "; - - char buffLen[40]; - sprintf(buffLen,"%d\r\n\r\n", body.size()); - - return header + buffLen; -} - - -std::string -XmlRpcServer::generateFaultResponse(std::string const& errorMsg, int errorCode) -{ - const char RESPONSE_1[] = - "\r\n" - "\r\n\t"; - const char RESPONSE_2[] = - "\r\n\r\n"; - - XmlRpcValue faultStruct; - faultStruct[FAULTCODE] = errorCode; - faultStruct[FAULTSTRING] = errorMsg; - std::string body = RESPONSE_1 + faultStruct.toXml() + RESPONSE_2; - std::string header = generateHeader(body); - - return header + body; -} - diff --git a/branches/lydia/xmlrpc++/XmlRpcServer.h b/branches/lydia/xmlrpc++/XmlRpcServer.h deleted file mode 100644 index 28b34a5..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcServer.h +++ /dev/null @@ -1,160 +0,0 @@ - -#ifndef _XMLRPCSERVER_H_ -#define _XMLRPCSERVER_H_ -// -// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley -// -#if defined(_MSC_VER) -# pragma warning(disable:4786) // identifier was truncated in debug info -#endif - -#ifndef MAKEDEPEND -# include -# include -#endif - -#include "XmlRpcDispatch.h" -#include "XmlRpcSource.h" - -namespace XmlRpc { - - - // An abstract class supporting XML RPC methods - class XmlRpcServerMethod; - - // Class representing connections to specific clients - class XmlRpcServerConnection; - - // Class representing argument and result values - class XmlRpcValue; - - - //! A class to handle XML RPC requests - class XmlRpcServer : public XmlRpcSource { - public: - //! Create a server object. - XmlRpcServer(); - //! Destructor. - virtual ~XmlRpcServer(); - - //! Specify whether introspection is enabled or not. Default is not enabled. - void enableIntrospection(bool enabled=true); - - //! Add a command to the RPC server - void addMethod(XmlRpcServerMethod* method); - - //! Remove a command from the RPC server - void removeMethod(XmlRpcServerMethod* method); - - //! Remove a command from the RPC server by name - void removeMethod(const std::string& methodName); - - //! Look up a method by name - XmlRpcServerMethod* findMethod(const std::string& name) const; - - //! Create a socket, bind to the specified port, and - //! set it in listen mode to make it available for clients. - //! @param port The port to bind and listen on (zero to choose an arbitrary port) - bool bindAndListen(int port, int backlog = 5); - - //! Get the port number this server is listening on. - int getPort(void) const; - - //! Process client requests for the specified time - void work(double msTime); - - //! Temporarily stop processing client requests and exit the work() method. - void exit(); - - //! Close all connections with clients and the socket file descriptor - void shutdown(); - - //! Introspection support - void listMethods(XmlRpcValue& result); - - - //! Parses the request xml, runs the method, generates the response (header+xml). - //! Returns a fault response if an error occurs during method execution. - virtual std::string executeRequest(std::string const& request); - - - // XmlRpcSource interface implementation - - //! Handle client connection requests - virtual unsigned handleEvent(unsigned eventType); - - //! Remove a connection from the dispatcher - virtual void removeConnection(XmlRpcServerConnection*); - - protected: - - // Static data - static const char METHODNAME_TAG[]; - static const char PARAMS_TAG[]; - static const char PARAMS_ETAG[]; - static const char PARAM_TAG[]; - static const char PARAM_ETAG[]; - - static const std::string SYSTEM_MULTICALL; - static const std::string METHODNAME; - static const std::string PARAMS; - - static const std::string FAULTCODE; - static const std::string FAULTSTRING; - - - //! Accept a client connection request - virtual void acceptConnection(); - - //! Create a new connection object for processing requests from a specific client. - //! If the client is not authorized to connect, close the socket and return 0. - virtual XmlRpcServerConnection* createConnection(int socket); - - //! Hand off a new connection object to a dispatcher. - virtual void dispatchConnection(XmlRpcServerConnection* sc); - - - //! Parse the methodName and parameters from the request. - //! @returns the methodName - std::string parseRequest(std::string const& request, XmlRpcValue& params); - - //! Execute a named method with the specified params. - bool executeMethod(const std::string& methodName, XmlRpcValue& params, XmlRpcValue& result); - - //! Execute multiple calls and return the results in an array. - //! System.multicall implementation - bool executeMulticall(const std::string& methodName, XmlRpcValue& params, XmlRpcValue& result); - - //! Construct a response from the result XML. - std::string generateResponse(std::string const& resultXml); - - //! Construct a fault response. - std::string generateFaultResponse(std::string const& msg, int errorCode = -1); - - //! Return the appropriate headers for the response. - std::string generateHeader(std::string const& body); - - - - //! Whether the introspection API is supported by this server - bool _introspectionEnabled; - - //! Event dispatcher - XmlRpcDispatch _disp; - - //! Collection of methods. This could be a set keyed on method name if we wanted... - typedef std::map< std::string, XmlRpcServerMethod* > MethodMap; - - //! Registered RPC methods. - MethodMap _methods; - - //! List all registered RPC methods (only available if introspection is enabled) - XmlRpcServerMethod* _listMethods; - - //! Return help string for a specified method (only available if introspection is enabled) - XmlRpcServerMethod* _methodHelp; - - }; -} // namespace XmlRpc - -#endif //_XMLRPCSERVER_H_ diff --git a/branches/lydia/xmlrpc++/XmlRpcServerConnection.cpp b/branches/lydia/xmlrpc++/XmlRpcServerConnection.cpp deleted file mode 100644 index d428ff4..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcServerConnection.cpp +++ /dev/null @@ -1,205 +0,0 @@ - -#include "XmlRpcServerConnection.h" - -#include "XmlRpcSocket.h" -#ifndef MAKEDEPEND -# include -# include -#endif - -#include "XmlRpcDispatch.h" -#include "XmlRpcServer.h" -#include "XmlRpcUtil.h" - -using namespace XmlRpc; - - - -// The server delegates handling client requests to a serverConnection object. -XmlRpcServerConnection::XmlRpcServerConnection(int fd, - XmlRpcServer* server, - bool deleteOnClose /*= false*/) : - XmlRpcSource(fd, deleteOnClose) -{ - XmlRpcUtil::log(2,"XmlRpcServerConnection: new socket %d.", fd); - _server = server; - _connectionState = READ_HEADER; - _keepAlive = true; -} - - -XmlRpcServerConnection::~XmlRpcServerConnection() -{ - XmlRpcUtil::log(4,"XmlRpcServerConnection dtor."); - _server->removeConnection(this); -} - - -// Handle input on the server socket by accepting the connection -// and reading the rpc request. Return true to continue to monitor -// the socket for events, false to remove it from the dispatcher. -unsigned -XmlRpcServerConnection::handleEvent(unsigned /*eventType*/) -{ - if (_connectionState == READ_HEADER) - if ( ! readHeader()) return 0; - - if (_connectionState == READ_REQUEST) - if ( ! readRequest()) return 0; - - if (_connectionState == WRITE_RESPONSE) - if ( ! writeResponse()) return 0; - - return (_connectionState == WRITE_RESPONSE) - ? XmlRpcDispatch::WritableEvent : XmlRpcDispatch::ReadableEvent; -} - - -bool -XmlRpcServerConnection::readHeader() -{ - // Read available data - bool eof; - if ( ! XmlRpcSocket::nbRead(this->getfd(), _header, &eof, NULL)) { // was _ssl_ssl - // Its only an error if we already have read some data - if (_header.length() > 0) - XmlRpcUtil::error("XmlRpcServerConnection::readHeader: error while reading header (%s).",XmlRpcSocket::getErrorMsg().c_str()); - return false; - } - - XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: read %d bytes.", _header.length()); - char *hp = (char*)_header.c_str(); // Start of header - char *ep = hp + _header.length(); // End of string - char *bp = 0; // Start of body - char *lp = 0; // Start of content-length value - char *kp = 0; // Start of connection value - - for (char *cp = hp; (bp == 0) && (cp < ep); ++cp) { - if ((ep - cp > 16) && (strncasecmp(cp, "Content-length: ", 16) == 0)) - lp = cp + 16; - else if ((ep - cp > 12) && (strncasecmp(cp, "Connection: ", 12) == 0)) - kp = cp + 12; - else if ((ep - cp > 4) && (strncmp(cp, "\r\n\r\n", 4) == 0)) - bp = cp + 4; - else if ((ep - cp > 2) && (strncmp(cp, "\n\n", 2) == 0)) - bp = cp + 2; - } - - // If we haven't gotten the entire header yet, return (keep reading) - if (bp == 0) { - // EOF in the middle of a request is an error, otherwise its ok - if (eof) { - XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: EOF"); - if (_header.length() > 0) - XmlRpcUtil::error("XmlRpcServerConnection::readHeader: EOF while reading header"); - return false; // Either way we close the connection - } - - return true; // Keep reading - } - - // Decode content length - if (lp == 0) { - XmlRpcUtil::error("XmlRpcServerConnection::readHeader: No Content-length specified"); - return false; // We could try to figure it out by parsing as we read, but for now... - } - - _contentLength = atoi(lp); - if (_contentLength <= 0) { - XmlRpcUtil::error("XmlRpcServerConnection::readHeader: Invalid Content-length specified (%d).", _contentLength); - return false; - } - - XmlRpcUtil::log(3, "XmlRpcServerConnection::readHeader: specified content length is %d.", _contentLength); - - // Otherwise copy non-header data to request buffer and set state to read request. - _request = bp; - - // Parse out any interesting bits from the header (HTTP version, connection) - _keepAlive = true; - if (_header.find("HTTP/1.0") != std::string::npos) { - if (kp == 0 || strncasecmp(kp, "keep-alive", 10) != 0) - _keepAlive = false; // Default for HTTP 1.0 is to close the connection - } else { - if (kp != 0 && strncasecmp(kp, "close", 5) == 0) - _keepAlive = false; - } - XmlRpcUtil::log(3, "KeepAlive: %d", _keepAlive); - - - _header = ""; - _connectionState = READ_REQUEST; - return true; // Continue monitoring this source -} - - - -bool -XmlRpcServerConnection::readRequest() -{ - // If we dont have the entire request yet, read available data - if (int(_request.length()) < _contentLength) { - bool eof; - if ( ! XmlRpcSocket::nbRead(this->getfd(), _request, &eof, NULL)) { // was _ssl_ssl - XmlRpcUtil::error("XmlRpcServerConnection::readRequest: read error (%s).",XmlRpcSocket::getErrorMsg().c_str()); - return false; - } - - // If we haven't gotten the entire request yet, return (keep reading) - if (int(_request.length()) < _contentLength) { - if (eof) { - XmlRpcUtil::error("XmlRpcServerConnection::readRequest: EOF while reading request"); - return false; // Either way we close the connection - } - return true; - } - } - - // Otherwise, parse and dispatch the request - XmlRpcUtil::log(3, "XmlRpcServerConnection::readRequest read %d bytes.", _request.length()); - //XmlRpcUtil::log(5, "XmlRpcServerConnection::readRequest:\n%s\n", _request.c_str()); - - _connectionState = WRITE_RESPONSE; - - return true; // Continue monitoring this source -} - - - -bool -XmlRpcServerConnection::writeResponse() -{ - if (_response.length() == 0) { - executeRequest(); - _bytesWritten = 0; - if (_response.length() == 0) { - XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: empty response."); - return false; - } - } - - // Try to write the response - if ( ! XmlRpcSocket::nbWrite(this->getfd(), _response, &_bytesWritten, NULL)) { // was _ssl_ssl - XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: write error (%s).",XmlRpcSocket::getErrorMsg().c_str()); - return false; - } - XmlRpcUtil::log(3, "XmlRpcServerConnection::writeResponse: wrote %d of %d bytes.", _bytesWritten, _response.length()); - - // Prepare to read the next request - if (_bytesWritten == int(_response.length())) { - _header = ""; - _request = ""; - _response = ""; - _connectionState = READ_HEADER; - } - - return _keepAlive; // Continue monitoring this source if true -} - - -//! Helper method to execute the client request -void XmlRpcServerConnection::executeRequest() -{ - _response = _server->executeRequest(_request); -} - diff --git a/branches/lydia/xmlrpc++/XmlRpcServerConnection.h b/branches/lydia/xmlrpc++/XmlRpcServerConnection.h deleted file mode 100644 index 31c31d0..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcServerConnection.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef _XMLRPCSERVERCONNECTION_H_ -#define _XMLRPCSERVERCONNECTION_H_ -// -// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley -// -#if defined(_MSC_VER) -# pragma warning(disable:4786) // identifier was truncated in debug info -#endif - -#ifndef MAKEDEPEND -# include -#endif - -#include "XmlRpcValue.h" -#include "XmlRpcSource.h" - -namespace XmlRpc { - - - // The server waits for client connections and provides support for executing methods - class XmlRpcServer; - class XmlRpcServerMethod; - - //! A class to handle XML RPC requests from a particular client - class XmlRpcServerConnection : public XmlRpcSource { - public: - - //! Constructor - XmlRpcServerConnection(int fd, XmlRpcServer* server, bool deleteOnClose = false); - //! Destructor - virtual ~XmlRpcServerConnection(); - - // XmlRpcSource interface implementation - //! Handle IO on the client connection socket. - //! @param eventType Type of IO event that occurred. @see XmlRpcDispatch::EventType. - virtual unsigned handleEvent(unsigned eventType); - - protected: - - //! Reads the http header - bool readHeader(); - - //! Reads the request (based on the content-length header value) - bool readRequest(); - - //! Executes the request and writes the resulting response - bool writeResponse(); - - - //! Helper method to execute the client request - virtual void executeRequest(); - - - //! The XmlRpc server that accepted this connection - XmlRpcServer* _server; - - //! Possible IO states for the connection - enum ServerConnectionState { READ_HEADER, READ_REQUEST, WRITE_RESPONSE }; - //! Current IO state for the connection - ServerConnectionState _connectionState; - - //! Request headers - std::string _header; - - //! Number of bytes expected in the request body (parsed from header) - int _contentLength; - - //! Request body - std::string _request; - - //! Response - std::string _response; - - //! Number of bytes of the response written so far - int _bytesWritten; - - //! Whether to keep the current client connection open for further requests - bool _keepAlive; - }; -} // namespace XmlRpc - -#endif // _XMLRPCSERVERCONNECTION_H_ diff --git a/branches/lydia/xmlrpc++/XmlRpcServerMethod.cpp b/branches/lydia/xmlrpc++/XmlRpcServerMethod.cpp deleted file mode 100644 index 1616ff4..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcServerMethod.cpp +++ /dev/null @@ -1,21 +0,0 @@ - -#include "XmlRpcServerMethod.h" -#include "XmlRpcServer.h" - -namespace XmlRpc { - - - XmlRpcServerMethod::XmlRpcServerMethod(std::string const& name, XmlRpcServer* server) - { - _name = name; - _server = server; - if (_server) _server->addMethod(this); - } - - XmlRpcServerMethod::~XmlRpcServerMethod() - { - if (_server) _server->removeMethod(this); - } - - -} // namespace XmlRpc diff --git a/branches/lydia/xmlrpc++/XmlRpcServerMethod.h b/branches/lydia/xmlrpc++/XmlRpcServerMethod.h deleted file mode 100644 index 738a9c8..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcServerMethod.h +++ /dev/null @@ -1,47 +0,0 @@ - -#ifndef _XMLRPCSERVERMETHOD_H_ -#define _XMLRPCSERVERMETHOD_H_ -// -// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley -// -#if defined(_MSC_VER) -# pragma warning(disable:4786) // identifier was truncated in debug info -#endif - -#ifndef MAKEDEPEND -# include -#endif - -namespace XmlRpc { - - // Representation of a parameter or result value - class XmlRpcValue; - - // The XmlRpcServer processes client requests to call RPCs - class XmlRpcServer; - - //! Abstract class representing a single RPC method - class XmlRpcServerMethod { - public: - //! Constructor - XmlRpcServerMethod(std::string const& name, XmlRpcServer* server = 0); - //! Destructor - virtual ~XmlRpcServerMethod(); - - //! Returns the name of the method - std::string& name() { return _name; } - - //! Execute the method. Subclasses must provide a definition for this method. - virtual void execute(XmlRpcValue& params, XmlRpcValue& result) = 0; - - //! Returns a help string for the method. - //! Subclasses should define this method if introspection is being used. - virtual std::string help() { return std::string(); } - - protected: - std::string _name; - XmlRpcServer* _server; - }; -} // namespace XmlRpc - -#endif // _XMLRPCSERVERMETHOD_H_ diff --git a/branches/lydia/xmlrpc++/XmlRpcSocket.cpp b/branches/lydia/xmlrpc++/XmlRpcSocket.cpp deleted file mode 100644 index ed29b1a..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcSocket.cpp +++ /dev/null @@ -1,285 +0,0 @@ - -#include "XmlRpcSocket.h" -#include "XmlRpcUtil.h" - -#ifndef MAKEDEPEND - -#if defined(_WINDOWS) -# include -# include -//# pragma lib(WS2_32.lib) - -# define EINPROGRESS WSAEINPROGRESS -# define EWOULDBLOCK WSAEWOULDBLOCK -# define ETIMEDOUT WSAETIMEDOUT - -typedef int socklen_t; - -#else -extern "C" { -# include -# include -# include -# include -# include -# include -# include -# include -} -#endif // _WINDOWS - -#endif // MAKEDEPEND - - -using namespace XmlRpc; - - - -#if defined(_WINDOWS) - -static void initWinSock() -{ - static bool wsInit = false; - if (! wsInit) - { - WORD wVersionRequested = MAKEWORD( 2, 0 ); - WSADATA wsaData; - WSAStartup(wVersionRequested, &wsaData); - wsInit = true; - } -} - -#else - -#define initWinSock() - -#endif // _WINDOWS - - -// These errors are not considered fatal for an IO operation; the operation will be re-tried. -bool -XmlRpcSocket::nonFatalError() -{ - int err = XmlRpcSocket::getError(); - return (err == EINPROGRESS || err == EAGAIN || err == EWOULDBLOCK || err == EINTR); -} - - -int -XmlRpcSocket::socket() -{ - initWinSock(); - return (int) ::socket(AF_INET, SOCK_STREAM, 0); -} - - -void -XmlRpcSocket::close(int fd) -{ - XmlRpcUtil::log(4, "XmlRpcSocket::close: fd %d.", fd); -#if defined(_WINDOWS) - closesocket(fd); -#else - ::close(fd); -#endif // _WINDOWS -} - - - - -bool -XmlRpcSocket::setNonBlocking(int fd) -{ -#if defined(_WINDOWS) - unsigned long flag = 1; - return (ioctlsocket((SOCKET)fd, FIONBIO, &flag) == 0); -#else - return (fcntl(fd, F_SETFL, O_NONBLOCK) == 0); -#endif // _WINDOWS -} - - -bool -XmlRpcSocket::setReuseAddr(int fd) -{ - // Allow this port to be re-bound immediately so server re-starts are not delayed - int sflag = 1; - return (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&sflag, sizeof(sflag)) == 0); -} - - -// Bind to a specified port -bool -XmlRpcSocket::bind(int fd, int port) -{ - struct sockaddr_in saddr; - memset(&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; - saddr.sin_addr.s_addr = htonl(INADDR_ANY); - saddr.sin_port = htons((u_short) port); - return (::bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) == 0); -} - - -// Set socket in listen mode -bool -XmlRpcSocket::listen(int fd, int backlog) -{ - return (::listen(fd, backlog) == 0); -} - - -int -XmlRpcSocket::accept(int fd) -{ - struct sockaddr_in addr; - socklen_t addrlen = sizeof(addr); - - return (int) ::accept(fd, (struct sockaddr*)&addr, &addrlen); -} - - - -// Connect a socket to a server (from a client) -bool -XmlRpcSocket::connect(int fd, std::string& host, int port) -{ - struct sockaddr_in saddr; - memset(&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; - - struct hostent *hp = gethostbyname(host.c_str()); - if (hp == 0) return false; - - saddr.sin_family = hp->h_addrtype; - memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length); - saddr.sin_port = htons((u_short) port); - - // For asynch operation, this will return EWOULDBLOCK (windows) or - // EINPROGRESS (linux) and we just need to wait for the socket to be writable... - int result = ::connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); - return result == 0 || nonFatalError(); -} - - - -// Read available text from the specified socket. Returns false on error. -bool -XmlRpcSocket::nbRead(int fd, std::string& s, bool *eof, SSL* ssl) -{ - const int READ_SIZE = 4096; // Number of bytes to attempt to read at a time - char readBuf[READ_SIZE]; - - bool wouldBlock = false; - *eof = false; - - while ( ! wouldBlock && ! *eof) { -#if defined(_WINDOWS) - int n = recv(fd, readBuf, READ_SIZE-1, 0); -#else - int n; - if (ssl != (SSL *) NULL) { - n = SSL_read(ssl, readBuf, READ_SIZE-1); - } else { - n = read(fd, readBuf, READ_SIZE-1); - } -#endif - XmlRpcUtil::log(5, "XmlRpcSocket::nbRead: read/recv returned %d.", n); - - if (n > 0) { - readBuf[n] = 0; - s.append(readBuf, n); - } else if (n == 0) { - *eof = true; - } else if (nonFatalError()) { - wouldBlock = true; - } else { - return false; // Error - } - } - return true; -} - - -// Write text to the specified socket. Returns false on error. -bool -XmlRpcSocket::nbWrite(int fd, std::string& s, int *bytesSoFar, SSL* ssl) -{ - int nToWrite = int(s.length()) - *bytesSoFar; - char *sp = const_cast(s.c_str()) + *bytesSoFar; - bool wouldBlock = false; - - while ( nToWrite > 0 && ! wouldBlock ) { -#if defined(_WINDOWS) - int n = send(fd, sp, nToWrite, 0); -#else - int n; - if (ssl != (SSL *) NULL) { - n = SSL_write(ssl, sp, nToWrite); - } else { - n = write(fd, sp, nToWrite); - } -#endif - XmlRpcUtil::log(5, "XmlRpcSocket::nbWrite: send/write returned %d.", n); - - if (n > 0) { - sp += n; - *bytesSoFar += n; - nToWrite -= n; - } else if (nonFatalError()) { - wouldBlock = true; - } else { - return false; // Error - } - } - return true; -} - -// Get the port of a bound socket -int -XmlRpcSocket::getPort(int socket) -{ - struct sockaddr_in saddr; - socklen_t saddr_len = sizeof(saddr); - int port; - - int result = ::getsockname(socket, (sockaddr*) &saddr, &saddr_len); - - if (result != 0) { - port = -1; - } else { - port = ntohs(saddr.sin_port); - } - return port; -} - - -// Returns last errno -int -XmlRpcSocket::getError() -{ -#if defined(_WINDOWS) - return WSAGetLastError(); -#else - return errno; -#endif -} - - -// Returns message corresponding to last errno -std::string -XmlRpcSocket::getErrorMsg() -{ - return getErrorMsg(getError()); -} - -// Returns message corresponding to errno... well, it should anyway -std::string -XmlRpcSocket::getErrorMsg(int error) -{ - char err[60]; - snprintf(err,sizeof(err),"error %d", error); - return std::string(err); -} - - diff --git a/branches/lydia/xmlrpc++/XmlRpcSocket.h b/branches/lydia/xmlrpc++/XmlRpcSocket.h deleted file mode 100644 index 115d3e0..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcSocket.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef _XMLRPCSOCKET_H_ -#define _XMLRPCSOCKET_H_ -// -// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley -// -#if defined(_MSC_VER) -# pragma warning(disable:4786) // identifier was truncated in debug info -#endif - -#ifndef MAKEDEPEND -# include -#endif - -#include - -namespace XmlRpc { - - //! A platform-independent socket API. - class XmlRpcSocket { - public: - // TODO - typedef the socket type, casting to int won't work for 64 bit windows - - //! Creates a stream (TCP) socket. Returns -1 on failure. - static int socket(); - - //! Closes a socket. - static void close(int socket); - - - //! Sets a stream (TCP) socket to perform non-blocking IO. Returns false on failure. - static bool setNonBlocking(int socket); - - //! Read text from the specified socket. Returns false on error. - static bool nbRead(int socket, std::string& s, bool *eof, SSL *ssl); - - //! Write text to the specified socket. Returns false on error. - static bool nbWrite(int socket, std::string& s, int *bytesSoFar, SSL* ssl); - - - // The next four methods are appropriate for servers. - - //! Allow the port the specified socket is bound to to be re-bound immediately so - //! server re-starts are not delayed. Returns false on failure. - static bool setReuseAddr(int socket); - - //! Bind to a specified port - static bool bind(int socket, int port); - - //! Set socket in listen mode - static bool listen(int socket, int backlog); - - //! Accept a client connection request - static int accept(int socket); - - //! Connect a socket to a server (from a client) - static bool connect(int socket, std::string& host, int port); - - //! Get the port of a bound socket - static int getPort(int socket); - - //! Returns true if the last error was not a fatal one (eg, EWOULDBLOCK) - static bool nonFatalError(); - - //! Returns last errno - static int getError(); - - //! Returns message corresponding to last error - static std::string getErrorMsg(); - - //! Returns message corresponding to error - static std::string getErrorMsg(int error); - }; - -} // namespace XmlRpc - -#endif diff --git a/branches/lydia/xmlrpc++/XmlRpcSource.cpp b/branches/lydia/xmlrpc++/XmlRpcSource.cpp deleted file mode 100644 index 31ab771..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcSource.cpp +++ /dev/null @@ -1,40 +0,0 @@ - -#include "XmlRpcSource.h" -#include "XmlRpcSocket.h" -#include "XmlRpcUtil.h" - -namespace XmlRpc { - - - XmlRpcSource::XmlRpcSource(int fd /*= -1*/, bool deleteOnClose /*= false*/) - : _fd(fd), _deleteOnClose(deleteOnClose), _keepOpen(false) - { - } - - XmlRpcSource::~XmlRpcSource() - { - } - - - void - XmlRpcSource::close() - { - if (_fd != -1) { - XmlRpcUtil::log(2,"XmlRpcSource::close: closing socket %d.", _fd); - XmlRpcSocket::close(_fd); - XmlRpcUtil::log(2,"XmlRpcSource::close: done closing socket %d.", _fd); - _fd = -1; - } - if (_deleteOnClose) { - XmlRpcUtil::log(2,"XmlRpcSource::close: deleting this"); - _deleteOnClose = false; - delete this; - } - if (_ssl_ssl != (SSL *) NULL) { - SSL_shutdown (_ssl_ssl); - SSL_free (_ssl_ssl); - SSL_CTX_free (_ssl_ctx); - } - } - -} // namespace XmlRpc diff --git a/branches/lydia/xmlrpc++/XmlRpcSource.h b/branches/lydia/xmlrpc++/XmlRpcSource.h deleted file mode 100644 index 2843241..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcSource.h +++ /dev/null @@ -1,67 +0,0 @@ - -#ifndef _XMLRPCSOURCE_H_ -#define _XMLRPCSOURCE_H_ -// -// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley -// -#if defined(_MSC_VER) -# pragma warning(disable:4786) // identifier was truncated in debug info -#endif - -// Deal with SSL dependencies -#include -#include -#include -#include -#include - -namespace XmlRpc { - - //! An RPC source represents a file descriptor to monitor - class XmlRpcSource { - public: - //! Constructor - //! @param fd The socket file descriptor to monitor. - //! @param deleteOnClose If true, the object deletes itself when close is called. - XmlRpcSource(int fd = -1, bool deleteOnClose = false); - - //! Destructor - virtual ~XmlRpcSource(); - - //! Return the file descriptor being monitored. - int getfd() const { return _fd; } - //! Specify the file descriptor to monitor. - void setfd(int fd) { _fd = fd; } - - //! Return whether the file descriptor should be kept open if it is no longer monitored. - bool getKeepOpen() const { return _keepOpen; } - //! Specify whether the file descriptor should be kept open if it is no longer monitored. - void setKeepOpen(bool b=true) { _keepOpen = b; } - - //! Close the owned fd. If deleteOnClose was specified at construction, the object is deleted. - virtual void close(); - - //! Return true to continue monitoring this source - virtual unsigned handleEvent(unsigned eventType) = 0; - - // Keep track of SSL status and other such things - bool _ssl; - SSL_CTX* _ssl_ctx; - SSL* _ssl_ssl; - SSL_METHOD* _ssl_meth; - private: - - // Socket. This should really be a SOCKET (an alias for unsigned int*) on windows... - int _fd; - - // In the server, a new source (XmlRpcServerConnection) is created - // for each connected client. When each connection is closed, the - // corresponding source object is deleted. - bool _deleteOnClose; - - // In the client, keep connections open if you intend to make multiple calls. - bool _keepOpen; - }; -} // namespace XmlRpc - -#endif //_XMLRPCSOURCE_H_ diff --git a/branches/lydia/xmlrpc++/XmlRpcThread.cpp b/branches/lydia/xmlrpc++/XmlRpcThread.cpp deleted file mode 100644 index 8a91d87..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcThread.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#if defined(XMLRPC_THREADS) - -#include "XmlRpcThread.h" - -#if defined(_WINDOWS) -# define WIN32_LEAN_AND_MEAN -# include -# include -#else -# include -#endif - - -using namespace XmlRpc; - - -//! Destructor. Does not perform a join() (ie, the thread may continue to run). -XmlRpcThread::~XmlRpcThread() -{ - if (_pThread) - { -#if defined(_WINDOWS) - ::CloseHandle((HANDLE)_pThread); -#else - ::pthread_detach((pthread_t)_pThread); -#endif - _pThread = 0; - } -} - -//! Execute the run method of the runnable object in a separate thread. -//! Returns immediately in the calling thread. -void -XmlRpcThread::start() -{ - if ( ! _pThread) - { -#if defined(_WINDOWS) - unsigned threadID; - _pThread = (HANDLE)_beginthreadex(NULL, 0, &runInThread, this, 0, &threadID); -#else - ::pthread_create((pthread_t*) &_pThread, NULL, &runInThread, this); -#endif - } -} - -//! Waits until the thread exits. -void -XmlRpcThread::join() -{ - if (_pThread) - { -#if defined(_WINDOWS) - ::WaitForSingleObject(_pThread, INFINITE); - ::CloseHandle(_pThread); -#else - ::pthread_join((pthread_t)_pThread, 0); -#endif - _pThread = 0; - } -} - -//! Start the runnable going in a thread -unsigned int -XmlRpcThread::runInThread(void* pThread) -{ - XmlRpcThread* t = (XmlRpcThread*)pThread; - t->getRunnable()->run(); - return 0; -} - -#endif // XMLRPC_THREADS - - diff --git a/branches/lydia/xmlrpc++/XmlRpcThread.h b/branches/lydia/xmlrpc++/XmlRpcThread.h deleted file mode 100644 index 6f4ec78..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcThread.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef _XMLRPCTHREAD_H_ -#define _XMLRPCTHREAD_H_ -// -// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley -// -#if defined(_MSC_VER) -# pragma warning(disable:4786) // identifier was truncated in debug info -#endif - -namespace XmlRpc { - - //! An abstract class providing an interface for objects that can run in a separate thread. - class XmlRpcRunnable { - public: - //! Code to be executed. - virtual void run() = 0; - }; // class XmlRpcRunnable - - - //! A simple platform-independent thread API implemented for posix and windows. - class XmlRpcThread { - public: - //! Construct a thread object. Not usable until setRunnable() has been called. - XmlRpcThread() : _runner(0), _pThread(0) {} - - //! Construct a thread object. - XmlRpcThread(XmlRpcRunnable* runnable) : _runner(runnable), _pThread(0) {} - - //! Destructor. Does not perform a join() (ie, the thread may continue to run). - ~XmlRpcThread(); - - //! Execute the run method of the runnable object in a separate thread. - //! Returns immediately in the calling thread. - void start(); - - //! Waits until the thread exits. - void join(); - - //! Access the runnable - XmlRpcRunnable* getRunnable() const { return _runner; } - - //! Set the runnable - void setRunnable(XmlRpcRunnable* r) { _runner = r; } - - private: - - //! Start the runnable going in a thread - static unsigned int __stdcall runInThread(void* pThread); - - //! Code to be executed - XmlRpcRunnable* _runner; - - //! Native thread object - void* _pThread; - - }; // class XmlRpcThread - -} // namespace XmlRpc - -#endif // _XMLRPCTHREAD_H_ diff --git a/branches/lydia/xmlrpc++/XmlRpcThreadedServer.cpp b/branches/lydia/xmlrpc++/XmlRpcThreadedServer.cpp deleted file mode 100644 index 3f40e49..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcThreadedServer.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#if defined(XMLRPC_THREADS) - -#include "XmlRpcThreadedServer.h" -//#include "XmlRpcServerConnection.h" - - -using namespace XmlRpc; - -// executeRequestThreaded: -// remove the serverConnection from the dispatcher (but don't close the socket) -// push the request onto the request queue -// (acquire the mutex, push_back request, release mutex, incr semaphore) -// - -// worker::run -// while ! stopped -// pop a request off the request queue (block on semaphore/decr, acquire mutex, get request, rel) -// executeRequest (parse, run, generate response) -// notify the serverConnection that the response is available -// (the serverConnection needs to add itself back to the dispatcher safely - mutex) - -// How do I interrupt the dispatcher if it is waiting in a select call? -// i) Replace select with WaitForMultipleObjects, using WSAEventSelect to associate -// each socket with an event object, and adding an additional "signal" event. -// - -#endif // XMLRPC_THREADS diff --git a/branches/lydia/xmlrpc++/XmlRpcThreadedServer.h b/branches/lydia/xmlrpc++/XmlRpcThreadedServer.h deleted file mode 100644 index bedbeec..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcThreadedServer.h +++ /dev/null @@ -1,67 +0,0 @@ - -#ifndef _XMLRPCTHREADEDSERVER_H_ -#define _XMLRPCTHREADEDSERVER_H_ -// -// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley -// -#if defined(_MSC_VER) -# pragma warning(disable:4786) // identifier was truncated in debug info -#endif - -#ifndef MAKEDEPEND -# include -# include -#endif - - -#include "XmlRpcMutex.h" -#include "XmlRpcServer.h" -#include "XmlRpcThread.h" - - -namespace XmlRpc { - - //! A class to handle multiple simultaneous XML RPC requests - class XmlRpcThreadedServer : public XmlRpcServer { - public: - - //! Create a server object with a specified number of worker threads. - XmlRpcThreadedServer(int nWorkers = 6) : _workers(nWorkers) {} - - - //! Execute a request - - protected: - - //! Each client request is assigned to one worker to handle. - //! Workers are executed on separate threads, and one worker may be - //! responsible for dispatching events to multiple client connections. - class Worker : XmlRpcRunnable { - public: - //! Constructor. Executes the run method in a separate thread. - Worker() { _thread.setRunnable(this); _thread.start(); } - - //! Implement the Runnable interface - void run(); - - protected: - - //! The thread this worker is running in. - XmlRpcThread _thread; - - }; - - - //! The worker pool - std::vector _workers; - - - //! Serialize dispatcher access - XmlRpcMutex _mutex; - - - }; // class XmlRpcThreadedServer - -} - -#endif // _XMLRPCTHREADEDSERVER_H_ diff --git a/branches/lydia/xmlrpc++/XmlRpcUtil.cpp b/branches/lydia/xmlrpc++/XmlRpcUtil.cpp deleted file mode 100644 index a084814..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcUtil.cpp +++ /dev/null @@ -1,259 +0,0 @@ - -#include "XmlRpcUtil.h" - -#ifndef MAKEDEPEND -# include -# include -# include -# include -# include -#endif - -#include "XmlRpc.h" - -using namespace XmlRpc; - - -//#define USE_WINDOWS_DEBUG // To make the error and log messages go to VC++ debug output -#ifdef USE_WINDOWS_DEBUG -#define WIN32_LEAN_AND_MEAN -#include -#endif - -// Version id -const char XmlRpc::XMLRPC_VERSION[] = "XMLRPC++ 0.8"; - -// Default log verbosity: 0 for no messages through 5 (writes everything) -int XmlRpcLogHandler::_verbosity = 0; - -// Default log handler -static class DefaultLogHandler : public XmlRpcLogHandler { -public: - - void log(int level, const char* msg) { -#ifdef USE_WINDOWS_DEBUG - if (level <= _verbosity) { OutputDebugString(msg); OutputDebugString("\n"); } -#else - if (level <= _verbosity) std::cout << msg << std::endl; -#endif - } - -} defaultLogHandler; - -// Message log singleton -XmlRpcLogHandler* XmlRpcLogHandler::_logHandler = &defaultLogHandler; - - -// Default error handler -static class DefaultErrorHandler : public XmlRpcErrorHandler { -public: - - void error(const char* msg) { -#ifdef USE_WINDOWS_DEBUG - OutputDebugString(msg); OutputDebugString("\n"); -#else - std::cerr << msg << std::endl; -#endif - } -} defaultErrorHandler; - - -// Error handler singleton -XmlRpcErrorHandler* XmlRpcErrorHandler::_errorHandler = &defaultErrorHandler; - - -// Easy API for log verbosity -int XmlRpc::getVerbosity() { return XmlRpcLogHandler::getVerbosity(); } -void XmlRpc::setVerbosity(int level) { XmlRpcLogHandler::setVerbosity(level); } - - - -void XmlRpcUtil::log(int level, const char* fmt, ...) -{ - if (level <= XmlRpcLogHandler::getVerbosity()) - { - va_list va; - char buf[1024]; - va_start( va, fmt); - vsnprintf(buf,sizeof(buf)-1,fmt,va); - buf[sizeof(buf)-1] = 0; - XmlRpcLogHandler::getLogHandler()->log(level, buf); - } -} - - -void XmlRpcUtil::error(const char* fmt, ...) -{ - va_list va; - va_start(va, fmt); - char buf[1024]; - vsnprintf(buf,sizeof(buf)-1,fmt,va); - buf[sizeof(buf)-1] = 0; - XmlRpcErrorHandler::getErrorHandler()->error(buf); -} - - -// Returns contents between and , updates offset to char after -std::string -XmlRpcUtil::parseTag(const char* tag, std::string const& xml, int* offset) -{ - if (*offset >= int(xml.length())) return std::string(); - size_t istart = xml.find(tag, *offset); - if (istart == std::string::npos) return std::string(); - istart += strlen(tag); - std::string etag = "= int(xml.length())) return false; - size_t istart = xml.find(tag, *offset); - if (istart == std::string::npos) - return false; - - *offset = int(istart + strlen(tag)); - return true; -} - - -// Returns true if the tag is found at the specified offset (modulo any whitespace) -// and updates offset to the char after the tag -bool -XmlRpcUtil::nextTagIs(const char* tag, std::string const& xml, int* offset) -{ - if (*offset >= int(xml.length())) return false; - const char* cp = xml.c_str() + *offset; - int nc = 0; - while (*cp && isspace(*cp)) { - ++cp; - ++nc; - } - - int len = int(strlen(tag)); - if (*cp && (strncmp(cp, tag, len) == 0)) { - *offset += nc + len; - return true; - } - return false; -} - -// Returns the next tag and updates offset to the char after the tag, or empty string -// if the next non-whitespace character is not '<'. Ignores parameters and values within -// the tag entity. -std::string -XmlRpcUtil::getNextTag(std::string const& xml, int* offset) -{ - if (*offset >= int(xml.length())) return std::string(); - - const char* cp = xml.c_str() + size_t(*offset); - const char* startcp = cp; - while (*cp && isspace(*cp)) - ++cp; - - - if (*cp != '<') return std::string(); - - // Tag includes the non-blank characters after < - const char* start = cp++; - while (*cp != '>' && *cp != 0 && ! isspace(*cp)) - ++cp; - - std::string s(start, cp-start+1); - - if (*cp != '>') // Skip parameters and values - { - while (*cp != '>' && *cp != 0) - ++cp; - - s[s.length()-1] = *cp; - } - - *offset += int(cp - startcp + 1); - return s; -} - - - -// xml encodings (xml-encoded entities are preceded with '&') -static const char AMP = '&'; -static const char rawEntity[] = { '<', '>', '&', '\'', '\"', 0 }; -static const char* xmlEntity[] = { "lt;", "gt;", "amp;", "apos;", "quot;", 0 }; -static const int xmlEntLen[] = { 3, 3, 4, 5, 5 }; - - -// Replace xml-encoded entities with the raw text equivalents. - -std::string -XmlRpcUtil::xmlDecode(const std::string& encoded) -{ - std::string::size_type iAmp = encoded.find(AMP); - if (iAmp == std::string::npos) - return encoded; - - std::string decoded(encoded, 0, iAmp); - std::string::size_type iSize = encoded.size(); - decoded.reserve(iSize); - - const char* ens = encoded.c_str(); - while (iAmp != iSize) { - if (encoded[iAmp] == AMP && iAmp+1 < iSize) { - int iEntity; - for (iEntity=0; xmlEntity[iEntity] != 0; ++iEntity) - //if (encoded.compare(iAmp+1, xmlEntLen[iEntity], xmlEntity[iEntity]) == 0) - if (strncmp(ens+iAmp+1, xmlEntity[iEntity], xmlEntLen[iEntity]) == 0) - { - decoded += rawEntity[iEntity]; - iAmp += xmlEntLen[iEntity]+1; - break; - } - if (xmlEntity[iEntity] == 0) // unrecognized sequence - decoded += encoded[iAmp++]; - - } else { - decoded += encoded[iAmp++]; - } - } - - return decoded; -} - - -// Replace raw text with xml-encoded entities. - -std::string -XmlRpcUtil::xmlEncode(const std::string& raw) -{ - std::string::size_type iRep = raw.find_first_of(rawEntity); - if (iRep == std::string::npos) - return raw; - - std::string encoded(raw, 0, iRep); - std::string::size_type iSize = raw.size(); - - while (iRep != iSize) { - int iEntity; - for (iEntity=0; rawEntity[iEntity] != 0; ++iEntity) - if (raw[iRep] == rawEntity[iEntity]) - { - encoded += AMP; - encoded += xmlEntity[iEntity]; - break; - } - if (rawEntity[iEntity] == 0) - encoded += raw[iRep]; - ++iRep; - } - return encoded; -} - - - diff --git a/branches/lydia/xmlrpc++/XmlRpcUtil.h b/branches/lydia/xmlrpc++/XmlRpcUtil.h deleted file mode 100644 index 8128f72..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcUtil.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef _XMLRPCUTIL_H_ -#define _XMLRPCUTIL_H_ -// -// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley -// -#if defined(_MSC_VER) -# pragma warning(disable:4786) // identifier was truncated in debug info -#endif - -#ifndef MAKEDEPEND -# include -#endif - -#if defined(_MSC_VER) -# define snprintf _snprintf -# define vsnprintf _vsnprintf -# define strcasecmp _stricmp -# define strncasecmp _strnicmp -#elif defined(__BORLANDC__) -# define strcasecmp stricmp -# define strncasecmp strnicmp -#endif - -namespace XmlRpc { - - //! Utilities for XML parsing, encoding, and decoding and message handlers. - class XmlRpcUtil { - public: - // hokey xml parsing - //! Returns contents between and , updates offset to char after - static std::string parseTag(const char* tag, std::string const& xml, int* offset); - - //! Returns true if the tag is found and updates offset to the char after the tag - static bool findTag(const char* tag, std::string const& xml, int* offset); - - //! Returns the next tag and updates offset to the char after the tag, or empty string - //! if the next non-whitespace character is not '<' - static std::string getNextTag(std::string const& xml, int* offset); - - //! Returns true if the tag is found at the specified offset (modulo any whitespace) - //! and updates offset to the char after the tag - static bool nextTagIs(const char* tag, std::string const& xml, int* offset); - - - //! Convert raw text to encoded xml. - static std::string xmlEncode(const std::string& raw); - - //! Convert encoded xml to raw text - static std::string xmlDecode(const std::string& encoded); - - - //! Dump messages somewhere - static void log(int level, const char* fmt, ...); - - //! Dump error messages somewhere - static void error(const char* fmt, ...); - - }; -} // namespace XmlRpc - -#endif // _XMLRPCUTIL_H_ diff --git a/branches/lydia/xmlrpc++/XmlRpcValue.cpp b/branches/lydia/xmlrpc++/XmlRpcValue.cpp deleted file mode 100644 index 69627a4..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcValue.cpp +++ /dev/null @@ -1,611 +0,0 @@ - -#include "XmlRpcValue.h" -#include "XmlRpcException.h" -#include "XmlRpcUtil.h" -#include "base64.h" - -#ifndef MAKEDEPEND -# include -# include -# include -# include -#endif - -namespace XmlRpc { - - - static const char VALUE_TAG[] = ""; - static const char VALUE_ETAG[] = ""; - - static const char BOOLEAN_TAG[] = ""; - static const char BOOLEAN_ETAG[] = ""; - static const char DOUBLE_TAG[] = ""; - static const char DOUBLE_ETAG[] = ""; - static const char INT_TAG[] = ""; - static const char I4_TAG[] = ""; - static const char I4_ETAG[] = ""; - static const char STRING_TAG[] = ""; - static const char DATETIME_TAG[] = ""; - static const char DATETIME_ETAG[] = ""; - static const char BASE64_TAG[] = ""; - static const char BASE64_ETAG[] = ""; - - static const char ARRAY_TAG[] = ""; - static const char DATA_TAG[] = ""; - static const char DATA_ETAG[] = ""; - static const char ARRAY_ETAG[] = ""; - - static const char STRUCT_TAG[] = ""; - static const char MEMBER_TAG[] = ""; - static const char NAME_TAG[] = ""; - static const char NAME_ETAG[] = ""; - static const char MEMBER_ETAG[] = ""; - static const char STRUCT_ETAG[] = ""; - - - - // Format strings - std::string XmlRpcValue::_doubleFormat("%f"); - - - - // Clean up - void XmlRpcValue::invalidate() - { - switch (_type) { - case TypeString: delete _value.asString; break; - case TypeDateTime: delete _value.asTime; break; - case TypeBase64: delete _value.asBinary; break; - case TypeArray: delete _value.asArray; break; - case TypeStruct: delete _value.asStruct; break; - default: break; - } - _type = TypeInvalid; - _value.asBinary = 0; - } - - - // Type checking - void XmlRpcValue::assertTypeOrInvalid(Type t) - { - if (_type == TypeInvalid) - { - _type = t; - switch (_type) { // Ensure there is a valid value for the type - case TypeString: _value.asString = new std::string(); break; - case TypeDateTime: _value.asTime = new struct tm(); break; - case TypeBase64: _value.asBinary = new BinaryData(); break; - case TypeArray: _value.asArray = new ValueArray(); break; - case TypeStruct: _value.asStruct = new ValueStruct(); break; - default: _value.asBinary = 0; break; - } - } - else if (_type != t) - throw XmlRpcException("type error"); - } - - void XmlRpcValue::assertArray(int size) const - { - if (_type != TypeArray) - throw XmlRpcException("type error: expected an array"); - else if (int(_value.asArray->size()) < size) - throw XmlRpcException("range error: array index too large"); - } - - - void XmlRpcValue::assertArray(int size) - { - if (_type == TypeInvalid) { - _type = TypeArray; - _value.asArray = new ValueArray(size); - } else if (_type == TypeArray) { - if (int(_value.asArray->size()) < size) - _value.asArray->resize(size); - } else - throw XmlRpcException("type error: expected an array"); - } - - void XmlRpcValue::assertStruct() - { - if (_type == TypeInvalid) { - _type = TypeStruct; - _value.asStruct = new ValueStruct(); - } else if (_type != TypeStruct) - throw XmlRpcException("type error: expected a struct"); - } - - - // Operators - XmlRpcValue& XmlRpcValue::operator=(XmlRpcValue const& rhs) - { - if (this != &rhs) - { - invalidate(); - _type = rhs._type; - switch (_type) { - case TypeBoolean: _value.asBool = rhs._value.asBool; break; - case TypeInt: _value.asInt = rhs._value.asInt; break; - case TypeDouble: _value.asDouble = rhs._value.asDouble; break; - case TypeDateTime: _value.asTime = new struct tm(*rhs._value.asTime); break; - case TypeString: _value.asString = new std::string(*rhs._value.asString); break; - case TypeBase64: _value.asBinary = new BinaryData(*rhs._value.asBinary); break; - case TypeArray: _value.asArray = new ValueArray(*rhs._value.asArray); break; - case TypeStruct: _value.asStruct = new ValueStruct(*rhs._value.asStruct); break; - default: _value.asBinary = 0; break; - } - } - return *this; - } - - - // Predicate for tm equality - static bool tmEq(struct tm const& t1, struct tm const& t2) { - return t1.tm_sec == t2.tm_sec && t1.tm_min == t2.tm_min && - t1.tm_hour == t2.tm_hour && t1.tm_mday == t1.tm_mday && - t1.tm_mon == t2.tm_mon && t1.tm_year == t2.tm_year; - } - - bool XmlRpcValue::operator==(XmlRpcValue const& other) const - { - if (_type != other._type) - return false; - - switch (_type) { - case TypeBoolean: return ( !_value.asBool && !other._value.asBool) || - ( _value.asBool && other._value.asBool); - case TypeInt: return _value.asInt == other._value.asInt; - case TypeDouble: return _value.asDouble == other._value.asDouble; - case TypeDateTime: return tmEq(*_value.asTime, *other._value.asTime); - case TypeString: return *_value.asString == *other._value.asString; - case TypeBase64: return *_value.asBinary == *other._value.asBinary; - case TypeArray: return *_value.asArray == *other._value.asArray; - - // The map<>::operator== requires the definition of value< for kcc - case TypeStruct: //return *_value.asStruct == *other._value.asStruct; - { - if (_value.asStruct->size() != other._value.asStruct->size()) - return false; - - ValueStruct::const_iterator it1=_value.asStruct->begin(); - ValueStruct::const_iterator it2=other._value.asStruct->begin(); - while (it1 != _value.asStruct->end()) { - const XmlRpcValue& v1 = it1->second; - const XmlRpcValue& v2 = it2->second; - if ( ! (v1 == v2)) - return false; - it1++; - it2++; - } - return true; - } - default: break; - } - return true; // Both invalid values ... - } - - bool XmlRpcValue::operator!=(XmlRpcValue const& other) const - { - return !(*this == other); - } - - - // Works for strings, binary data, arrays, and structs. - int XmlRpcValue::size() const - { - switch (_type) { - case TypeString: return int(_value.asString->size()); - case TypeBase64: return int(_value.asBinary->size()); - case TypeArray: return int(_value.asArray->size()); - case TypeStruct: return int(_value.asStruct->size()); - default: break; - } - - throw XmlRpcException("type error"); - } - - // Checks for existence of struct member - bool XmlRpcValue::hasMember(const std::string& name) const - { - return _type == TypeStruct && _value.asStruct->find(name) != _value.asStruct->end(); - } - - // Set the value from xml. The chars at *offset into valueXml - // should be the start of a tag. Destroys any existing value. - bool XmlRpcValue::fromXml(std::string const& valueXml, int* offset) - { - int savedOffset = *offset; - - invalidate(); - if ( ! XmlRpcUtil::nextTagIs(VALUE_TAG, valueXml, offset)) - return false; // Not a value, offset not updated - - int afterValueOffset = *offset; - std::string typeTag = XmlRpcUtil::getNextTag(valueXml, offset); - bool result = false; - if (typeTag == BOOLEAN_TAG) - result = boolFromXml(valueXml, offset); - else if (typeTag == I4_TAG || typeTag == INT_TAG) - result = intFromXml(valueXml, offset); - else if (typeTag == DOUBLE_TAG) - result = doubleFromXml(valueXml, offset); - else if (typeTag.empty() || typeTag == STRING_TAG) - result = stringFromXml(valueXml, offset); - else if (typeTag == DATETIME_TAG) - result = timeFromXml(valueXml, offset); - else if (typeTag == BASE64_TAG) - result = binaryFromXml(valueXml, offset); - else if (typeTag == ARRAY_TAG) - result = arrayFromXml(valueXml, offset); - else if (typeTag == STRUCT_TAG) - result = structFromXml(valueXml, offset); - // Watch for empty/blank strings with no tag - else if (typeTag == VALUE_ETAG) - { - *offset = afterValueOffset; // back up & try again - result = stringFromXml(valueXml, offset); - } - - if (result) // Skip over the tag - XmlRpcUtil::findTag(VALUE_ETAG, valueXml, offset); - else // Unrecognized tag after - *offset = savedOffset; - - return result; - } - - // Encode the Value in xml - std::string XmlRpcValue::toXml() const - { - switch (_type) { - case TypeBoolean: return boolToXml(); - case TypeInt: return intToXml(); - case TypeDouble: return doubleToXml(); - case TypeString: return stringToXml(); - case TypeDateTime: return timeToXml(); - case TypeBase64: return binaryToXml(); - case TypeArray: return arrayToXml(); - case TypeStruct: return structToXml(); - default: break; - } - return std::string(); // Invalid value - } - - - // Boolean - bool XmlRpcValue::boolFromXml(std::string const& valueXml, int* offset) - { - const char* valueStart = valueXml.c_str() + *offset; - char* valueEnd; - long ivalue = strtol(valueStart, &valueEnd, 10); - if (valueEnd == valueStart || (ivalue != 0 && ivalue != 1)) - return false; - - _type = TypeBoolean; - _value.asBool = (ivalue == 1); - *offset += int(valueEnd - valueStart); - return true; - } - - std::string XmlRpcValue::boolToXml() const - { - std::string xml = VALUE_TAG; - xml += BOOLEAN_TAG; - xml += (_value.asBool ? "1" : "0"); - xml += BOOLEAN_ETAG; - xml += VALUE_ETAG; - return xml; - } - - // Int - bool XmlRpcValue::intFromXml(std::string const& valueXml, int* offset) - { - const char* valueStart = valueXml.c_str() + *offset; - char* valueEnd; - long ivalue = strtol(valueStart, &valueEnd, 10); - if (valueEnd == valueStart) - return false; - - _type = TypeInt; - _value.asInt = int(ivalue); - *offset += int(valueEnd - valueStart); - return true; - } - - std::string XmlRpcValue::intToXml() const - { - char buf[256]; - snprintf(buf, sizeof(buf)-1, "%d", _value.asInt); - buf[sizeof(buf)-1] = 0; - std::string xml = VALUE_TAG; - xml += I4_TAG; - xml += buf; - xml += I4_ETAG; - xml += VALUE_ETAG; - return xml; - } - - // Double - bool XmlRpcValue::doubleFromXml(std::string const& valueXml, int* offset) - { - const char* valueStart = valueXml.c_str() + *offset; - char* valueEnd; - double dvalue = strtod(valueStart, &valueEnd); - if (valueEnd == valueStart) - return false; - - _type = TypeDouble; - _value.asDouble = dvalue; - *offset += int(valueEnd - valueStart); - return true; - } - - std::string XmlRpcValue::doubleToXml() const - { - char buf[256]; - snprintf(buf, sizeof(buf)-1, getDoubleFormat().c_str(), _value.asDouble); - buf[sizeof(buf)-1] = 0; - - std::string xml = VALUE_TAG; - xml += DOUBLE_TAG; - xml += buf; - xml += DOUBLE_ETAG; - xml += VALUE_ETAG; - return xml; - } - - // String - bool XmlRpcValue::stringFromXml(std::string const& valueXml, int* offset) - { - size_t valueEnd = valueXml.find('<', *offset); - if (valueEnd == std::string::npos) - return false; // No end tag; - - _type = TypeString; - _value.asString = new std::string(XmlRpcUtil::xmlDecode(valueXml.substr(*offset, valueEnd-*offset))); - *offset += int(_value.asString->length()); - return true; - } - - std::string XmlRpcValue::stringToXml() const - { - std::string xml = VALUE_TAG; - //xml += STRING_TAG; optional - xml += XmlRpcUtil::xmlEncode(*_value.asString); - //xml += STRING_ETAG; - xml += VALUE_ETAG; - return xml; - } - - // DateTime (stored as a struct tm) - bool XmlRpcValue::timeFromXml(std::string const& valueXml, int* offset) - { - size_t valueEnd = valueXml.find('<', *offset); - if (valueEnd == std::string::npos) - return false; // No end tag; - - std::string stime = valueXml.substr(*offset, valueEnd-*offset); - - struct tm t; - if (sscanf(stime.c_str(),"%4d%2d%2dT%2d:%2d:%2d",&t.tm_year,&t.tm_mon,&t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec) != 6) - return false; - - t.tm_year -= 1900; - t.tm_isdst = -1; - _type = TypeDateTime; - _value.asTime = new struct tm(t); - *offset += int(stime.length()); - return true; - } - - std::string XmlRpcValue::timeToXml() const - { - struct tm* t = _value.asTime; - char buf[20]; - snprintf(buf, sizeof(buf)-1, "%04d%02d%02dT%02d:%02d:%02d", - 1900+t->tm_year,t->tm_mon,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec); - buf[sizeof(buf)-1] = 0; - - std::string xml = VALUE_TAG; - xml += DATETIME_TAG; - xml += buf; - xml += DATETIME_ETAG; - xml += VALUE_ETAG; - return xml; - } - - - // Base64 - bool XmlRpcValue::binaryFromXml(std::string const& valueXml, int* offset) - { - size_t valueEnd = valueXml.find('<', *offset); - if (valueEnd == std::string::npos) - return false; // No end tag; - - _type = TypeBase64; - std::string asString = valueXml.substr(*offset, valueEnd-*offset); - _value.asBinary = new BinaryData(); - // check whether base64 encodings can contain chars xml encodes... - - // convert from base64 to binary - int iostatus = 0; - base64 decoder; - std::back_insert_iterator ins = std::back_inserter(*(_value.asBinary)); - decoder.get(asString.begin(), asString.end(), ins, iostatus); - - *offset += int(asString.length()); - return true; - } - - - std::string XmlRpcValue::binaryToXml() const - { - // convert to base64 - std::vector base64data; - int iostatus = 0; - base64 encoder; - std::back_insert_iterator > ins = std::back_inserter(base64data); - encoder.put(_value.asBinary->begin(), _value.asBinary->end(), ins, iostatus, base64<>::crlf()); - - // Wrap with xml - std::string xml = VALUE_TAG; - xml += BASE64_TAG; - xml.append(base64data.begin(), base64data.end()); - xml += BASE64_ETAG; - xml += VALUE_ETAG; - return xml; - } - - - // Array - bool XmlRpcValue::arrayFromXml(std::string const& valueXml, int* offset) - { - if ( ! XmlRpcUtil::nextTagIs(DATA_TAG, valueXml, offset)) - return false; - - _type = TypeArray; - _value.asArray = new ValueArray; - XmlRpcValue v; - while (v.fromXml(valueXml, offset)) - _value.asArray->push_back(v); // copy... - - // Skip the trailing - (void) XmlRpcUtil::nextTagIs(DATA_ETAG, valueXml, offset); - return true; - } - - - // In general, its preferable to generate the xml of each element of the - // array as it is needed rather than glomming up one big string. - std::string XmlRpcValue::arrayToXml() const - { - std::string xml = VALUE_TAG; - xml += ARRAY_TAG; - xml += DATA_TAG; - - int s = int(_value.asArray->size()); - for (int i=0; iat(i).toXml(); - - xml += DATA_ETAG; - xml += ARRAY_ETAG; - xml += VALUE_ETAG; - return xml; - } - - - // Struct - bool XmlRpcValue::structFromXml(std::string const& valueXml, int* offset) - { - _type = TypeStruct; - _value.asStruct = new ValueStruct; - - while (XmlRpcUtil::nextTagIs(MEMBER_TAG, valueXml, offset)) { - // name - const std::string name = XmlRpcUtil::parseTag(NAME_TAG, valueXml, offset); - // value - XmlRpcValue val(valueXml, offset); - if ( ! val.valid()) { - invalidate(); - return false; - } - const std::pair p(name, val); - _value.asStruct->insert(p); - - (void) XmlRpcUtil::nextTagIs(MEMBER_ETAG, valueXml, offset); - } - return true; - } - - - // In general, its preferable to generate the xml of each element - // as it is needed rather than glomming up one big string. - std::string XmlRpcValue::structToXml() const - { - std::string xml = VALUE_TAG; - xml += STRUCT_TAG; - - ValueStruct::const_iterator it; - for (it=_value.asStruct->begin(); it!=_value.asStruct->end(); ++it) { - xml += MEMBER_TAG; - xml += NAME_TAG; - xml += XmlRpcUtil::xmlEncode(it->first); - xml += NAME_ETAG; - xml += it->second.toXml(); - xml += MEMBER_ETAG; - } - - xml += STRUCT_ETAG; - xml += VALUE_ETAG; - return xml; - } - - - - // Write the value without xml encoding it - std::ostream& XmlRpcValue::write(std::ostream& os) const { - switch (_type) { - default: break; - case TypeBoolean: os << _value.asBool; break; - case TypeInt: os << _value.asInt; break; - case TypeDouble: os << _value.asDouble; break; - case TypeString: os << *_value.asString; break; - case TypeDateTime: - { - struct tm* t = _value.asTime; - char buf[20]; - snprintf(buf, sizeof(buf)-1, "%4d%02d%02dT%02d:%02d:%02d", - t->tm_year,t->tm_mon,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec); - buf[sizeof(buf)-1] = 0; - os << buf; - break; - } - case TypeBase64: - { - int iostatus = 0; - std::ostreambuf_iterator out(os); - base64 encoder; - encoder.put(_value.asBinary->begin(), _value.asBinary->end(), out, iostatus, base64<>::crlf()); - break; - } - case TypeArray: - { - int s = int(_value.asArray->size()); - os << '{'; - for (int i=0; i 0) os << ','; - _value.asArray->at(i).write(os); - } - os << '}'; - break; - } - case TypeStruct: - { - os << '['; - ValueStruct::const_iterator it; - for (it=_value.asStruct->begin(); it!=_value.asStruct->end(); ++it) - { - if (it!=_value.asStruct->begin()) os << ','; - os << it->first << ':'; - it->second.write(os); - } - os << ']'; - break; - } - - } - - return os; - } - -} // namespace XmlRpc - - -// ostream -std::ostream& operator<<(std::ostream& os, XmlRpc::XmlRpcValue& v) -{ - // If you want to output in xml format: - //return os << v.toXml(); - return v.write(os); -} - diff --git a/branches/lydia/xmlrpc++/XmlRpcValue.h b/branches/lydia/xmlrpc++/XmlRpcValue.h deleted file mode 100644 index b490ae4..0000000 --- a/branches/lydia/xmlrpc++/XmlRpcValue.h +++ /dev/null @@ -1,259 +0,0 @@ - -#ifndef _XMLRPCVALUE_H_ -#define _XMLRPCVALUE_H_ -// -// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley -// - -#if defined(_MSC_VER) -# pragma warning(disable:4786) // identifier was truncated in debug info -#endif - -#ifndef MAKEDEPEND -# include -# include -# include -# include -#endif - -namespace XmlRpc { - - //! A class to represent RPC arguments and results. - //! Each XmlRpcValue object contains a typed value, - //! where the type is determined by the initial value - //! assigned to the object. - // should probably refcount them... - class XmlRpcValue { - public: - - //! XmlRpcValue types - enum Type { - TypeInvalid, - TypeBoolean, - TypeInt, - TypeDouble, - TypeString, - TypeDateTime, - TypeBase64, - TypeArray, - TypeStruct - }; - - // Non-primitive types - typedef std::vector BinaryData; - typedef std::vector ValueArray; - typedef std::map ValueStruct; - - - // Constructors - //! Construct an empty XmlRpcValue - XmlRpcValue() : _type(TypeInvalid) { _value.asBinary = 0; } - - //! Construct an XmlRpcValue with a bool value - XmlRpcValue(bool value) : _type(TypeBoolean) { _value.asBool = value; } - - //! Construct an XmlRpcValue with an int value - XmlRpcValue(int value) : _type(TypeInt) { _value.asInt = value; } - - //! Construct an XmlRpcValue with a double value - XmlRpcValue(double value) : _type(TypeDouble) { _value.asDouble = value; } - - //! Construct an XmlRpcValue with a string value - XmlRpcValue(std::string const& value) : _type(TypeString) - { _value.asString = new std::string(value); } - - //! Construct an XmlRpcValue with a string value. - //! @param value A null-terminated (C) string. - XmlRpcValue(const char* value) : _type(TypeString) - { _value.asString = new std::string(value); } - - //! Construct an XmlRpcValue with a date/time value. - //! @param value A pointer to a struct tm (see localtime) - XmlRpcValue(struct tm* value) : _type(TypeDateTime) - { _value.asTime = new struct tm(*value); } - - //! Construct an XmlRpcValue with a binary data value - //! @param value A pointer to data - //! @param nBytes The length of the data pointed to, in bytes - XmlRpcValue(void* value, int nBytes) : _type(TypeBase64) - { - _value.asBinary = new BinaryData((char*)value, ((char*)value)+nBytes); - } - - //! Construct from xml, beginning at *offset chars into the string, updates offset - XmlRpcValue(std::string const& xml, int* offset) : _type(TypeInvalid) - { if ( ! fromXml(xml,offset)) _type = TypeInvalid; } - - //! Copy constructor - XmlRpcValue(XmlRpcValue const& rhs) : _type(TypeInvalid) { *this = rhs; } - - //! Destructor (make virtual if you want to subclass) - /*virtual*/ ~XmlRpcValue() { invalidate(); } - - //! Erase the current value - void clear() { invalidate(); } - - // Operators - //! Assignment from one XmlRpcValue to this one. - //! @param rhs The value in rhs is copied to this value. - XmlRpcValue& operator=(XmlRpcValue const& rhs); - - //! Assign an int to this XmlRpcValue. - XmlRpcValue& operator=(int const& rhs) { return operator=(XmlRpcValue(rhs)); } - - //! Assign a double to this XmlRpcValue. - XmlRpcValue& operator=(double const& rhs) { return operator=(XmlRpcValue(rhs)); } - - //! Assign a string to this XmlRpcValue. - XmlRpcValue& operator=(const char* rhs) { return operator=(XmlRpcValue(std::string(rhs))); } - - //! Tests two XmlRpcValues for equality - bool operator==(XmlRpcValue const& other) const; - - //! Tests two XmlRpcValues for inequality - bool operator!=(XmlRpcValue const& other) const; - - //! Treat an XmlRpcValue as a bool. - //! Throws XmlRpcException if the value is initialized to - //! a type that is not TypeBoolean. - operator bool&() { assertTypeOrInvalid(TypeBoolean); return _value.asBool; } - - //! Treat an XmlRpcValue as an int. - //! Throws XmlRpcException if the value is initialized to - //! a type that is not TypeInt. - operator int&() { assertTypeOrInvalid(TypeInt); return _value.asInt; } - - //! Treat an XmlRpcValue as a double. - //! Throws XmlRpcException if the value is initialized to - //! a type that is not TypeDouble. - operator double&() { assertTypeOrInvalid(TypeDouble); return _value.asDouble; } - - //! Treat an XmlRpcValue as a string. - //! Throws XmlRpcException if the value is initialized to - //! a type that is not TypeString. - operator std::string&() { assertTypeOrInvalid(TypeString); return *_value.asString; } - - //! Access the BinaryData value. - //! Throws XmlRpcException if the value is initialized to - //! a type that is not TypeBase64. - operator BinaryData&() { assertTypeOrInvalid(TypeBase64); return *_value.asBinary; } - - //! Access the DateTime value. - //! Throws XmlRpcException if the value is initialized to - //! a type that is not TypeDateTime. - operator struct tm&() { assertTypeOrInvalid(TypeDateTime); return *_value.asTime; } - - - //! Const array value accessor. - //! Access the ith value of the array. - //! Throws XmlRpcException if the value is not an array or if the index i is - //! not a valid index for the array. - XmlRpcValue const& operator[](int i) const { assertArray(i+1); return _value.asArray->at(i); } - - //! Array value accessor. - //! Access the ith value of the array, growing the array if necessary. - //! Throws XmlRpcException if the value is not an array. - XmlRpcValue& operator[](int i) { assertArray(i+1); return _value.asArray->at(i); } - - //! Struct entry accessor. - //! Returns the value associated with the given entry, creating one if necessary. - XmlRpcValue& operator[](std::string const& k) { assertStruct(); return (*_value.asStruct)[k]; } - - //! Struct entry accessor. - //! Returns the value associated with the given entry, creating one if necessary. - XmlRpcValue& operator[](const char* k) { assertStruct(); std::string s(k); return (*_value.asStruct)[s]; } - - //! Access the struct value map. - //! Can be used to iterate over the entries in the map to find all defined entries. - operator ValueStruct const&() { assertStruct(); return *_value.asStruct; } - - // Accessors - //! Return true if the value has been set to something. - bool valid() const { return _type != TypeInvalid; } - - //! Return the type of the value stored. \see Type. - Type const &getType() const { return _type; } - - //! Return the size for string, base64, array, and struct values. - int size() const; - - //! Specify the size for array values. Array values will grow beyond this size if needed. - void setSize(int size) { assertArray(size); } - - //! Check for the existence of a struct member by name. - bool hasMember(const std::string& name) const; - - //! Decode xml. Destroys any existing value. - bool fromXml(std::string const& valueXml, int* offset); - - //! Encode the Value in xml - std::string toXml() const; - - //! Write the value (no xml encoding) - std::ostream& write(std::ostream& os) const; - - // Formatting - //! Return the format used to write double values. - static std::string const& getDoubleFormat() { return _doubleFormat; } - - //! Specify the format used to write double values. - static void setDoubleFormat(const char* f) { _doubleFormat = f; } - - - protected: - // Clean up - void invalidate(); - - // Type checking - void assertTypeOrInvalid(Type t); - void assertArray(int size) const; - void assertArray(int size); - void assertStruct(); - - // XML decoding - bool boolFromXml(std::string const& valueXml, int* offset); - bool intFromXml(std::string const& valueXml, int* offset); - bool doubleFromXml(std::string const& valueXml, int* offset); - bool stringFromXml(std::string const& valueXml, int* offset); - bool timeFromXml(std::string const& valueXml, int* offset); - bool binaryFromXml(std::string const& valueXml, int* offset); - bool arrayFromXml(std::string const& valueXml, int* offset); - bool structFromXml(std::string const& valueXml, int* offset); - - // XML encoding - std::string boolToXml() const; - std::string intToXml() const; - std::string doubleToXml() const; - std::string stringToXml() const; - std::string timeToXml() const; - std::string binaryToXml() const; - std::string arrayToXml() const; - std::string structToXml() const; - - // Format strings - static std::string _doubleFormat; - - // Type tag and values - Type _type; - - // At some point I will split off Arrays and Structs into - // separate ref-counted objects for more efficient copying. - union { - bool asBool; - int asInt; - double asDouble; - struct tm* asTime; - std::string* asString; - BinaryData* asBinary; - ValueArray* asArray; - ValueStruct* asStruct; - } _value; - - }; -} // namespace XmlRpc - - -std::ostream& operator<<(std::ostream& os, XmlRpc::XmlRpcValue& v); - - -#endif // _XMLRPCVALUE_H_ diff --git a/branches/lydia/xmlrpc++/base64.h b/branches/lydia/xmlrpc++/base64.h deleted file mode 100644 index 519ee0f..0000000 --- a/branches/lydia/xmlrpc++/base64.h +++ /dev/null @@ -1,379 +0,0 @@ - - -// base64.hpp -// Autor Konstantin Pilipchuk -// mailto:lostd@ukr.net -// -// - -#if !defined(__BASE64_H_INCLUDED__) -#define __BASE64_H_INCLUDED__ 1 - -#ifndef MAKEDEPEND -# include -#endif - -static -int _base64Chars[]= {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', - 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z', - '0','1','2','3','4','5','6','7','8','9', - '+','/' }; - - -#define _0000_0011 0x03 -#define _1111_1100 0xFC -#define _1111_0000 0xF0 -#define _0011_0000 0x30 -#define _0011_1100 0x3C -#define _0000_1111 0x0F -#define _1100_0000 0xC0 -#define _0011_1111 0x3F - -#define _EQUAL_CHAR (-1) -#define _UNKNOWN_CHAR (-2) - -#define _IOS_FAILBIT std::ios_base::failbit -#define _IOS_EOFBIT std::ios_base::eofbit -#define _IOS_BADBIT std::ios_base::badbit -#define _IOS_GOODBIT std::ios_base::goodbit - -// TEMPLATE CLASS base64_put -template > -class base64 -{ -public: - - typedef unsigned char byte_t; - typedef _E char_type; - typedef _Tr traits_type; - - // base64 requires max line length <= 72 characters - // you can fill end of line - // it may be crlf, crlfsp, noline or other class like it - - - struct crlf - { - template - _OI operator()(_OI _To) const{ - *_To = _Tr::to_char_type('\r'); ++_To; - *_To = _Tr::to_char_type('\n'); ++_To; - - return (_To); - } - }; - - - struct crlfsp - { - template - _OI operator()(_OI _To) const{ - *_To = _Tr::to_char_type('\r'); ++_To; - *_To = _Tr::to_char_type('\n'); ++_To; - *_To = _Tr::to_char_type(' '); ++_To; - - return (_To); - } - }; - - struct noline - { - template - _OI operator()(_OI _To) const{ - return (_To); - } - }; - - struct three2four - { - void zero() - { - _data[0] = 0; - _data[1] = 0; - _data[2] = 0; - } - - byte_t get_0() const - { - return _data[0]; - } - byte_t get_1() const - { - return _data[1]; - } - byte_t get_2() const - { - return _data[2]; - } - - void set_0(byte_t _ch) - { - _data[0] = _ch; - } - - void set_1(byte_t _ch) - { - _data[1] = _ch; - } - - void set_2(byte_t _ch) - { - _data[2] = _ch; - } - - // 0000 0000 1111 1111 2222 2222 - // xxxx xxxx xxxx xxxx xxxx xxxx - // 0000 0011 1111 2222 2233 3333 - - int b64_0() const {return (_data[0] & _1111_1100) >> 2;} - int b64_1() const {return ((_data[0] & _0000_0011) << 4) + ((_data[1] & _1111_0000)>>4);} - int b64_2() const {return ((_data[1] & _0000_1111) << 2) + ((_data[2] & _1100_0000)>>6);} - int b64_3() const {return (_data[2] & _0011_1111);} - - void b64_0(int _ch) {_data[0] = ((_ch & _0011_1111) << 2) | (_0000_0011 & _data[0]);} - - void b64_1(int _ch) { - _data[0] = ((_ch & _0011_0000) >> 4) | (_1111_1100 & _data[0]); - _data[1] = ((_ch & _0000_1111) << 4) | (_0000_1111 & _data[1]); } - - void b64_2(int _ch) { - _data[1] = ((_ch & _0011_1100) >> 2) | (_1111_0000 & _data[1]); - _data[2] = ((_ch & _0000_0011) << 6) | (_0011_1111 & _data[2]); } - - void b64_3(int _ch){ - _data[2] = (_ch & _0011_1111) | (_1100_0000 & _data[2]);} - - private: - byte_t _data[3]; - - }; - - - - - template - _II put(_II _First, _II _Last, _OI _To, _State& _St, _Endline _Endl) const - { - three2four _3to4; - int line_octets = 0; - - while(_First != _Last) - { - _3to4.zero(); - - // берём по 3 символа - _3to4.set_0(*_First); - _First++; - - if(_First == _Last) - { - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To; - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To; - *_To = _Tr::to_char_type('='); ++_To; - *_To = _Tr::to_char_type('='); ++_To; - goto __end; - } - - _3to4.set_1(*_First); - _First++; - - if(_First == _Last) - { - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To; - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To; - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To; - *_To = _Tr::to_char_type('='); ++_To; - goto __end; - } - - _3to4.set_2(*_First); - _First++; - - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To; - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To; - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To; - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_3()]); ++_To; - - if(line_octets == 17) // base64 позволяет длину строки не более 72 символов - { - //_To = _Endl(_To); - *_To = '\n'; ++_To; - line_octets = 0; - } - else - ++line_octets; - } - - __end: ; - - return (_First); - - } - - - template - _II get(_II _First, _II _Last, _OI _To, _State& _St) const - { - three2four _3to4; - int _Char; - - while(_First != _Last) - { - - // Take octet - _3to4.zero(); - - // -- 0 -- - // Search next valid char... - while((_Char = _getCharType(*_First)) < 0 && _Char == _UNKNOWN_CHAR) - { - if(++_First == _Last) - { - _St |= _IOS_FAILBIT|_IOS_EOFBIT; return _First; // unexpected EOF - } - } - - if(_Char == _EQUAL_CHAR){ - // Error! First character in octet can't be '=' - _St |= _IOS_FAILBIT; - return _First; - } - else - _3to4.b64_0(_Char); - - - // -- 1 -- - // Search next valid char... - while(++_First != _Last) - if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR) - break; - - if(_First == _Last) { - _St |= _IOS_FAILBIT|_IOS_EOFBIT; // unexpected EOF - return _First; - } - - if(_Char == _EQUAL_CHAR){ - // Error! Second character in octet can't be '=' - _St |= _IOS_FAILBIT; - return _First; - } - else - _3to4.b64_1(_Char); - - - // -- 2 -- - // Search next valid char... - while(++_First != _Last) - if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR) - break; - - if(_First == _Last) { - // Error! Unexpected EOF. Must be '=' or base64 character - _St |= _IOS_FAILBIT|_IOS_EOFBIT; - return _First; - } - - if(_Char == _EQUAL_CHAR){ - // OK! - _3to4.b64_2(0); - _3to4.b64_3(0); - - // chek for EOF - if(++_First == _Last) - { - // Error! Unexpected EOF. Must be '='. Ignore it. - //_St |= _IOS_BADBIT|_IOS_EOFBIT; - _St |= _IOS_EOFBIT; - } - else - if(_getCharType(*_First) != _EQUAL_CHAR) - { - // Error! Must be '='. Ignore it. - //_St |= _IOS_BADBIT; - } - else - ++_First; // Skip '=' - - // write 1 byte to output - *_To = (byte_t) _3to4.get_0(); - return _First; - } - else - _3to4.b64_2(_Char); - - - // -- 3 -- - // Search next valid char... - while(++_First != _Last) - if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR) - break; - - if(_First == _Last) { - // Unexpected EOF. It's error. But ignore it. - //_St |= _IOS_FAILBIT|_IOS_EOFBIT; - _St |= _IOS_EOFBIT; - - return _First; - } - - if(_Char == _EQUAL_CHAR) - { - // OK! - _3to4.b64_3(0); - - // write to output 2 bytes - *_To = (byte_t) _3to4.get_0(); - *_To = (byte_t) _3to4.get_1(); - - ++_First; // set position to next character - - return _First; - } - else - _3to4.b64_3(_Char); - - - // write to output 3 bytes - *_To = (byte_t) _3to4.get_0(); - *_To = (byte_t) _3to4.get_1(); - *_To = (byte_t) _3to4.get_2(); - - ++_First; - - - } // while(_First != _Last) - - return (_First); - } - -protected: - - int _getCharType(int _Ch) const - { - if(_base64Chars[62] == _Ch) - return 62; - - if(_base64Chars[63] == _Ch) - return 63; - - if((_base64Chars[0] <= _Ch) && (_base64Chars[25] >= _Ch)) - return _Ch - _base64Chars[0]; - - if((_base64Chars[26] <= _Ch) && (_base64Chars[51] >= _Ch)) - return _Ch - _base64Chars[26] + 26; - - if((_base64Chars[52] <= _Ch) && (_base64Chars[61] >= _Ch)) - return _Ch - _base64Chars[52] + 52; - - if(_Ch == _Tr::to_int_type('=')) - return _EQUAL_CHAR; - - return _UNKNOWN_CHAR; - } - - -}; - - -#endif diff --git a/branches/lydia/xmlrpc.cpp b/branches/lydia/xmlrpc.cpp deleted file mode 100644 index 06cb228..0000000 --- a/branches/lydia/xmlrpc.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/* IvySync - Video SyncStarter - * - * (c) Copyright 2004 - 2006 Denis Rojo - * Nederlands Instituut voor Mediakunst - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include -#include -#include - -static bool quit; - -IvySyncDaemon::IvySyncDaemon(XmlRpcServer *srv) { - - xmlrpc = srv; - xmlrpc->_ssl = false; - xmlrpc->_ssl_ssl = NULL; - - quit = false; - -} - -bool IvySyncDaemon::init(int port) { - - if( ! xmlrpc->bindAndListen(port) ) return false; - - // to be introspective we can list our own methods - // xmlrpc->enableIntrospection(true); - - return true; -} - -void IvySyncDaemon::run(double mstime) { - // running = true; - // unlock(); - - if(::quit) { - quit = true; - return; - } - - // run for amount of milliseconds (-1.0 for infinite) - xmlrpc->work( mstime ); - -} - - -Play::Play(XmlRpcServer* srv, Linklist *decoders) - : XmlRpcServerMethod("Play", srv), - IvySyncPublicMethod(decoders) -{ } - -SyncStart::SyncStart(XmlRpcServer* srv, Linklist *decoders) - : XmlRpcServerMethod("SyncStart", srv), - IvySyncPublicMethod(decoders) -{ } - - -Stop::Stop(XmlRpcServer* srv, Linklist *decoders) - : XmlRpcServerMethod("Stop", srv), - IvySyncPublicMethod(decoders) -{ } - -Pause::Pause(XmlRpcServer* srv, Linklist *decoders) - : XmlRpcServerMethod("Pause", srv), - IvySyncPublicMethod(decoders) -{ } - -GetPos::GetPos(XmlRpcServer* srv, Linklist *decoders) - : XmlRpcServerMethod("GetPos", srv), - IvySyncPublicMethod(decoders) -{ } - -SetPos::SetPos(XmlRpcServer* srv, Linklist *decoders) - : XmlRpcServerMethod("SetPos", srv), - IvySyncPublicMethod(decoders) -{ } - - - -GetOffset::GetOffset(XmlRpcServer* srv, Linklist *decoders) - : XmlRpcServerMethod("GetOffset", srv), - IvySyncPublicMethod(decoders) -{ } - -SetOffset::SetOffset(XmlRpcServer* srv, Linklist *decoders) - : XmlRpcServerMethod("SetOffset", srv), - IvySyncPublicMethod(decoders) -{ } - -SyncOffset::SyncOffset(XmlRpcServer* srv, Linklist *decoders) - : XmlRpcServerMethod("SyncOffset", srv), - IvySyncPublicMethod(decoders) -{ } - -Open::Open(XmlRpcServer* src, Linklist *decoders) - : XmlRpcServerMethod("Open", src), - IvySyncPublicMethod(decoders) -{ } - -Quit::Quit(XmlRpcServer* src, Linklist *decoders) - : XmlRpcServerMethod("Quit", src), - IvySyncPublicMethod(decoders) -{ } - -void Quit::execute(XmlRpcValue ¶ms, XmlRpcValue &result) { - Decoder *dec; - - dec = (Decoder*)decoders->begin(); - while(dec) { - - dec->stop(); - dec->close(); - - dec = (Decoder*)dec->next; - } - - result = 1.0; - - ::quit = true; -} - -void Open::execute(XmlRpcValue ¶ms, XmlRpcValue &result) { - int decnum; - char *path; - - if( params.size() < 2) { - E("XMLRPC: Open called with invalid number of arguments(%u)", - params.size() ); - result = 0.0; - return; - } - - // get out the decoder parameter - decnum = (int) params[0]; - Decoder *dec = (Decoder*) (*decoders)[decnum]; - if(!dec) { - E("video decoder %i not present", decnum); - result = 0.0; return; } - - // get out the path to the file to be opened - path = (char*) (std::string(params[1])).c_str(); - D("XMLRPC: Open decoder %u file %s", decnum, path); - - FILE *fd; - fd = fopen(path, "r"); - if(!fd) { - result = 0.0; - return; - } else fclose(fd); - - dec->stop(); - dec->empty(); - dec->append(path); - result = 1.0; - -} - -void Play::execute(XmlRpcValue ¶ms, XmlRpcValue &result) { - int decnum; - - if( params.size() < 1) { - E("XMLRPC: Play called with invalid number of arguments (%u)", - params.size() ); - result = 0.0; - return; - } - - decnum = (int) params[0]; - Decoder *dec = (Decoder*) (*decoders)[decnum]; - if(!dec) { - E("video decoder %i not present", decnum); - result = 0.0; return; } - - D("XMLRPC: Play decoder %u", decnum ); - result = (double) dec->play(); -} - -void SyncStart::execute(XmlRpcValue ¶ms, XmlRpcValue &result) { - - D("syncstart called"); - - Decoder *dec = (Decoder*) decoders->begin(); - - while(dec) { - dec->stop(); - dec->setup(&syncer, 0); - dec->play(); - dec = (Decoder*) dec->next; - } - - N("synced start in 3 seconds..."); - jsleep(3,0); - - syncer = true; - - result = 1.0; - A("...start!"); -} - -void Stop::execute(XmlRpcValue ¶ms, XmlRpcValue &result) { - int decnum; - - if( params.size() < 1) { - E("XMLRPC: Stop called with invalid number of arguments (%u)", - params.size() ); - result = 0.0; - return; - } - - decnum = (int) params[0]; - Decoder *dec = (Decoder*) (*decoders)[decnum]; - if(!dec) { - E("video decoder %i not present", decnum); - result = 0.0; return; } - - D("XMLRPC: Stop decoder %u", decnum); - result = (double) dec->stop(); -} - -void Pause::execute(XmlRpcValue ¶ms, XmlRpcValue &result) { - int decnum; - - if( params.size() < 1) { - E("XMLRPC: Pause called with invalid number of arguments (%u)", - params.size() ); - result = 0.0; - return; - } - - decnum = (int) params[0]; - Decoder *dec = (Decoder*) (*decoders)[decnum]; - if(!dec) { - E("video decoder %i not present", decnum); - result = 0.0; return; } - - D("XMLRPC: Pause decoder %u", decnum); - result = (double) dec->pause(); -} - - -void GetPos::execute(XmlRpcValue ¶ms, XmlRpcValue &result) { - int decnum; - double pos; - - if( params.size() < 1) { - E("XMLRPC: GetPos called with invalid number of arguments (%u)", - params.size() ); - return; - } - - decnum = (int) params[0]; - Decoder *dec = (Decoder*) (*decoders)[decnum]; - if(!dec) { - E("video decoder %i not present", decnum); - result = 0.0; return; } - - pos = (double) dec->getpos(); - result = pos; - // D("XMLRPC: GetPos decoder %u returns %u", decnum, pos); - -} - -void GetOffset::execute(XmlRpcValue ¶ms, XmlRpcValue &result) { - int decnum; - int pos; - - if( params.size() < 1) { - E("XMLRPC: GetOffset called with invalid number of arguments (%u)", - params.size() ); - return; - } - - decnum = (int) params[0]; - Decoder *dec = (Decoder*) (*decoders)[decnum]; - if(!dec) { - E("video decoder %i not present", decnum); - result = 0.0; return; } - - pos = (int) dec->getoffset(); - result = pos; - D("XMLRPC: GetOffset decoder %u returns %d", decnum, pos); -} - - -void SetPos::execute(XmlRpcValue ¶ms, XmlRpcValue &result) { - int decnum; - int pos; - - if( params.size() < 2) { - E("XMLRPC: SetPos called with invalid number of arguments (%u)", - params.size() ); - return; - } - - decnum = (int) params[0]; - Decoder *dec = (Decoder*) (*decoders)[decnum]; - if(!dec) { - E("video decoder %i not present", decnum); - result = 0.0; return; } - - pos = (int) params[1]; - D("XMLRPC: SetPos decoder %u to position %i", decnum, pos); - dec->setpos( pos ); -} - -void SetOffset::execute(XmlRpcValue ¶ms, XmlRpcValue &result) { - int decnum; - int pos; - - if( params.size() < 2) { - E("XMLRPC: SetOffset called with invalid number of arguments (%u)", - params.size() ); - return; - } - - decnum = (int) params[0]; - Decoder *dec = (Decoder*) (*decoders)[decnum]; - if(!dec) { - E("video decoder %i not present", decnum); - result = 0.0; return; } - - pos = (int) params[1]; - D("XMLRPC: SetOffset decoder %u to position %d", decnum, pos); - dec->setoffset( (off64_t) pos ); -} - -void SyncOffset::execute(XmlRpcValue ¶ms, XmlRpcValue &result) { - D("syncoffset called"); - int offset; - - if( params.size() < 1) { - E("XMLRPC: SyncOffset called without offset argument"); - return; - } - - offset = (int) params[0]; - - Decoder *dec = (Decoder*) decoders->begin(); - - while(dec) { - dec->stop(); - dec->setup(&syncer, 0); - dec->setoffset( offset ); - dec->play(); - dec = (Decoder*) dec->next; - } - - N("global seek to offset %u",offset); - A("synced start in 3 seconds..."); - jsleep(3,0); - - syncer = true; - - result = 1.0; - A("...start!"); -} - diff --git a/branches/lydia/xmlrpc.h b/branches/lydia/xmlrpc.h deleted file mode 100644 index 55f4d7d..0000000 --- a/branches/lydia/xmlrpc.h +++ /dev/null @@ -1,245 +0,0 @@ -/* IvySync - Video SyncStarter - * - * (c) Copyright 2004 - 2006 Denis Rojo - * Nederlands Instituut voor Mediakunst - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU Public License as published - * by the Free Software Foundation; either version 2 of the License, - * or (at your option) any later version. - * - * This source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * Please refer to the GNU Public License for more details. - * - * You should have received a copy of the GNU Public License along with - * this source code; if not, write to: - * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __XMLRPC_H__ -#define __XMLRPC_H__ - - -#include - -#include -#include - -#include -#include - -using namespace XmlRpc; - -// damn STL -//#include -//using namespace std; -//using namespace __gnu_cxx; - - -// METHODS: -class Open; -class Play; -class Stop; -class GetPos; -class SetPos; -class Quit; - - -class IvySyncDaemon { -public: - IvySyncDaemon(XmlRpcServer *srv); - ~IvySyncDaemon() { }; - - bool init(int port); - void run(double mstime); - - bool quit; - -private: - - XmlRpcServer *xmlrpc; - -}; - -class IvySyncPublicMethod { -public: - - IvySyncPublicMethod(Linklist *decs) { - decoders = decs; - } - - ~IvySyncPublicMethod() { }; - - Linklist *decoders; - -}; - -//RPC(Stop,"Stop playing a channel"); -//RPC(PlaylistAppend,"Append a file to a channel's playlist"); - - -class Play : public XmlRpcServerMethod, IvySyncPublicMethod { -public: - - Play(XmlRpcServer* srv, Linklist *decoders); - - ~Play() { }; - - void execute(XmlRpcValue ¶ms, XmlRpcValue &result); - - std::string help() { - return std::string("Start playing the channel"); } - -}; - -class SyncStart : public XmlRpcServerMethod, IvySyncPublicMethod { -public: - - SyncStart(XmlRpcServer* srv, Linklist *decoders); - - ~SyncStart() { }; - - void execute(XmlRpcValue ¶ms, XmlRpcValue &result); - - std::string help() { - return std::string("Start playing all channels in sync"); } - - private: - bool syncer; - -}; - - -class Stop : public XmlRpcServerMethod, IvySyncPublicMethod { -public: - - Stop(XmlRpcServer* srv, Linklist *decoders); - - ~Stop() { }; - - void execute(XmlRpcValue ¶ms, XmlRpcValue &result); - - std::string help() { - return std::string("Stop playing the channel"); } - -}; - -class Pause : public XmlRpcServerMethod, IvySyncPublicMethod { -public: - - Pause(XmlRpcServer* srv, Linklist *decoders); - - ~Pause() { }; - - void execute(XmlRpcValue ¶ms, XmlRpcValue &result); - - std::string help() { - return std::string("Pause the channel"); } - -}; - -class GetPos : public XmlRpcServerMethod, IvySyncPublicMethod { -public: - - GetPos(XmlRpcServer* srv, Linklist *decoders); - - ~GetPos() { }; - - void execute(XmlRpcValue ¶ms, XmlRpcValue &result); - - std::string help() { - return std::string("Return position of channel in percentage"); } - -}; - -class GetOffset : public XmlRpcServerMethod, IvySyncPublicMethod { - public: - - GetOffset(XmlRpcServer* srv, Linklist *decoders); - - ~GetOffset() { }; - - void execute(XmlRpcValue ¶ms, XmlRpcValue &result); - - std::string help() { - return std::string("Return position of channel in byte offset"); } -}; - -class SetPos : public XmlRpcServerMethod, IvySyncPublicMethod { - public: - - SetPos(XmlRpcServer* srv, Linklist *decoders); - - ~SetPos() { }; - - void execute(XmlRpcValue ¶ms, XmlRpcValue &result); - - std::string help() { - return std::string("Skip channel to position in percentage"); } - -}; - - -class SetOffset : public XmlRpcServerMethod, IvySyncPublicMethod { - public: - - SetOffset(XmlRpcServer* srv, Linklist *decoders); - - ~SetOffset() { }; - - void execute(XmlRpcValue ¶ms, XmlRpcValue &result); - - std::string help() { - return std::string("Skip channel to position in byte offset"); } - -}; - -class SyncOffset : public XmlRpcServerMethod, IvySyncPublicMethod { -public: - - SyncOffset(XmlRpcServer* srv, Linklist *decoders); - - ~SyncOffset() { }; - - void execute(XmlRpcValue ¶ms, XmlRpcValue &result); - - std::string help() { - return std::string("Skip all channels to a certain offset and start playing in sync"); } - - private: - bool syncer; - -}; - - -class Open : public XmlRpcServerMethod, IvySyncPublicMethod { - public: - - Open(XmlRpcServer* srv, Linklist *decoders); - - ~Open() { }; - - void execute(XmlRpcValue ¶ms, XmlRpcValue &result); - - std::string help() { - return std::string("Open a new file to be played"); } - -}; - -class Quit : public XmlRpcServerMethod, IvySyncPublicMethod { - public: - - Quit(XmlRpcServer* srv, Linklist *decoders); - - ~Quit() { }; - - void execute(XmlRpcValue ¶ms, XmlRpcValue &result); - - std::string help() { - return std::string("Quit the ivysync from running"); } - -}; - -#endif