180 lines
5 KiB
C
180 lines
5 KiB
C
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/*
|
|
* ola2pd - interface from Open Lighting Arquitecture to Pure Data
|
|
* v 0.03
|
|
*
|
|
* Copyright (c) 2012-2013 Santiago Noreña <belfegor@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 <doj@cubic.org>
|
|
* and ola_dmxmonitor by Simon Newton (nomis52<AT>gmail.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 <m_pd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include <iostream>
|
|
|
|
//#include <ola/BaseTypes.h>
|
|
#include <ola/Callback.h>
|
|
#include <ola/DmxBuffer.h>
|
|
#include <ola/OlaCallbackClient.h>
|
|
#include <ola/OlaClientWrapper.h>
|
|
|
|
//#include <ola/io/SelectServer.h>
|
|
//#include <ola/network/TCPSocket.h>
|
|
|
|
//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);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|