lms-video/src/ola2pd/ola2pd.c
2013-04-29 19:18:42 +02:00

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);
}