/////////////////////////////////////////////////////////////////////////////////////////// /* * ola2pd - interface from Open Lighting Arquitecture to Pure Data * v 0.03 * * Copyright (c) 2012-2013 Santiago NoreƱa * * ola2pd is an external for Pure Data and Max that reads one DMX512 * universe from the Open Lighting Arquitecture and output it like a list * of 512 channels. * * Based on dmxmonitor Copyright (C) 2001 Dirk Jagdmann * and ola_dmxmonitor by Simon Newton (nomis52gmail.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "m_pd.h" //#include #include #include #include #include //#include #include #include #include #include //#include //#include //static char *version = "$Revision: 0.01 $"; //#define DEBUG(x) /*------------------------------------------------------------------------------ * CLASS DEF */ //static t_class *ola2pd_class; typedef struct _ola2pd { t_object x_obj; t_outlet *x_out; unsigned int x_universe; unsigned int x_counter; OlaCallbackClient *x_clientpointer; } t_ola2pd; struct timeval m_last_data; OlaCallbackClientWrapper m_client; /*------------------------------------------------------------------------------ * IMPLEMENTATION */ void ola2pd_open(t_ola2pd* x) { if (x->x_clientpointer == NULL) { // set up ola connection if (!m_client.Setup()) {post("%s: %s",thisName(), strerror(errno));} x->x_clientpointer = m_client.GetClient(); x->x_clientpointer->SetDmxCallback(ola::NewCallback(this, &ola2pd::NewDmx)); x->xclientpointer->RegisterUniverse(m_universe,ola::REGISTER,ola::NewSingleCallback(this, &ola2pd::RegisterComplete)); x->xclient.GetSelectServer()->RegisterRepeatingTimeout(5000,ola::NewCallback(this, &ola2pd::CheckDataLoss)); post("ola2pd: Init complete. Start listening..."); x->x_client.GetSelectServer()->Run(); } } void ola2pd_close(t_ola2pd* x) { if (x->x_clientpointer != NULL) { x->x_clientpointer->RegisterUniverse(x->x_universe,ola::UNREGISTER,ola::NewSingleCallback(this, &ola2pd::RegisterComplete)); m_client.GetSelectServer()->Terminate(); m_clientpointer = NULL; post("ola2pd: Close complete"); } } void ola2pd_universe(t_ola2pd* x, t_floatarg f) { x->x_universe = f; } void ola2pd_bang(t_ola2pd* x) { if (x->x_clientpointer != NULL) {post("%s listening on universe %d",thisName(),x->x_universe);} else {post("%s configured on universe %d. Send open to start listening",thisName(),x->x_universe);} } /* * Called when there is new DMX data */ void NewDmx(unsigned int universe,const DmxBuffer &buffer,const string &error) { m_counter++; gettimeofday(&m_last_data, NULL); int z; AtomList dmxlist; dmxlist(512); for(z=0; z < 512; z++){SetFloat(dmxlist[z],(buffer.Get(z)));} ToOutList(0, dmxlist); } /* * Check for data loss. */ bool CheckDataLoss() { struct timeval now, diff; if (timerisset(&m_last_data)) { gettimeofday(&now, NULL); timersub(&now, &m_last_data, &diff); if (diff.tv_sec > 4 || (diff.tv_sec == 4 && diff.tv_usec > 4000000)) { // loss of data post("ola2pd: Can not read DMX!"); } } return true; } /* * Control de errores en el registro de Universos en OLA */ void ola2pd::RegisterComplete(const string &error) { if (!error.empty()) { post("ola2pd:Register command failed"); m_client.GetSelectServer()->Terminate(); } } t_class *ola2pd_class; void *ola2pd_new() { t_ola2pd *x = (t_ola2pd *)pd_new(ola2pd_class); x->x_out = outlet_new((t_object *)x, &s_symbol); x->x_pattern = gensym("empty"); x->x_universe = 0; x->x_counter = 0; return (void *)x; } void ola2pd_setup(void) { ola2pd_class = class_new(gensym("ola2pd"),(t_newmethod)ola2pd_new,0,sizeof(t_ola2pd),0,A_DEFFLOAT, 0); /* add inlet datatype methods */ class_addbang(ola2pd_class,(t_method) ola2pd_output); class_addmethod(ola2pd_class,(t_method)ola2pd_file,gensym("open"),0); class_addmethod(ola2pd_class,(t_method)ola2pd_type,gensym("close"),0); class_addmethod(ola2pd_class,(t_method)ola2pd_type,gensym("universe"),A_FLOAT, 0); class_addfloat(ola2pd_class, ola2pd_universe); }