From 3f0c36f57af40e853ece2c5889a05120129f649b Mon Sep 17 00:00:00 2001 From: Alexandre Quessy Date: Wed, 19 Jul 2006 00:27:57 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r5374, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/aalex/; revision=5375 --- LICENSE.txt | 340 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.txt | 53 +++++++++ makefile | 48 ++++++++ matches-help.pd | 26 +++++ matches.c | 193 +++++++++++++++++++++++++++++++ pcre-help.pd | 38 +++++++ pcre.c | 172 ++++++++++++++++++++++++++++ x11key-help.pd | 43 +++++++ x11key.c | 162 ++++++++++++++++++++++++++ x11mouse-help.pd | 76 +++++++++++++ x11mouse.c | 181 +++++++++++++++++++++++++++++ xmms-help.pd | 40 +++++++ xmms.c | 148 ++++++++++++++++++++++++ 13 files changed, 1520 insertions(+) create mode 100644 LICENSE.txt create mode 100644 README.txt create mode 100644 makefile create mode 100644 matches-help.pd create mode 100644 matches.c create mode 100644 pcre-help.pd create mode 100644 pcre.c create mode 100644 x11key-help.pd create mode 100644 x11key.c create mode 100644 x11mouse-help.pd create mode 100644 x11mouse.c create mode 100644 xmms-help.pd create mode 100644 xmms.c diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..67282dd --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..df8afc3 --- /dev/null +++ b/README.txt @@ -0,0 +1,53 @@ +ABOUT aalex's + +These are objects for Pure Data. + +[x11mouse] generates a X11 mouse event +[x11key] generates a X11 keyboard event +[xmms] controls the X Multimedia System +[pcre] matches a symbol against a Perl compatible regular expression. Still needs symbol as a selector for arguments. + + +I also include a few of my abstractions : + + +================================================= +INSTALL + +To use on Linux, add the path to this directory into your ~/.pdrc invisible file. +Currenly, the only one to work on Mac is [matches]. All the others are for GNU/Linux. + + +================================================= +COMPILE + +To compile on Debian, execute the follwing command in a terminal. +It could probably work on Mac too, instlaling the packages with Fink. Tell +me if ever you need some of them for Mac, as the makefile will need to be modified. + + +sudo apt-get install xlib-dev xmms-dev +cd aalex +make + + +================================================= +AUTHOR + +Alexandre Quessy +alex@sourcelibre.com + + +================================================= +LICENSE + +GNU Public License +)c( Copyleft 2006 +Enjoy at your own risks ! + + +================================================= +HISTORY + +2006-07-18 Fixed *MD64 compilation flag (thanks to r1). Changed [matches] for [pcre]. +2006-07 Initial release of old externals plus x11 objects. diff --git a/makefile b/makefile new file mode 100644 index 0000000..3a8e66a --- /dev/null +++ b/makefile @@ -0,0 +1,48 @@ +# +# For Debian : +# apt-get install xlib-dev xmms-dev +# + + + +current: pd_linux + @echo make pd_linux, pd_darwin, clean ... you must be specific + @echo default to pd_linux + + +clean: ; rm -f *.pd_linux *.o + +# ----------------------- LINUX i386 ----------------------- + +pd_linux: pcre.pd_linux xmms.pd_linux x11mouse.pd_linux x11key.pd_linux + +.SUFFIXES: .pd_linux + +LINUXCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer \ + -Wall -W -Wshadow -Wstrict-prototypes -Werror \ + -Wno-unused -Wno-parentheses -Wno-switch -fPIC + +LINUXINCLUDE = -I../src -L/usr/lib/X11 -I/usr/include/X11 -L/usr/X11R6/lib +LINUXLINKS = -lX11 -lXtst -lgtk -lgdk -lgmodule -lglib -ldl -lXi -lXext -lX11 -lm -lxmms + +.c.pd_linux: + cc $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c \ + `xmms-config --cflags` + ld -export_dynamic -shared -o $*.pd_linux $*.o -lpcre -lc -lm\ + -L/usr/lib -L/usr/X11R6/lib $(LINUXLINKS) + strip --strip-unneeded $*.pd_linux + rm $*.o +# ----------------------- Mac OSX ----------------------- + +pd_darwin: matches.pd_darwin concat.pd_darwin + +.SUFFIXES: .pd_darwin + +DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \ + -Wno-unused -Wno-parentheses -Wno-switch + +.c.pd_darwin: + cc $(DARWINCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c -lpcre + cc -bundle -undefined suppress -flat_namespace -o $*.pd_darwin $*.o + rm -f $*.o + diff --git a/matches-help.pd b/matches-help.pd new file mode 100644 index 0000000..1485071 --- /dev/null +++ b/matches-help.pd @@ -0,0 +1,26 @@ +#N canvas 0 0 786 271 10; +#X obj 239 110 symbol; +#X obj 205 202 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 205 180 matches b9; +#X obj 118 200 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 118 179 matches #9; +#X msg 199 36 F#9; +#X msg 231 35 D7b9; +#X text 395 60 Matches a symbol against a Perl-compatible regular expression. +See man pcre.; +#X text 399 30 matches; +#X obj 293 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 293 183 matches !9; +#X msg 273 34 Am7; +#X connect 0 0 2 0; +#X connect 0 0 4 0; +#X connect 0 0 10 0; +#X connect 2 0 1 0; +#X connect 4 0 3 0; +#X connect 5 0 0 0; +#X connect 6 0 0 0; +#X connect 10 0 9 0; +#X connect 11 0 0 0; diff --git a/matches.c b/matches.c new file mode 100644 index 0000000..13c3b1d --- /dev/null +++ b/matches.c @@ -0,0 +1,193 @@ +/** + * The [matches] class in Pure Data is an external to verify that a subject + * matches a Perl-compatible regular expression mask. + * + * http://alexandre.quessy.net + * + * @author Alexandre Quessy + * @c GNU General Public License 2006 + */ + +#include "m_pd.h" +#include +#include +#include + +#define CAPTUREVECTORSIZE 30 /* multiple of 3 */ +#define MATCHES_ERROR_PREFIX "[matches]: " +#define MATCHES_FALSE_MASK "xxxxxxxxxxxxxxxxxxxxxx" +#define MATCHES_DECIMAL_PRECISION_SIZE_T 4 + +/** variables of the pd object */ +typedef struct matches { + t_object x_ob; /* contient inlets et outlets */ + t_outlet *x_outlet; + pcre *regex; /* mask */ +} t_matches; + +/** functions */ +char *_str_replace(const char search, const char replace, const char *subject); +int _isMatching(t_matches *x, char *text); +void _compile_pattern(t_matches *x, const char *pattern); + + +/** left inlet: subject */ +void matches_symbol0(t_matches *x, t_symbol *arg) { + int isOk =_isMatching(x, arg->s_name); + outlet_float(x->x_outlet, isOk); +} + +/* left inlet: subject (when a float) +void matches_float0(t_matches *x, t_floatarg arg) { + char *str_float = sprintf("%f0", arg); + int isOk =_isMatching(x, str_float); + outlet_float(x->x_outlet, isOk); +} +*/ + + +/** right inlet : mask */ +void matches_symbol1(t_matches *x, t_symbol *arg) { + _compile_pattern(x, arg->s_name); +} + +/* right inlet +void matches_float1(t_matches *x, t_floatarg arg) { + char *str_float = sprintf("%f0", arg); + _compile_pattern(x, str_float); +} +*/ +t_class *matches_class; + +/** constructor */ +void *matches_new(t_symbol *selector, int argc, t_atom *argv) { + int is_valid = 0; + t_matches *x = (t_matches *) pd_new(matches_class); + + /* set the mask */ + if (argc < 1) { + post("%s No mask given as argument. Please supply one as message.\n", MATCHES_ERROR_PREFIX); + } else { + /* if (argv[0].a_type == A_SYMBOL) { */ + t_symbol *tmp = atom_getsymbol(&argv[0]); + _compile_pattern(x, tmp->s_name); + is_valid = 1; + /* + } else { + post("%s Argument should be a symbol\n", MATCHES_ERROR_PREFIX); + } + */ + } + if (is_valid == 0) { + _compile_pattern(x, MATCHES_FALSE_MASK); + } + /* add inlets */ + inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("symbol"), gensym("mask")); /* selecteur, renomme mask */ + + /* add outlet */ + x->x_outlet = outlet_new(&x->x_ob, gensym("float")); + return (void *)x; +} + +/** setup */ +void matches_setup(void) { + matches_class = class_new(gensym("matches"), (t_newmethod) matches_new, 0, sizeof(t_matches), 0, A_GIMME, 0); + class_addmethod(matches_class, (t_method) matches_symbol0, gensym("symbol"), A_SYMBOL, 0); + class_addmethod(matches_class, (t_method) matches_symbol1, gensym("mask"), A_SYMBOL, 0); + /* + class_addmethod(matches_class, (t_method) matches_float0, gensym("float"), A_FLOAT, 0); + class_addmethod(matches_class, (t_method) matches_float1, gensym("float"), A_FLOAT, 0); + */ +} + + + +/* + +matju aalex: pour les inlets acceptant plusieurs sélecteurs, check gridflow/bridge/puredata.c +matju aalex: ça fait: inlet_new(self->bself, &p->ob_pd, 0,0); +matju aalex: avec un proxy inlet +aalex ???? MiS : http://www.tigerdirect.ca/applications/SearchTools/item-details.asp?EdpNo=1068181&CatId=107 +aalex ah +aalex matju : il me faut absolument un proxy-inlet, donc +matju aalex: dans cet exemple, self->bself est d'un soustype de t_object* et &p->ob_pd est un t_pd* +matju aalex: je crois que oui +matju aalex: &p->ob_pd est en fait la même chose que (t_pd *)p, si je ne m'abuse + +*/ + + + +/* ############################### functions ###################### */ + + + + +/** clone of the PHP function */ +char *_str_replace(const char search, const char replace, const char *subject) { + int i, len; + char *result = strdup(subject); + len = strlen(result); + for (i = 0; i <= len; i++) { + if(result[i] == search) { + result[i] = replace; + } + } + return result; +} + +/** + * returns 1 if matches, 0 if not + * TODO use stdbool.h, I think + */ +int _isMatching(t_matches *x, char *text) { /* 2nd is const */ + int capturevector[CAPTUREVECTORSIZE]; + int rc; + int i; + int result = 0; + + rc = pcre_exec(x->regex, NULL, text, (int) strlen(text), 0, 0, capturevector, CAPTUREVECTORSIZE); + + if (rc < 0) { + result = 0; + } else { + result = 1; + } + + /* ok, a partir d'ici c'est different de l'autre exemple, sauf qu'on avait mis des parentheses dans le pattern */ + if (rc == 0) { + rc = CAPTUREVECTORSIZE / 3; + post("ovector only has room for %d captured substrings\n", rc - 1); + } + for (i = 0; i < rc; i++) { + char *substring_start = text + capturevector[2 * i]; /* ovector */ + int substring_length = capturevector[2 * i + 1] - capturevector[2 * i]; + post("%2d matching: %.*s", i, substring_length, substring_start); + } + /* I think that from here I should clean up my memory */ + + return result; +} + +/* ############## begin class matches ####################### */ + +/** + * private method to set and compile the mask + * TODO : use pcre_malloc() and pcre_free() + */ +void _compile_pattern(t_matches *x, const char *pattern) { + pcre *regex; + const char *regex_error; + int erroroffset; + char *mask = _str_replace('`', '\\', pattern); + + regex = pcre_compile(mask, 0, ®ex_error, &erroroffset, NULL); + if (regex == NULL) { + post("%s Compilation failed at offset %d : %s", MATCHES_ERROR_PREFIX, erroroffset, regex_error); + regex = pcre_compile(MATCHES_FALSE_MASK, 0, ®ex_error, &erroroffset, NULL); /* will always return false if invalid pattern */ + } else { + post("%s New PCRE mask: %s", MATCHES_ERROR_PREFIX, mask); + } + /* free(x->regex); */ + x->regex = regex; +} diff --git a/pcre-help.pd b/pcre-help.pd new file mode 100644 index 0000000..4a65e0f --- /dev/null +++ b/pcre-help.pd @@ -0,0 +1,38 @@ +#N canvas 4 301 765 489 10; +#X obj 136 -59 cnv 15 200 140 empty empty empty 20 12 0 14 -258699 +-66577 0; +#X obj 129 161 cnv 15 300 140 empty empty empty 20 12 0 14 -258699 +-66577 0; +#X obj 176 107 symbol; +#X obj 239 259 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 152 257 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 +1; +#X msg 148 -23 F#9; +#X msg 214 -23 D7b9; +#X text 395 60 Matches a symbol against a Perl-compatible regular expression. +See man pcre.; +#X obj 327 262 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X msg 265 -10 Am7; +#X obj 152 236 pcre #9; +#X obj 239 237 pcre b9; +#X obj 327 240 pcre !9; +#X text 399 30 pcre; +#X text 166 -53 patterns; +#X text 140 170 masks; +#X msg 298 127 foo; +#X msg 86 11 foo; +#X obj 317 162 symbol; +#X connect 2 0 10 0; +#X connect 2 0 11 0; +#X connect 2 0 12 0; +#X connect 5 0 2 0; +#X connect 6 0 2 0; +#X connect 9 0 2 0; +#X connect 10 0 4 0; +#X connect 11 0 3 0; +#X connect 12 0 8 0; +#X connect 16 0 18 0; +#X connect 17 0 2 0; +#X connect 18 0 10 1; diff --git a/pcre.c b/pcre.c new file mode 100644 index 0000000..7477938 --- /dev/null +++ b/pcre.c @@ -0,0 +1,172 @@ +/** + * The [pcre] class in Pure Data is an external to verify that a subject + * matches a Perl-compatible regular expression mask. + * + * http://alexandre.quessy.net + * + * @author Alexandre Quessy + * @c GNU General Public License 2006 + */ + +#include "m_pd.h" +#include +#include +#include + +#define CAPTUREVECTORSIZE 30 /* multiple of 3 */ +#define pdpcre_ERROR_PREFIX "[pdpcre]: " +#define pdpcre_FALSE_MASK "xxxxxxxxxxxxxxxxxxxxxx" +#define pdpcre_DECIMAL_PRECISION_SIZE_T 4 + +/** variables of the pd object */ +typedef struct pdpcre { + t_object x_ob; /* contient inlets et outlets */ + t_outlet *x_outlet; + pcre *regex; /* mask */ +} t_pdpcre; + +/** functions */ +char *_str_replace(const char search, const char replace, const char *subject); +int _isMatching(t_pdpcre *x, char *text); +void _compile_pattern(t_pdpcre *x, const char *pattern); + + +/** left inlet: subject */ +void pdpcre_symbol0(t_pdpcre *x, t_symbol *arg) { + int isOk =_isMatching(x, arg->s_name); + outlet_float(x->x_outlet, isOk); +} + +/* left inlet: subject (when a float) +void pdpcre_float0(t_pdpcre *x, t_floatarg arg) { + char *str_float = sprintf("%f0", arg); + int isOk =_isMatching(x, str_float); + outlet_float(x->x_outlet, isOk); +} +*/ + + +/** right inlet : mask */ +void pdpcre_symbol1(t_pdpcre *x, t_symbol *arg) { + _compile_pattern(x, arg->s_name); +} + +/* right inlet +void pdpcre_float1(t_pdpcre *x, t_floatarg arg) { + char *str_float = sprintf("%f0", arg); + _compile_pattern(x, str_float); +} +*/ +t_class *pdpcre_class; + +/** constructor */ +void *pdpcre_new(t_symbol *selector, int argc, t_atom *argv) { + int is_valid = 0; + t_pdpcre *x = (t_pdpcre *) pd_new(pdpcre_class); + + /* set the mask */ + if (argc < 1) { + post("%s No mask given as argument. Please supply one as message.\n", pdpcre_ERROR_PREFIX); + } else { + if (argv[0].a_type == A_SYMBOL) { + t_symbol *tmp = atom_getsymbol(&argv[0]); + _compile_pattern(x, tmp->s_name); + is_valid = 1; + } else { + post("%s Argument should be a symbol\n", pdpcre_ERROR_PREFIX); + } + } + if (is_valid == 0) { + _compile_pattern(x, pdpcre_FALSE_MASK); + } + /* add inlets */ + inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("symbol"), gensym("mask")); /* selecteur, renomme mask */ + + /* add outlet */ + x->x_outlet = outlet_new(&x->x_ob, gensym("float")); + return (void *)x; +} + +/** setup */ +void pcre_setup(void) { + pdpcre_class = class_new(gensym("pcre"), (t_newmethod) pdpcre_new, 0, sizeof(t_pdpcre), 0, A_GIMME, 0); + class_addmethod(pdpcre_class, (t_method) pdpcre_symbol0, gensym("symbol"), A_SYMBOL, 0); + class_addmethod(pdpcre_class, (t_method) pdpcre_symbol1, gensym("mask"), A_SYMBOL, 0); +} + + + + +/* ############################### functions ###################### */ + + + + +/** clone of the PHP function */ +char *_str_replace(const char search, const char replace, const char *subject) { + int i, len; + char *result = strdup(subject); + len = strlen(result); + for (i = 0; i <= len; i++) { + if(result[i] == search) { + result[i] = replace; + } + } + return result; +} + +/** + * returns 1 if pdpcre, 0 if not + * TODO use stdbool.h, I think + */ +int _isMatching(t_pdpcre *x, char *text) { /* 2nd is const */ + int capturevector[CAPTUREVECTORSIZE]; + int rc; + int i; + int result = 0; + + rc = pcre_exec(x->regex, NULL, text, (int) strlen(text), 0, 0, capturevector, CAPTUREVECTORSIZE); + + if (rc < 0) { + result = 0; + } else { + result = 1; + } + + /* ok, a partir d'ici c'est different de l'autre exemple, sauf qu'on avait mis des parentheses dans le pattern */ + if (rc == 0) { + rc = CAPTUREVECTORSIZE / 3; + post("ovector only has room for %d captured substrings\n", rc - 1); + } + for (i = 0; i < rc; i++) { + char *substring_start = text + capturevector[2 * i]; /* ovector */ + int substring_length = capturevector[2 * i + 1] - capturevector[2 * i]; + //post("%2d matching: %.*s", i, substring_length, substring_start); + } + /* I think that from here I should clean up my memory */ + + return result; +} + +/* ############## begin class pdpcre ####################### */ + +/** + * private method to set and compile the mask + * TODO : use pcre_malloc() and pcre_free() + */ +void _compile_pattern(t_pdpcre *x, const char *pattern) { + pcre *regex; + const char *regex_error; + int erroroffset; + char *mask = _str_replace('`', '\\', pattern); + + regex = pcre_compile(mask, 0, ®ex_error, &erroroffset, NULL); + if (regex == NULL) { + post("%s Compilation failed at offset %d : %s", pdpcre_ERROR_PREFIX, erroroffset, regex_error); + regex = pcre_compile(pdpcre_FALSE_MASK, 0, ®ex_error, &erroroffset, NULL); /* will always return false if invalid pattern */ + } else { + post("%s New PCRE mask: %s", pdpcre_ERROR_PREFIX, mask); + } + /* free(x->regex); */ + x->regex = regex; +} diff --git a/x11key-help.pd b/x11key-help.pd new file mode 100644 index 0000000..616c91b --- /dev/null +++ b/x11key-help.pd @@ -0,0 +1,43 @@ +#N canvas 466 121 703 480 10; +#X obj 89 21 cnv 15 150 140 empty empty empty 20 12 0 14 -258699 -66577 +0; +#X obj 334 26 cnv 15 200 140 empty empty empty 20 12 0 14 -258699 -66577 +0; +#X obj 230 191 cnv 15 420 230 empty empty x11key_object 20 12 0 14 -258699 +-66577 0; +#X obj 166 365 x11key; +#X msg 22 61 help; +#X msg 104 106 letter a; +#X msg 103 40 bang; +#X msg 348 50 bang; +#X msg 29 305 display :0.0; +#X obj 347 114 delay 1000; +#X obj 105 84 delay 1000; +#X obj 446 116 delay 2000; +#X msg 344 139 keysym A 1; +#X msg 448 136 keysym A 0; +#X obj 349 92 t b b; +#X text 341 34 2 triggers on and of a key; +#X text 109 25 1 types a key; +#X text 25 273 Not yet implemented; +#X text 243 231 [x11key] simulates X11 keyboard events.; +#X text 240 262 Try examples 1 and 2 They generate keys as if you typed +it on your keyboard. Give the focus to an other application than PD +\, in order to see that you really fake letters typing.; +#X text 240 322 Comments are welcome. The API (the messages for every +is likely to change.; +#X text 242 384 )c( Copyleft 2006 Alexandre Quessy; +#X text 245 399 Released under the GNU Public License; +#X text 245 368 pureX11; +#X connect 4 0 3 0; +#X connect 5 0 3 0; +#X connect 6 0 10 0; +#X connect 7 0 14 0; +#X connect 8 0 3 0; +#X connect 9 0 12 0; +#X connect 10 0 5 0; +#X connect 11 0 13 0; +#X connect 12 0 3 0; +#X connect 13 0 3 0; +#X connect 14 0 9 0; +#X connect 14 1 11 0; diff --git a/x11key.c b/x11key.c new file mode 100644 index 0000000..2134019 --- /dev/null +++ b/x11key.c @@ -0,0 +1,162 @@ +/** + * [x11kry] Generates X11 keyboard events on Linux + * @author Alexandre Quessy + * @license GNU Public License )c( 2006 + */ + +#include +#include +#include +#include +// #include +#include +#include +#include "m_pd.h" + +#define PUREX11_DEFAULT_KEYSTATE 0 +#define PUREX11_DEFAULT_DISPLAY 0 + +/** variables of the pd object */ +typedef struct x11key { + t_object x_ob; /* The instance. Contains inlets and outlets */ + int *displayName; +} t_x11key; + +/** + * letter : types the letter you give it. + */ +void x11key_letter(t_x11key *x, t_symbol *s, int argc, t_atom *argv) { + Display *display; + KeySym keysym; + KeyCode keycode; + int result; + + if (argc == 1) { + if (argv[0].a_type == A_SYMBOL) { + t_symbol *sym = atom_getsymbolarg(0, argc, argv); + char *theChars = sym->s_name; + //keysym = XK_q; + keysym = XStringToKeysym(theChars); + /* should be hostname:number.screen_number */ + display = XOpenDisplay(NULL); /* defaults to $DISPLAY */ + if (display == NULL) { + post("Error : could not open display.\n"); + }else { + // printf("Display opened successfully.\n"); + keycode = XKeysymToKeycode(display, keysym); + //post("letter = %s", theChars); + //post("keycode = %d", (int) keycode); + /** Pushes on and off the letter */ + result = XTestFakeKeyEvent(display, keycode, True, 0); + //post("result = %d", result); + if (result == 0) { + post("Error : could not simulate typing the letter."); + } + result = XTestFakeKeyEvent(display, keycode, False, 0); + if (result == 0) { + post("Error : could not simulate typing the letter."); + } + XCloseDisplay(display); + } + } else { + post("Error : Bad argument type. Must be a symbol. Try [symbol 7< if you want to type a number."); + } + } else { + post("Error : Missing argument. The letter to type."); + } +} + + + +/** + * key : types the key symbol you give it. See /usr/include/X11/keysymdef.h + */ +void x11key_keysym(t_x11key *x, t_symbol *s, int argc, t_atom *argv) { + Display *display; + KeySym keysym; + KeyCode keycode; + int result; + int state = PUREX11_DEFAULT_KEYSTATE; + bool boolState; + + if (argc >= 2) { + if (argv[1].a_type == A_FLOAT) { + state = (int) atom_getfloatarg(1, argc, argv); + } + } + + if (argc >= 1) { + if (argv[0].a_type == A_SYMBOL) { + t_symbol *sym = atom_getsymbolarg(0, argc, argv); + char *theChars = sym->s_name; + //keysym = XK_q; + keysym = XStringToKeysym(theChars); + /* should be hostname:number.screen_number */ + display = XOpenDisplay(NULL); /* defaults to $DISPLAY */ + if (display == NULL) { + post("Error : could not open display.\n"); + }else { + // printf("Display opened successfully.\n"); + keycode = XKeysymToKeycode(display, keysym); + + /** Pushes on and off the letter */ + boolState = (state == 0) ? False : True; + result = XTestFakeKeyEvent(display, keycode, boolState, 0); + if (result == 0) { + post("Error : could not simulate typing the letter."); + } + XCloseDisplay(display); + } + } else { + post("Error : Bad argument type. Must be a symbol. "); + } + } else { + post("Error : Missing argument. The letter to type."); + } +} + + + +/** display */ +void x11key_display(t_x11key *x, t_symbol *s, int argc, t_atom *argv) { + post("Not yet implemented."); +} + +/** help */ +void x11key_help(t_x11key *x, t_symbol *s, int argc, t_atom *argv) { + post("keysym [see /usr/include/X11/keysymdef.h for the key symbols]"); + post("letter [letter a-zA-Z0-9...]"); + post("help"); + post("display : not yet implemented"); +} + + + + + +/** The class */ +t_class *x11key_class; + +/** constructor */ +void *x11key_new(t_symbol *selector, int argc, t_atom *argv) { + t_x11key *x = (t_x11key *) pd_new(x11key_class); + //x->displayName = PUREX11_DEFAULT_DISPLAY; + return (void *)x; +} + +/** setup */ +void x11key_setup(void) { + x11key_class = class_new(gensym("x11key"), (t_newmethod) x11key_new, 0, sizeof(t_x11key), 0, A_GIMME, 0); + class_addmethod(x11key_class, (t_method)x11key_letter, gensym("letter"), A_GIMME, 0); + class_addmethod(x11key_class, (t_method)x11key_keysym, gensym("keysym"), A_GIMME, 0); + class_addmethod(x11key_class, (t_method)x11key_display, gensym("display"), A_GIMME, 0); + class_addmethod(x11key_class, (t_method)x11key_help, gensym("help"), A_GIMME, 0); + + post("=============================================="); + post(" Pure X11"); + post("Copyleft 2006 Alexandre Quessy"); + post("GNU Public License"); + post("[x11key] simulates X11 keyboard events."); + post("=============================================="); + +} diff --git a/x11mouse-help.pd b/x11mouse-help.pd new file mode 100644 index 0000000..4555b04 --- /dev/null +++ b/x11mouse-help.pd @@ -0,0 +1,76 @@ +#N canvas 63 104 997 560 10; +#X obj 13 10 cnv 15 150 140 empty empty empty 20 12 0 14 -258699 -66577 +0; +#X obj 385 63 cnv 15 100 100 empty empty empty 20 12 0 14 -258699 -66577 +0; +#X obj 521 275 cnv 15 420 230 empty empty x11mouse_object 20 12 0 14 +-258699 -66577 0; +#X obj 189 152 cnv 15 150 140 empty empty empty 20 12 0 14 -258699 +-66577 0; +#X obj 569 70 cnv 15 100 100 empty empty empty 20 12 0 14 -258699 -66577 +0; +#X obj 760 23 cnv 15 200 200 empty empty empty 20 12 0 14 -258699 -66577 +0; +#X obj 271 468 x11mouse; +#X msg 32 107 click; +#X msg 199 261 press 1 1; +#X msg 49 339 help; +#X obj 848 95 f 0; +#X obj 889 95 + 1; +#X msg 927 58 0; +#X obj 802 41 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 +; +#X msg 810 186 move \$1 \$1; +#X obj 848 125 > 50; +#X obj 32 85 delay 500; +#X msg 32 30 bang; +#X obj 90 158 print; +#X obj 199 240 delay 500; +#X msg 196 189 bang; +#X obj 587 116 delay 500; +#X msg 587 76 bang; +#X msg 587 137 press 3 1; +#X msg 392 124 move 400 200; +#X floatatom 763 186 5 0 0 0 - - -; +#X obj 847 146 sel 1; +#X obj 848 65 metro 50; +#X obj 813 123 * 4; +#X text 542 395 Comments are welcome. The API (the messages for every +is likely to change.; +#X text 544 457 )c( Copyleft 2006 Alexandre Quessy; +#X text 547 472 Released under the GNU Public License; +#X text 547 441 pureX11; +#X text 16 -10 1 Click and keep your mouse over the message; +#X text 197 164 2 Click and keep your mouse over the message; +#X text 388 48 3 Moves the mouse; +#X text 766 7 5 Moves the mouse around; +#X text 548 306 [x11mouse] simulates X11 mouse events.; +#X text 564 51 4 Right-clicks (button 3); +#X text 545 337 Try all examples.; +#X text 221 297 press 1 on; +#X text 218 320 press 1 off; +#X connect 7 0 6 0; +#X connect 7 0 18 0; +#X connect 8 0 6 0; +#X connect 9 0 6 0; +#X connect 10 0 11 0; +#X connect 10 0 15 0; +#X connect 10 0 28 0; +#X connect 11 0 10 1; +#X connect 12 0 10 1; +#X connect 12 0 27 0; +#X connect 13 0 27 0; +#X connect 14 0 6 0; +#X connect 15 0 26 0; +#X connect 16 0 7 0; +#X connect 17 0 16 0; +#X connect 19 0 8 0; +#X connect 20 0 19 0; +#X connect 21 0 23 0; +#X connect 22 0 21 0; +#X connect 23 0 6 0; +#X connect 24 0 6 0; +#X connect 26 0 12 0; +#X connect 27 0 10 0; +#X connect 28 0 14 0; +#X connect 28 0 25 0; diff --git a/x11mouse.c b/x11mouse.c new file mode 100644 index 0000000..b13ace0 --- /dev/null +++ b/x11mouse.c @@ -0,0 +1,181 @@ +/** + * [x11mouse] Generates X11 mouse events on Linux + * @author Alexandre Quessy + * @license GNU Public License )c( 2006 + */ + +#include +#include +#include +#include +#include +#include +#include "m_pd.h" + +#define PUREX11_DEFAULT_MOUSEBUTTON 1 +#define PUREX11_DEFAULT_MOUSESTATE 0 +#define PUREX11_DEFAULT_DISPLAY 0 +#define PUREX11_DEFAULT_XVALUE 0 +#define PUREX11_DEFAULT_YVALUE 0 + + +/** variables of the pd object */ +typedef struct x11mouse { + t_object x_ob; /* The instance. Contains inlets and outlets */ + int *displayName; +} t_x11mouse; + + + +/** + * Mouse click + * @param int Button number + */ +void x11mouse_click(t_x11mouse *x, t_symbol *s, int argc, t_atom *argv) { + Display *display; + int result; + + int button = PUREX11_DEFAULT_MOUSEBUTTON; + + display = XOpenDisplay(0); /* defaults to $DISPLAY if 0 */ + if (display == NULL) { + post("[x11mouse] error : could not open display."); + } + if (argc >= 1) { + if (argv[0].a_type == A_FLOAT) { + button = (int) atom_getfloatarg(0, argc, argv); + } + } + + result = XTestFakeButtonEvent(display, button, True, CurrentTime); + result = XTestFakeButtonEvent(display, button, False, CurrentTime); + XCloseDisplay(display); +} + +/** + * Mouse button press or release + * @param int State. Defaults to 0. + * @param int Button number + */ +void x11mouse_press(t_x11mouse *x, t_symbol *s, int argc, t_atom *argv) { + Display *display; + int result; + + int button = PUREX11_DEFAULT_MOUSEBUTTON; + int state = PUREX11_DEFAULT_MOUSESTATE; + bool boolState; + + display = XOpenDisplay(0); /* defaults to $DISPLAY if 0 */ + if (display == NULL) { + post("[x11mouse] error : could not open display."); + } + + if (argc >= 2) { + if (argv[1].a_type == A_FLOAT) { + button = (int) atom_getfloatarg(1, argc, argv); + } + if (argv[0].a_type == A_FLOAT) { + state = (int) atom_getfloatarg(0, argc, argv); + } + } else if (argc >= 1) { + if (argv[0].a_type == A_FLOAT) { + state = (int) atom_getfloatarg(0, argc, argv); + } + } + + boolState = (state == 0) ? False : True; + result = XTestFakeButtonEvent(display, button, boolState, CurrentTime); + if (!result) { + post("[x11mouse] error : could not fake button event."); + } + XCloseDisplay(display); +} + +/** + * Moves the mouse to the coordonates you give it. + */ +void x11mouse_move(t_x11mouse *x, t_symbol *s, int argc, t_atom *argv) { + Display *display; + int result; + int xCoord = PUREX11_DEFAULT_XVALUE; + int yCoord = PUREX11_DEFAULT_YVALUE; + + display = XOpenDisplay(0); /* defaults to $DISPLAY if 0 */ + if (display == NULL) { + post("[x11mouse] error : could not open display."); + } + + if (argc >= 2) { + if (argv[1].a_type == A_FLOAT) { + yCoord = (int) atom_getfloatarg(0, argc, argv); + } + if (argv[0].a_type == A_FLOAT) { + xCoord = (int) atom_getfloatarg(0, argc, argv); + } + } else if (argc >= 1) { + if (argv[0].a_type == A_FLOAT) { + xCoord = (int) atom_getfloatarg(0, argc, argv); + } + } + + result = XTestFakeMotionEvent(display, 0, xCoord, yCoord, CurrentTime); + if (!result) { + post("[x11mouse] error : could not fake motion event."); + } + XCloseDisplay(display); +} + +/** + * Sets the X11 display name. + * Defaults to $DISPLAY, usually :0.0 + * + * Not currently implemented. You cannot change the display. (for now) + * @todo Allow the user to change the display + */ +void x11mouse_display(t_x11mouse *x, t_symbol *s, int argc, t_atom *argv) { + Display *display; + display = XOpenDisplay(0); /* defaults to $DISPLAY if 0 */ + if (display == NULL) { + post("[x11mouse] error : could not open display."); + } + XCloseDisplay(display); +} + +void x11mouse_help(t_x11mouse *x, t_symbol *s, int argc, t_atom *argv) { + post("press [state 0/1] [button number 1-3]"); + post("move [x] [y]"); + post("click [button number 1-3]"); + post("help"); + post("display not yet implemented"); + + + +} + +/** The class */ +t_class *x11mouse_class; + +/** constructor */ +void *x11mouse_new(t_symbol *selector, int argc, t_atom *argv) { + t_x11mouse *x = (t_x11mouse *) pd_new(x11mouse_class); + //x->displayName = PUREX11_DEFAULT_DISPLAY; + return (void *)x; +} + +/** setup */ +void x11mouse_setup(void) { + x11mouse_class = class_new(gensym("x11mouse"), (t_newmethod) x11mouse_new, 0, sizeof(t_x11mouse), 0, A_GIMME, 0); + class_addmethod(x11mouse_class, (t_method)x11mouse_press, gensym("press"), A_GIMME, 0); + class_addmethod(x11mouse_class, (t_method)x11mouse_move, gensym("move"), A_GIMME, 0); + class_addmethod(x11mouse_class, (t_method)x11mouse_display, gensym("display"), A_GIMME, 0); + class_addmethod(x11mouse_class, (t_method)x11mouse_click, gensym("click"), A_GIMME, 0); + class_addmethod(x11mouse_class, (t_method)x11mouse_help, gensym("help"), A_GIMME, 0); + + post("=============================================="); + post(" Pure X11"); + post("Copyleft 2006 Alexandre Quessy"); + post("GNU Public License"); + post("[x11mouse] simulates X11 mouse events."); + post("=============================================="); + +} diff --git a/xmms-help.pd b/xmms-help.pd new file mode 100644 index 0000000..4ea2c27 --- /dev/null +++ b/xmms-help.pd @@ -0,0 +1,40 @@ +#N canvas 603 220 447 336 10; +#X obj 14 113 cnv 15 50 50 empty empty empty 20 12 0 14 -258699 -66577 +0; +#X obj 79 112 cnv 15 50 50 empty empty empty 20 12 0 14 -24198 -66577 +0; +#X obj 158 105 cnv 15 50 50 empty empty empty 20 12 0 14 -258699 -66577 +0; +#X obj 259 104 cnv 15 50 50 empty empty empty 20 12 0 14 -24198 -66577 +0; +#X obj 208 105 cnv 15 50 50 empty empty empty 20 12 0 14 -241291 -66577 +0; +#X obj 60 274 xmms; +#X msg 79 112 next; +#X msg 15 113 prev; +#X msg 265 122 play; +#X msg 165 121 stop; +#X msg 213 122 pause; +#X obj 56 11 keyname; +#X obj 99 35 select h j k l; +#X msg 317 232 volume \$1; +#X obj 318 172 vsl 15 50 0 100 0 0 empty empty empty 0 -8 0 8 -62784 +-1 -1 0 1; +#X msg 213 206 forward 4000; +#X msg 214 183 backward 4000; +#X msg 210 229 backward; +#X connect 6 0 5 0; +#X connect 7 0 5 0; +#X connect 8 0 5 0; +#X connect 9 0 5 0; +#X connect 10 0 5 0; +#X connect 11 1 12 0; +#X connect 12 0 16 0; +#X connect 12 1 10 0; +#X connect 12 2 8 0; +#X connect 12 3 15 0; +#X connect 13 0 5 0; +#X connect 14 0 13 0; +#X connect 15 0 5 0; +#X connect 16 0 5 0; +#X connect 17 0 5 0; diff --git a/xmms.c b/xmms.c new file mode 100644 index 0000000..ef17659 --- /dev/null +++ b/xmms.c @@ -0,0 +1,148 @@ +/** + * [xmms] is a Pure Data object to control the X Multimedia System, an audio player. + * + * @url http://alexandre.quessy.net/ + * @author Alexandre Quessy + * @license GNU General Public License 2006 + * thanks to Andy Gimblett for code examples + */ +/* +To know which flags to use for compilation: +`xmms-config --cflags --libs` + +On Debian, you need libxmms and xmms-festalon if you want to read nsf files. +*/ + +//#define _GNU_SOURCE + +/* PD includes */ +#include "m_pd.h" +#include +// #include +#include +// #include + +/* XMMS includes */ +#include +// #include +/* local constants */ +#define PDXMMS_DEFAULTSKIP 5000 + + +//need following declarations so internal XMMS functions can be called +//(ripped from XMMS source) +//from xmms.c +//gboolean playlist_load(gchar * inpipefile); + + +/** variables of the pd object */ +typedef struct xmms { + t_object x_ob; /* The instance. Contains inlets and outlets */ + /* xmms session. 0 is the first one when we start it */ + int session; + //t_outlet *x_outlet; +} t_xmms; + + + +void xmms_prev(t_xmms *x, t_symbol *s, int argc, t_atom *argv) { + xmms_remote_playlist_prev(x->session); +} + +void xmms_next(t_xmms *x, t_symbol *s, int argc, t_atom *argv) { + xmms_remote_playlist_next(x->session); +} + +void xmms_play(t_xmms *x, t_symbol *s, int argc, t_atom *argv) { + xmms_remote_play(x->session); +} + +void xmms_pause(t_xmms *x, t_symbol *s, int argc, t_atom *argv) { + xmms_remote_pause(x->session); +} + +void xmms_stop(t_xmms *x, t_symbol *s, int argc, t_atom *argv) { + xmms_remote_stop(x->session); +} + +void xmms_volume(t_xmms *x, t_symbol *s, int argc, t_atom *argv) { + float f; + int l, r; + if (argc >= 1) { + if (argv[0].a_type == A_FLOAT) { + f = (float) atom_getfloatarg(0, argc, argv); + l = (int) f; + //if (mute_flag) mute_flag = 0; + if (l > 100) l = 100; + else if (l < 0) l = 0; + //if (r > 100) r = 100; + //else if (r < 0) r = 0; + r = f; + xmms_remote_set_volume(x->session, l, r); + } + } +} + + +/* skipf and skipb */ +void xmms_forward(t_xmms *x, t_symbol *s, int argc, t_atom *argv) { + int time = xmms_remote_get_output_time(x->session); + double skip = PDXMMS_DEFAULTSKIP; + + if (argc >= 1) { + if (argv[0].a_type == A_FLOAT) { + skip = (double) atom_getfloatarg(0, argc, argv); + } + } + xmms_remote_jump_to_time(x->session, (int) rint(time + skip)); +} + +void xmms_backward(t_xmms *x, t_symbol *s, int argc, t_atom *argv) { + int time = xmms_remote_get_output_time(x->session); + double skip = PDXMMS_DEFAULTSKIP; + + if (argc >= 1) { + if (argv[0].a_type == A_FLOAT) { + skip = (double) atom_getfloatarg(0, argc, argv); + } + } + xmms_remote_jump_to_time(x->session, (int) rint(time - skip)); +} + +/* +void xmms_load0(t_xmms *x, t_symbol *s, int argc, t_atom *argv) { + if (argc >= 1) { + if (argv[0].a_type == A_SYMBOL) { + t_symbol *tmp = atom_getsymbol(&argv[0]); + playlist_load(tmp->s_name); + } + } +} + */ +/** The class */ +t_class *xmms_class; + +/** constructor */ +void *xmms_new(t_symbol *selector, int argc, t_atom *argv) { + t_xmms *x = (t_xmms *) pd_new(xmms_class); + //x->x_outlet = outlet_new(&x->x_ob, gensym("symbol")); + x->session = 0; + // if (!xmms_remote_is_running(x->session)) return 0; + return (void *)x; +} + +/** setup */ +void xmms_setup(void) { + xmms_class = class_new(gensym("xmms"), (t_newmethod) xmms_new, 0, sizeof(t_xmms), 0, A_GIMME, 0); + + class_addmethod(xmms_class, (t_method)xmms_stop, gensym("stop"), A_GIMME, 0); + class_addmethod(xmms_class, (t_method)xmms_play, gensym("play"), A_GIMME, 0); + class_addmethod(xmms_class, (t_method)xmms_pause, gensym("pause"), A_GIMME, 0); + class_addmethod(xmms_class, (t_method)xmms_next, gensym("next"), A_GIMME, 0); + class_addmethod(xmms_class, (t_method)xmms_prev, gensym("prev"), A_GIMME, 0); + class_addmethod(xmms_class, (t_method)xmms_forward, gensym("forward"), A_GIMME, 0); + class_addmethod(xmms_class, (t_method)xmms_backward, gensym("backward"), A_GIMME, 0); + class_addmethod(xmms_class, (t_method)xmms_volume, gensym("volume"), A_GIMME, 0); + //class_addmethod(xmms_class, (t_method)xmms_load0, gensym("load"), A_GIMME, 0); +} + -- cgit v1.2.1