diff options
Diffstat (limited to 'oscbonjour')
-rw-r--r-- | oscbonjour/README.txt | 23 | ||||
-rw-r--r-- | oscbonjour/makefile | 46 | ||||
-rw-r--r-- | oscbonjour/oscbonjour.cpp | 282 |
3 files changed, 351 insertions, 0 deletions
diff --git a/oscbonjour/README.txt b/oscbonjour/README.txt new file mode 100644 index 0000000..93df570 --- /dev/null +++ b/oscbonjour/README.txt @@ -0,0 +1,23 @@ + +oscbonjour - a PD external for browsing/resolving and registering +Bonjour/ZeroConf services +--------- + +This is a port of the oscbonjour Max/MSP external by Remy Muller + +To compile you will need osctools, as found at: + +http://sourceforge.net/projects/osctools/ + +then modify the makefile so that ZEROCONF-SRC points to +osctools/zeroconf and type: + +make +sudo make install + +from the current directory + +jamie@postlude.co.uk, 2006 + + + diff --git a/oscbonjour/makefile b/oscbonjour/makefile new file mode 100644 index 0000000..4c4eb8c --- /dev/null +++ b/oscbonjour/makefile @@ -0,0 +1,46 @@ +PD-PATH=/usr/lib/pd +PD-SRC=/usr/local/include +ZEROCONF-SRC=../zeroconf + +CC = g++ +LD = g++ +INCLUDE=-I$(PD-SRC) -I$(ZEROCONF-SRC) -I. +LIB=-lc -lm +CC_FLAGS = -DPD -c -Wall -fPIC -O3 +LD_FLAGS = --export-dynamic -shared -o + + +TARGET=oscbonjour.pd_linux +OBJ=oscbonjour.o + + +#-------------------------------------------------------- + +all: pd_linux + +pd_linux: $(TARGET) + + +$(TARGET): $(OBJ) + $(LD) $(LD_FLAGS) $(TARGET) $(OBJ) $(LIB) + strip --strip-unneeded $(TARGET) + chmod 755 $(TARGET) + +oscbonjour.o: + $(CC) $(CC_FLAGS) $(INCLUDE) oscbonjour.cpp +#TinyXML: + +#tinyxml.o: tinyxml/tinyxml.h tinyxml/tinyxml.cpp +# $(CC) $(CC_FLAGS) $(INCLUDE) tinyxml/tinyxml.cpp + + +#----------------------------------------------------- + + +clean: + rm -f $(OBJ) $(TARGET) + + +install: + cp -f $(TARGET) $(PD-PATH)/externs + cp -f help/*.pd $(PD-PATH)/doc/5.reference diff --git a/oscbonjour/oscbonjour.cpp b/oscbonjour/oscbonjour.cpp new file mode 100644 index 0000000..3f7b6df --- /dev/null +++ b/oscbonjour/oscbonjour.cpp @@ -0,0 +1,282 @@ +/* + This file is part of Oscbonjour. + Copyright (c) 2005 Rémy Muller. + + 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 "m_pd.h" + +#include "OscUdpZeroConfBrowser.h" +#include "OscUdpZeroConfResolver.h" +#include "OscUdpZeroConfService.h" + +//#include "ZeroConf.h" + +#include <vector> +#include <string> +#include <algorithm> + +#define VERSION "0.1 alpha" + +class Oscbonjour; + + +//------------------------------------------------------------------------------------------------------------ +// class +//------------------------------------------------------------------------------------------------------------ +typedef struct oscbonjour +{ + t_object x_obj; + Oscbonjour *oscbonjour; + t_outlet *out0,*out1,*out2; +} t_oscbonjour; + +t_class *oscbonjour_class; +//static t_messlist *oscbonjour_class = NULL; + + +//------------------------------------------------------------------------------------------------------------ +class Oscbonjour : public OSCBrowseListener + , public OSCResolveListener + , public OSCRegisterListener +{ + t_oscbonjour *external; + + //ZeroConf zeroconf; + OscUdpZeroConfBrowser *browser; + OscUdpZeroConfResolver *resolver; + OscUdpZeroConfService *service; + std::vector<std::string> services; + typedef std::vector<std::string>::iterator veciterator; + +public: + Oscbonjour(t_oscbonjour *external) + :external(external) + ,browser(0) + ,resolver(0) + ,service(0) + + { + } + virtual ~Oscbonjour() + { + if(browser) delete browser; + if(resolver)delete resolver; + if(service) delete service; + } + void Browse(const char *type, const char *domain) + { + services.clear(); + if(browser) delete browser; + browser = 0; + browser = new OscUdpZeroConfBrowser(this); +// zeroconf.Browse(type,domain,this); + } + void Resolve(const char *name,const char *type,const char *domain) + { + if(resolver) delete resolver; + resolver = 0; + resolver = new OscUdpZeroConfResolver(name,type,domain,this); +// zeroconf.Resolve(name,type,domain,this); + } + void Register(const char *name,t_int port) + { + if(service) delete service; + service = 0; + service = new OscUdpZeroConfService(name,port,this); +// zeroconf.Register(name,"_osc._udp","local",port,this); + } + virtual void OnAddService(const char *name,const char *type,const char *domain) + { + std::string servname(name); + veciterator it = std::find(services.begin(),services.end(),servname); + if(it!=services.end()) return; // we already have it + services.push_back(servname); + + t_atom at[1]; + SETSYMBOL(at,gensym(const_cast<char*>(servname.c_str()))); + + if(external) + outlet_anything(external->out2,gensym("append"),1,at); + } + virtual void OnRemoveService(const char *name,const char *type,const char *domain) + { + std::string servname(name); + veciterator it = std::find(services.begin(),services.end(),servname); + if(it==services.end()) return; // we don't have it + t_int index = it-services.begin(); // store the position + services.erase(it); + + t_atom at[1]; + SETFLOAT(at,index); + + if(external) + outlet_anything(external->out2,gensym("delete"),1,at); + } + virtual void OnResolveService(const char *fullName,const char *hostTarget,int port,const char *txtRecord) + { + if(external) + { + t_atom at[1]; + + SETSYMBOL(at,gensym(const_cast<char*>(hostTarget))); + outlet_anything(external->out0,gensym("host"),1,at); + + SETFLOAT(at,port); + outlet_anything(external->out0,gensym("port"),1,at); + } + } + virtual void OnRegisterService(const char *name) + { + t_atom at[1]; + SETSYMBOL(at,gensym(const_cast<char*>(name))); + + if(external) + outlet_anything(external->out1,gensym("realname"),1,at); + } + +}; + +//------------------------------------------------------------------------------------------------------------ +static void oscbonjour_version(t_oscbonjour *x, t_symbol *s, short ac, t_atom *at) +{ + post("oscbonjour (mDNS for Pure Data) version %s", VERSION); +} +//------------------------------------------------------------------------------------------------------------ +// user t_methods +//------------------------------------------------------------------------------------------------------------ +static void oscbonjour_register(t_oscbonjour *x, t_symbol *s, short ac, t_atom *at) +{ + if(ac<2) return; + if(at[0].a_type != A_SYMBOL || at[1].a_type != A_FLOAT) return; + + t_int port = (t_int)at[1].a_w.w_float; + x->oscbonjour->Register(at[0].a_w.w_symbol->s_name,port); +} +//------------------------------------------------------------------------------------------------------------ +static void oscbonjour_browse(t_oscbonjour *x, t_symbol *s, short ac, t_atom *at) +{ + outlet_anything(x->out2,gensym("clear"),0,NULL); + + const char *type = "_osc._udp"; + const char *domain = "local"; + + if(ac>0) + { + // 1st arg is type + // 2nd is domain + } + x->oscbonjour->Browse(type,domain); +} +//------------------------------------------------------------------------------------------------------------ +static void oscbonjour_resolve(t_oscbonjour *x, t_symbol *s, short ac, t_atom *at) +{ + if(ac<1) return; + if(at[0].a_type != A_SYMBOL) return; + + const char *name = at[0].a_w.w_symbol->s_name; + const char *type = "_osc._udp"; + const char *domain = "local"; + + if(ac>1) + { + // 2nd argument is type + // 3rd argument is domain + } + + x->oscbonjour->Resolve(name,type,domain); +} +//------------------------------------------------------------------------------------------------------------ +static void oscbonjour_assist(t_oscbonjour *x, void *b, t_int msg, t_int a, char *dst) +{ + if (msg == 1) //inlet + { + sprintf(dst,"messages: browse, resolve, register"); + } + else if (msg == 2) //outlet + { + switch(a) + { + case 0: sprintf(dst,"resolved host and port for service name"); break; + case 1: sprintf(dst,"real registered service name"); break; + case 2: sprintf(dst,"available services, connect to menu"); break; + default: break; + } + } +} +//------------------------------------------------------------------------------------------------------------ +static void *oscbonjour_new(t_symbol *s, t_int ac, t_atom *at) +{ + t_oscbonjour *x = (t_oscbonjour *)pd_new(oscbonjour_class); + + x->oscbonjour = new Oscbonjour(x); + x->out2 = outlet_new(&x->x_obj,0L); + x->out1 = outlet_new(&x->x_obj,0L); + x->out0 = outlet_new(&x->x_obj,0L); + + if(ac>0) + { + if(at[0].a_type != A_SYMBOL) + { + post("bad arguments"); + return x; + } + t_symbol *sym = at[0].a_w.w_symbol; + std::string cmd(sym->s_name); + + at++; + ac--; + + if (cmd == "register") oscbonjour_register (x,sym,ac,at); + else if (cmd == "browse") oscbonjour_browse (x,sym,ac,at); + else if (cmd == "resolve") oscbonjour_resolve (x,sym,ac,at); + } + + return x; +} +//------------------------------------------------------------------------------------------------------------ +static void oscbonjour_free(t_oscbonjour *x) +{ + if(x->oscbonjour) delete x->oscbonjour; +} + +//------------------------------------------------------------------------------------------------------------ +// Entry Point +//------------------------------------------------------------------------------------------------------------ +extern "C" void oscbonjour_setup(void) +{ + oscbonjour_class = class_new(gensym("oscbonjour"), (t_newmethod)oscbonjour_new, (t_method)oscbonjour_free, (short)sizeof(t_oscbonjour), 0L, A_GIMME, 0); + + class_addmethod(oscbonjour_class, (t_method)oscbonjour_register, gensym("register"), A_GIMME, 0); + class_addmethod(oscbonjour_class, (t_method)oscbonjour_browse, gensym("browse"), A_GIMME, 0); + class_addmethod(oscbonjour_class, (t_method)oscbonjour_resolve, gensym("resolve"), A_GIMME, 0); + class_addmethod(oscbonjour_class, (t_method)oscbonjour_assist, gensym("assist"), A_CANT, 0); + + oscbonjour_version(0, 0, 0, 0); + +} + + + |