/* * ola2pd - interface from Open Lighting Arquitecture to Pure Data * v 0.03 * * Copyright (c) 2012-2013 Santiago NoreƱa (libremediaserver@gmail.com) * * 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. * */ // Define flext #define FLEXT_USE_CMEM 1 //#define FLEXT_SHARED 1 #define FLEXT_ATTRIBUTES 1 #include #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 500) #error You need at least flext version 0.5.0 #endif #ifdef HAVE_CONFIG_H #include #endif // Define general #include #include // Define ola #include #include #include #include #include #include #include using ola::DmxBuffer; using ola::OlaCallbackClient; using ola::OlaCallbackClientWrapper; using ola::io::SelectServer; using std::string; class ola2pd: public flext_base { FLEXT_HEADER_S(ola2pd,flext_base,setup) public: // constructor with no arguments ola2pd(): // initialize data members m_universe(0), m_clientpointer(NULL), m_counter(0) // m_stdin_descriptor(STDIN_FILENO) { // --- define inlets and outlets --- AddInAnything(); // default inlet AddOutList(); // outlet for DMX list post("ola2pd v0.03 - an interface to Open Lighting Arquitecture"); post("(C) 2012-2013 Santi Nore libremediaserver@gmail.com"); } void NewDmx(unsigned int universe, const DmxBuffer &buffer, const string &error); void RegisterComplete(const string &error); // void StdinReady(); bool CheckDataLoss(); protected: void m_open() { if (m_clientpointer == NULL) { // set up ola connection if (!m_client.Setup()) { post("%s: %s",thisName(), strerror(errno)); } m_clientpointer = m_client.GetClient(); m_clientpointer->SetDmxCallback(ola::NewCallback(this, &ola2pd::NewDmx)); m_clientpointer->RegisterUniverse(m_universe,ola::REGISTER,ola::NewSingleCallback(this, &ola2pd::RegisterComplete)); // m_client.GetSelectServer()->AddReadDescriptor(&m_stdin_descriptor); // m_stdin_descriptor.SetOnData(ola::NewCallback(this, &ola2pd::StdinReady)); m_client.GetSelectServer()->RegisterRepeatingTimeout(5000,ola::NewCallback(this, &ola2pd::CheckDataLoss)); post("ola2pd: Init complete. Start listening..."); m_client.GetSelectServer()->Run(); } } void m_close() { if (m_clientpointer != NULL) { m_clientpointer->RegisterUniverse(m_universe,ola::UNREGISTER,ola::NewSingleCallback(this, &ola2pd::RegisterComplete)); m_client.GetSelectServer()->Terminate(); post("ola2pd: Close complete"); m_clientpointer = NULL; } } void m_bang() { if (m_clientpointer != NULL) {post("%s listening on universe %d",thisName(),m_universe);} else {post("%s configured on universe %d. Send open to start listening",thisName(),m_universe);} } private: unsigned int m_universe; unsigned int m_counter; // ola::io::UnmanagedFileDescriptor m_stdin_descriptor; struct timeval m_last_data; OlaCallbackClientWrapper m_client; OlaCallbackClient *m_clientpointer; static void setup(t_classid c) { // --- set up methods (class scope) --- // register a bang method to the default inlet (0) FLEXT_CADDBANG(c,0,m_bang); // set up tagged methods for the default inlet (0) FLEXT_CADDMETHOD_(c,0,"open",m_open); FLEXT_CADDMETHOD_(c,0,"close",m_close); // --- set up attributes (class scope) --- FLEXT_CADDATTR_VAR1(c,"universe",m_universe); } FLEXT_CALLBACK(m_bang) FLEXT_THREAD(m_open) FLEXT_CALLBACK(m_close) FLEXT_ATTRVAR_I(m_universe) // wrapper functions (get and set) for integer variable universe }; // instantiate the class (constructor takes no arguments) FLEXT_NEW("ola2pd",ola2pd) /* * Called when there is new DMX data */ void ola2pd::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 ola2pd::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(); } }