summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/extra/OSCroute.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/extra/OSCroute.c')
-rw-r--r--apps/plugins/pdbox/PDa/extra/OSCroute.c604
1 files changed, 0 insertions, 604 deletions
diff --git a/apps/plugins/pdbox/PDa/extra/OSCroute.c b/apps/plugins/pdbox/PDa/extra/OSCroute.c
index 437d34dc68..24860d0b79 100644
--- a/apps/plugins/pdbox/PDa/extra/OSCroute.c
+++ b/apps/plugins/pdbox/PDa/extra/OSCroute.c
@@ -598,607 +598,3 @@ static Boolean MatchList (const char *pattern, const char *test) {
598 598
599} 599}
600 600
601
602
603/*
604Written by Adrian Freed, The Center for New Music and Audio Technologies,
605University of California, Berkeley. Copyright (c) 1992,93,94,95,96,97,98,99,2000,01,02,03,04
606The Regents of the University of California (Regents).
607
608Permission to use, copy, modify, distribute, and distribute modified versions
609of this software and its documentation without fee and without a signed
610licensing agreement, is hereby granted, provided that the above copyright
611notice, this paragraph and the following two paragraphs appear in all copies,
612modifications, and distributions.
613
614IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
615SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
616OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
617BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
618
619REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
620THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
621PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
622HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
623MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
624
625
626The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl
627*/
628
629 /* OSC-route.c
630 Max object for OSC-style dispatching
631
632 To-do:
633
634 Match a pattern against a pattern?
635 Declare outlet types / distinguish leaf nodes from other children
636 More sophisticated (2-pass?) allmessages scheme
637 set message?
638
639
640 pd
641 -------------
642 -- tweaks for Win32 www.zeggz.com/raf 13-April-2002
643
644
645 */
646
647#ifdef WIN32
648 #include <stdlib.h>
649 #include <string.h>
650#endif
651#ifdef __APPLE__
652 #include <stdio.h>
653#endif
654#ifdef UNIX
655 #include <stdio.h>
656#endif
657
658/* structure definition of your object */
659
660#define MAX_NUM 20
661#define OSC_ROUTE_VERSION "1.05"
662#define OSCWarning(x...) post(x)
663
664/* the required include files */
665#include "m_pd.h"
666
667
668#ifndef TRUE
669typedef int Boolean;
670#define TRUE 1
671#define FALSE 0
672#endif
673
674
675/* Fixed byte width types */
676typedef int int4; /* 4 byte int */
677
678Boolean PatternMatch (const char *pattern, const char *test);
679
680
681
682/* Version 1.04: Allows #1 thru #9 as typed-in arguments
683 Version 1.05: Allows "list" messages as well as "message" messages.
684*/
685
686static t_class *OSCroute_class;
687
688typedef struct _OSCroute
689{
690 t_object x_obj; // required header
691 t_int x_num; // Number of address prefixes we store
692 t_int x_complainmode; // Do we print a message if no match?
693 t_int x_sendmode; // use pd internal sends instead of outlets
694 char *x_prefixes[MAX_NUM];
695 void *x_outlets[MAX_NUM+1];
696} t_OSCroute;
697
698t_symbol *ps_list, *ps_complain, *ps_emptySymbol;
699
700/* prototypes */
701
702void OSCroute_doanything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
703void OSCroute_anything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
704void OSCroute_list(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
705/* //void *OSCroute_new(t_symbol *s, int argc, atom *argv); */
706void *OSCroute_new(t_symbol *s, int argc, t_atom *argv);
707void OSCroute_version (t_OSCroute *x);
708/* void OSCroute_assist (OSCroute *x, void *box, long msg, long arg, */
709/* char *dstString); */
710void OSCroute_allmessages(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv);
711
712static char *NextSlashOrNull(char *p);
713static void StrCopyUntilSlash(char *target, const char *source);
714
715
716// free
717static void OSCroute_free(t_OSCroute *x)
718{
719 // freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec));
720}
721
722/* initialization routine */
723
724// setup
725#ifdef WIN32
726 OSC_API void OSCroute_setup(void) {
727#else
728void OSCroute_setup(void) {
729#endif
730 OSCroute_class = class_new(gensym("OSCroute"), (t_newmethod)OSCroute_new,
731 (t_method)OSCroute_free,sizeof(t_OSCroute), 0, A_GIMME, 0);
732 class_addlist(OSCroute_class, OSCroute_list);
733 class_addanything(OSCroute_class, OSCroute_anything);
734 class_addmethod(OSCroute_class, (t_method)OSCroute_version, gensym("version"), A_NULL, 0, 0);
735 class_sethelpsymbol(OSCroute_class, gensym("OSCroute-help.pd"));
736
737 /*
738 class_addmethod(OSCroute_class, (t_method)OSCroute_connect,
739 gensym("connect"), A_SYMBOL, A_FLOAT, 0);
740 class_addmethod(OSCroute_class, (t_method)OSCroute_disconnect,
741 gensym("disconnect"), 0);
742 class_addmethod(OSCroute_class, (t_method)OSCroute_send, gensym("send"),
743 A_GIMME, 0);
744 */
745/* ps_list = gensym("list"); */
746/* ps_complain = gensym("complain"); */
747 ps_emptySymbol = gensym("");
748
749 post("OSCroute object version " OSC_ROUTE_VERSION " by Matt Wright. pd: jdl Win32 raf.");
750 post("OSCroute Copyright © 1999 Regents of the University of California. All Rights Reserved.");
751}
752
753
754
755/* instance creation routine */
756
757void *OSCroute_new(t_symbol *s, int argc, t_atom *argv)
758{
759
760 t_OSCroute *x = (t_OSCroute *)pd_new(OSCroute_class); // get memory for a new object & initialize
761
762 int i; //{{raf}} n not used
763
764 // EnterCallback();
765
766 if (argc > MAX_NUM) {
767 post("* OSC-route: too many arguments: %ld (max %ld)", argc, MAX_NUM);
768 // ExitCallback();
769 return 0;
770 }
771
772 x->x_complainmode = 0;
773 x->x_num = 0;
774 for (i = 0; i < argc; ++i) {
775 if (argv[i].a_type == A_SYMBOL) {
776 if (argv[i].a_w.w_symbol->s_name[0] == '/') {
777 /* Now that's a nice prefix */
778 x->x_prefixes[i] = argv[i].a_w.w_symbol->s_name;
779 ++(x->x_num);
780 } else if (argv[i].a_w.w_symbol->s_name[0] == '#' &&
781 argv[i].a_w.w_symbol->s_name[1] >= '1' &&
782 argv[i].a_w.w_symbol->s_name[1] <= '9') {
783 /* The Max programmer is trying to make a patch that will be
784 a subpatch with arguments. We have to make an outlet for this
785 argument. */
786 x->x_prefixes[i] = "dummy";
787 ++(x->x_num);
788 } else {
789 /* Maybe this is an option we support */
790
791/* if (argv[i].a_w.w_sym == ps_complain) { */
792/* x->x_complainmode = 1; */
793/* } else { */
794/* post("* OSC-route: Unrecognized argument %s", argv[i].a_w.w_sym->s_name); */
795/* } */
796
797 }
798
799 // no LONG
800
801/* } else if (argv[i].a_type == A_FLOAD) { */
802/* // Convert to a numeral. Max ints are -2147483648 to 2147483647 */
803/* char *string = getbytes(12); */
804/* // I can't be bothered to plug this 12 byte memory leak */
805/* if (string == 0) { */
806/* post("* OSC-route: out of memory!"); */
807/* // ExitCallback(); */
808/* return 0; */
809/* } */
810/* sprintf(string, "%d", argv[i].a_w.w_long); */
811/* x->x_prefixes[i] = string; */
812/* ++(x->x_num); */
813
814 } else if (argv[i].a_type == A_FLOAT) {
815 post("* OSC-route: float arguments are not OK.");
816 // ExitCallback();
817 return 0;
818 } else {
819 post("* OSC-route: unrecognized argument type!");
820 // ExitCallback();
821 return 0;
822 }
823 }
824
825
826 /* Have to create the outlets in reverse order */
827 /* well, not in pd ? */
828 // for (i = x->x_num-1; i >= 0; --i) {
829 // for (i = 0; i <= x->x_num-1; i++) {
830 for (i = 0; i <= x->x_num; i++) {
831 // x->x_outlets[i] = listout(x);
832 x->x_outlets[i] = outlet_new(&x->x_obj, &s_list);
833 }
834
835 // ExitCallback();
836 return (x);
837}
838
839
840void OSCroute_version (t_OSCroute *x) {
841 // EnterCallback();
842 post("OSCroute Version " OSC_ROUTE_VERSION
843 ", by Matt Wright. pd jdl, win32: raf.\nOSCroute Compiled " __TIME__ " " __DATE__);
844 // ExitCallback();
845}
846
847/* I don't know why these aren't defined in some Max #include file. */
848#define ASSIST_INLET 1
849#define ASSIST_OUTLET 2
850
851void OSCroute_assist (t_OSCroute *x, void *box, long msg, long arg,
852 char *dstString) {
853 // EnterCallback();
854
855 if (msg==ASSIST_INLET) {
856 sprintf(dstString, "Incoming OSC messages");
857 } else if (msg==ASSIST_OUTLET) {
858 if (arg < 0 || arg >= x->x_num) {
859 post("* OSCroute_assist: No outlet corresponds to arg %ld!", arg);
860 } else {
861 sprintf(dstString, "subaddress + args for prefix %s", x->x_prefixes[arg]);
862 }
863 } else {
864 post("* OSCroute_assist: unrecognized message %ld", msg);
865 }
866
867 // ExitCallback();
868}
869
870void OSCroute_list(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
871 // EnterCallback();
872 if (argc > 0 && argv[0].a_type == A_SYMBOL) {
873 /* Ignore the fact that this is a "list" */
874 OSCroute_doanything(x, argv[0].a_w.w_symbol, argc-1, argv+1);
875 } else {
876 // post("* OSC-route: invalid list beginning with a number");
877 // output on unmatched outlet jdl 20020908
878 if (argv[0].a_type == A_FLOAT) {
879 outlet_float(x->x_outlets[x->x_num], argv[0].a_w.w_float);
880 } else {
881 post("* OSC-route: unrecognized atom type!");
882 }
883 }
884 // ExitCallback();
885}
886
887
888void OSCroute_anything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
889 // EnterCallback();
890 OSCroute_doanything(x, s, argc, argv);
891 // ExitCallback();
892}
893
894
895
896
897void OSCroute_doanything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
898 char *pattern, *nextSlash;
899 int i;
900 int matchedAnything;
901 // post("*** OSCroute_anything(s %s, argc %ld)", s->s_name, (long) argc);
902
903 pattern = s->s_name;
904 if (pattern[0] != '/') {
905 post("* OSC-route: invalid message pattern %s does not begin with /", s->s_name);
906 outlet_anything(x->x_outlets[x->x_num], s, argc, argv);
907 return;
908 }
909
910 matchedAnything = 0;
911
912 nextSlash = NextSlashOrNull(pattern+1);
913 if (*nextSlash == '\0') {
914 /* last level of the address, so we'll output the argument list */
915
916
917#ifdef NULL_IS_DIFFERENT_FROM_BANG
918 if (argc==0) {
919 post("* OSC-route: why are you matching one level pattern %s with no args?",
920 pattern);
921 return;
922 }
923#endif
924
925 for (i = 0; i < x->x_num; ++i) {
926 if (PatternMatch(pattern+1, x->x_prefixes[i]+1)) {
927 ++matchedAnything;
928
929 // I hate stupid Max lists with a special first element
930 if (argc == 0) {
931 outlet_bang(x->x_outlets[i]);
932 } else if (argv[0].a_type == A_SYMBOL) {
933 // Promote the symbol that was argv[0] to the special symbol
934 outlet_anything(x->x_outlets[i], argv[0].a_w.w_symbol, argc-1, argv+1);
935 } else if (argc > 1) {
936 // Multiple arguments starting with a number, so naturally we have
937 // to use a special function to output this "list", since it's what
938 // Max originally meant by "list".
939 outlet_list(x->x_outlets[i], 0L, argc, argv);
940 } else {
941 // There was only one argument, and it was a number, so we output it
942 // not as a list
943/* if (argv[0].a_type == A_LONG) { */
944
945/* outlet_int(x->x_outlets[i], argv[0].a_w.w_long); */
946 // } else
947 if (argv[0].a_type == A_FLOAT) {
948
949 outlet_float(x->x_outlets[i], argv[0].a_w.w_float);
950 } else {
951 post("* OSC-route: unrecognized atom type!");
952 }
953 }
954 }
955 }
956 } else {
957 /* There's more address after this part, so our output list will begin with
958 the next slash. */
959 t_symbol *restOfPattern = 0; /* avoid the gensym unless we have to output */
960 char patternBegin[1000];
961
962
963 /* Get the first level of the incoming pattern to match against all our prefixes */
964 StrCopyUntilSlash(patternBegin, pattern+1);
965
966 for (i = 0; i < x->x_num; ++i) {
967 if (PatternMatch(patternBegin, x->x_prefixes[i]+1)) {
968 ++matchedAnything;
969 if (restOfPattern == 0) {
970 restOfPattern = gensym(nextSlash);
971 }
972 outlet_anything(x->x_outlets[i], restOfPattern, argc, argv);
973 }
974 }
975 }
976
977 if (x->x_complainmode) {
978 if (!matchedAnything) {
979 post("* OSC-route: pattern %s did not match any prefixes", pattern);
980 }
981 }
982
983 // output unmatched data on rightmost outlet a la normal 'route' object, jdl 20020908
984 if (!matchedAnything) {
985 outlet_anything(x->x_outlets[x->x_num], s, argc, argv);
986 }
987
988
989}
990
991static char *NextSlashOrNull(char *p) {
992 while (*p != '/' && *p != '\0') {
993 p++;
994 }
995 return p;
996}
997
998static void StrCopyUntilSlash(char *target, const char *source) {
999 while (*source != '/' && *source != '\0') {
1000 *target = *source;
1001 ++target;
1002 ++source;
1003 }
1004 *target = 0;
1005}
1006
1007static int MyStrCopy(char *target, const char *source) {
1008 int i = 0;
1009 while (*source != '\0') {
1010 *target = *source;
1011 ++target;
1012 ++source;
1013 ++i;
1014 }
1015 *target = 0;
1016 return i;
1017}
1018
1019
1020
1021void OSCroute_allmessages(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) {
1022 int i;
1023 t_symbol *prefixSymbol = 0;
1024 char prefixBuf[1000];
1025 char *endOfPrefix;
1026 t_atom a[1];
1027
1028 if (argc >= 1 && argv[0].a_type == A_SYMBOL) {
1029 prefixSymbol = argv[0].a_w.w_symbol;
1030 endOfPrefix = prefixBuf + MyStrCopy(prefixBuf,
1031 prefixSymbol->s_name);
1032 } else {
1033 prefixSymbol = ps_emptySymbol;
1034 prefixBuf[0] = '\0';
1035 endOfPrefix = prefixBuf;
1036 }
1037
1038
1039 for (i = 0; i < x->x_num; ++i) {
1040 post("OSC: %s%s", prefixSymbol->s_name, x->x_prefixes[i]);
1041 MyStrCopy(endOfPrefix, x->x_prefixes[i]);
1042 SETSYMBOL(a, gensym(prefixBuf));
1043 outlet_anything(x->x_outlets[i], s, 1, a);
1044 }
1045}
1046
1047
1048/* --------------------------------------------------- */
1049
1050
1051
1052static const char *theWholePattern; /* Just for warning messages */
1053
1054static Boolean MatchBrackets (const char *pattern, const char *test);
1055static Boolean MatchList (const char *pattern, const char *test);
1056
1057Boolean PatternMatch (const char * pattern, const char * test) {
1058 theWholePattern = pattern;
1059
1060 if (pattern == 0 || pattern[0] == 0) {
1061 return test[0] == 0;
1062 }
1063
1064 if (test[0] == 0) {
1065 if (pattern[0] == '*')
1066 return PatternMatch (pattern+1,test);
1067 else
1068 return FALSE;
1069 }
1070
1071 switch (pattern[0]) {
1072 case 0 : return test[0] == 0;
1073 case '?' : return PatternMatch (pattern + 1, test + 1);
1074 case '*' :
1075 if (PatternMatch (pattern+1, test)) {
1076 return TRUE;
1077 } else {
1078 return PatternMatch (pattern, test+1);
1079 }
1080 case ']' :
1081 case '}' :
1082 OSCWarning("Spurious %c in pattern \".../%s/...\"",pattern[0], theWholePattern);
1083 return FALSE;
1084 case '[' :
1085 return MatchBrackets (pattern,test);
1086 case '{' :
1087 return MatchList (pattern,test);
1088 case '\\' :
1089 if (pattern[1] == 0) {
1090 return test[0] == 0;
1091 } else if (pattern[1] == test[0]) {
1092 return PatternMatch (pattern+2,test+1);
1093 } else {
1094 return FALSE;
1095 }
1096 default :
1097 if (pattern[0] == test[0]) {
1098 return PatternMatch (pattern+1,test+1);
1099 } else {
1100 return FALSE;
1101 }
1102 }
1103}
1104
1105
1106/* we know that pattern[0] == '[' and test[0] != 0 */
1107
1108static Boolean MatchBrackets (const char *pattern, const char *test) {
1109 Boolean result;
1110 Boolean negated = FALSE;
1111 const char *p = pattern;
1112
1113 if (pattern[1] == 0) {
1114 OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
1115 return FALSE;
1116 }
1117
1118 if (pattern[1] == '!') {
1119 negated = TRUE;
1120 p++;
1121 }
1122
1123 while (*p != ']') {
1124 if (*p == 0) {
1125 OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
1126 return FALSE;
1127 }
1128 if (p[1] == '-' && p[2] != 0) {
1129 if (test[0] >= p[0] && test[0] <= p[2]) {
1130 result = !negated;
1131 goto advance;
1132 }
1133 }
1134 if (p[0] == test[0]) {
1135 result = !negated;
1136 goto advance;
1137 }
1138 p++;
1139 }
1140
1141 result = negated;
1142
1143advance:
1144
1145 if (!result)
1146 return FALSE;
1147
1148 while (*p != ']') {
1149 if (*p == 0) {
1150 OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
1151 return FALSE;
1152 }
1153 p++;
1154 }
1155
1156 return PatternMatch (p+1,test+1);
1157}
1158
1159static Boolean MatchList (const char *pattern, const char *test) {
1160
1161 const char *restOfPattern, *tp = test;
1162
1163
1164 for(restOfPattern = pattern; *restOfPattern != '}'; restOfPattern++) {
1165 if (*restOfPattern == 0) {
1166 OSCWarning("Unterminated { in pattern \".../%s/...\"", theWholePattern);
1167 return FALSE;
1168 }
1169 }
1170
1171 restOfPattern++; /* skip close curly brace */
1172
1173
1174 pattern++; /* skip open curly brace */
1175
1176 while (1) {
1177
1178 if (*pattern == ',') {
1179 if (PatternMatch (restOfPattern, tp)) {
1180 return TRUE;
1181 } else {
1182 tp = test;
1183 ++pattern;
1184 }
1185 } else if (*pattern == '}') {
1186 return PatternMatch (restOfPattern, tp);
1187 } else if (*pattern == *tp) {
1188 ++pattern;
1189 ++tp;
1190 } else {
1191 tp = test;
1192 while (*pattern != ',' && *pattern != '}') {
1193 pattern++;
1194 }
1195 if (*pattern == ',') {
1196 pattern++;
1197 }
1198 }
1199 }
1200
1201}
1202
1203
1204