mirror of
				https://github.com/ElvishArtisan/rivendell.git
				synced 2025-11-04 08:04:12 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			869 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			869 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// rdlivewire.cpp
 | 
						|
//
 | 
						|
// A LiveWire Node Driver for Rivendell
 | 
						|
//
 | 
						|
//   (C) Copyright 2007,2016 Fred Gleason <fredg@paravelsystems.com>
 | 
						|
//
 | 
						|
//   This program is free software; you can redistribute it and/or modify
 | 
						|
//   it under the terms of the GNU General Public License version 2 as
 | 
						|
//   published by the Free Software Foundation.
 | 
						|
//
 | 
						|
//   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., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
						|
//
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
#include <syslog.h>
 | 
						|
#include <unistd.h>
 | 
						|
 | 
						|
#include <qapplication.h>
 | 
						|
#include <qsignalmapper.h>
 | 
						|
 | 
						|
#include <rd.h>
 | 
						|
#include <rdlivewire.h>
 | 
						|
 | 
						|
AString::AString()
 | 
						|
  : QString()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
AString::AString(const AString &lhs)
 | 
						|
  : QString(lhs)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
AString::AString(const QString &lhs)
 | 
						|
  : QString(lhs)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
QStringList AString::split(const QString &sep,const QString &esc) const
 | 
						|
{
 | 
						|
  if(esc.isEmpty()) {
 | 
						|
    return QStringList::split(sep,*this);
 | 
						|
  }
 | 
						|
  QStringList list;
 | 
						|
  bool escape=false;
 | 
						|
  QChar e=esc.at(0);
 | 
						|
  list.push_back(QString());
 | 
						|
  for(int i=0;i<length();i++) {
 | 
						|
    if(at(i)==e) {
 | 
						|
      escape=!escape;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      if((!escape)&&(mid(i,1)==sep)) {
 | 
						|
	list.push_back(QString());
 | 
						|
      }
 | 
						|
      else {
 | 
						|
	list.back()+=at(i);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return list;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
RDLiveWire::RDLiveWire(unsigned id,QObject *parent)
 | 
						|
  : QObject(parent)
 | 
						|
{
 | 
						|
  live_id=id;
 | 
						|
  live_sources=0;
 | 
						|
  live_destinations=0;
 | 
						|
  live_channels=RD_LIVEWIRE_DEFAULT_CHANNELS;
 | 
						|
  live_gpis=0;
 | 
						|
  live_gpos=0;
 | 
						|
  live_tcp_port=0;
 | 
						|
  live_base_output=0;
 | 
						|
  live_ptr=0;
 | 
						|
  live_connected=false;
 | 
						|
  live_load_ver_count=0;
 | 
						|
  live_gpi_initialized=false;
 | 
						|
  live_gpo_initialized=false;
 | 
						|
 | 
						|
  //
 | 
						|
  // Connection Socket
 | 
						|
  //
 | 
						|
  live_socket=new Q3Socket(this,"live_socket");
 | 
						|
  connect(live_socket,SIGNAL(connected()),this,SLOT(connectedData()));
 | 
						|
  connect(live_socket,SIGNAL(connectionClosed()),
 | 
						|
	  this,SLOT(connectionClosedData()));
 | 
						|
  connect(live_socket,SIGNAL(readyRead()),this,SLOT(readyReadData()));
 | 
						|
  connect(live_socket,SIGNAL(error(int)),this,SLOT(errorData(int)));
 | 
						|
 | 
						|
  //
 | 
						|
  // Watchdog Timers
 | 
						|
  //
 | 
						|
  live_watchdog_timer=new QTimer(this,",live_watchdog_timer");
 | 
						|
  connect(live_watchdog_timer,SIGNAL(timeout()),this,SLOT(watchdogData()));
 | 
						|
 | 
						|
  live_watchdog_timeout_timer=new QTimer(this,",live_watchdog_timeout_timer");
 | 
						|
  connect(live_watchdog_timeout_timer,SIGNAL(timeout()),
 | 
						|
	  this,SLOT(watchdogTimeoutData()));
 | 
						|
 | 
						|
  live_holdoff_timer=new QTimer(this,",live_holdoff_timer");
 | 
						|
  connect(live_holdoff_timer,SIGNAL(timeout()),this,SLOT(holdoffData()));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
unsigned RDLiveWire::id() const
 | 
						|
{
 | 
						|
  return live_id;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
QString RDLiveWire::hostname() const
 | 
						|
{
 | 
						|
  return live_hostname;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Q_UINT16 RDLiveWire::tcpPort() const
 | 
						|
{
 | 
						|
  return live_tcp_port;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
unsigned RDLiveWire::baseOutput()
 | 
						|
{
 | 
						|
  return live_base_output;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::connectToHost(const QString &hostname,Q_UINT16 port,
 | 
						|
			       const QString &passwd,unsigned base_output)
 | 
						|
{
 | 
						|
  live_hostname=hostname;
 | 
						|
  live_tcp_port=port;
 | 
						|
  live_password=passwd;
 | 
						|
  live_base_output=base_output;
 | 
						|
  live_socket->connectToHost(hostname,port);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool RDLiveWire::loadSettings(const QString &hostname,Q_UINT16 port,
 | 
						|
			      const QString &passwd,unsigned base_output)
 | 
						|
{
 | 
						|
  int passes=50;
 | 
						|
 | 
						|
  live_load_ver_count=1;
 | 
						|
  connectToHost(hostname,port,passwd,base_output);
 | 
						|
  while(--passes>0) {
 | 
						|
    usleep(100000);
 | 
						|
    qApp->processEvents();
 | 
						|
    if(live_load_ver_count==0) {
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
QString RDLiveWire::deviceName() const
 | 
						|
{
 | 
						|
  return live_device_name;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
QString RDLiveWire::protocolVersion() const
 | 
						|
{
 | 
						|
  return live_protocol_version;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
QString RDLiveWire::systemVersion() const
 | 
						|
{
 | 
						|
  return live_system_version;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int RDLiveWire::sources() const
 | 
						|
{
 | 
						|
  return live_sources;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int RDLiveWire::destinations() const
 | 
						|
{
 | 
						|
  return live_destinations;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int RDLiveWire::channels() const
 | 
						|
{
 | 
						|
  return live_channels;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int RDLiveWire::gpis() const
 | 
						|
{
 | 
						|
  return live_gpis;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int RDLiveWire::gpos() const
 | 
						|
{
 | 
						|
  return live_gpos;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
unsigned RDLiveWire::gpiChannel(int slot,int line) const
 | 
						|
{
 | 
						|
  return live_gpi_channels[slot][line];
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
unsigned RDLiveWire::gpoChannel(int slot,int line) const
 | 
						|
{
 | 
						|
  return live_gpo_channels[slot][line];
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool RDLiveWire::gpiState(int slot,int line) const
 | 
						|
{
 | 
						|
  return live_gpi_states[slot][line];
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool RDLiveWire::gpoState(int slot,int line) const
 | 
						|
{
 | 
						|
  return live_gpo_states[slot][line];
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::gpiSet(int slot,int line,unsigned interval)
 | 
						|
{
 | 
						|
  QString cmd=QString().sprintf("GPI %d ",slot+1);
 | 
						|
  for(int i=0;i<RD_LIVEWIRE_GPIO_BUNDLE_SIZE;i++) {
 | 
						|
    if(i==line) {
 | 
						|
      cmd+="l";
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      if(live_gpi_states[slot][i]) {
 | 
						|
	cmd+="l";
 | 
						|
      }
 | 
						|
      else {
 | 
						|
	cmd+="h";
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  cmd+="\"";
 | 
						|
  SendCommand(cmd);
 | 
						|
  live_gpi_states[slot][line]=true;
 | 
						|
  if(interval>0) {
 | 
						|
    live_gpi_timers[slot*RD_LIVEWIRE_GPIO_BUNDLE_SIZE+line]->
 | 
						|
      start(interval,true);
 | 
						|
  }
 | 
						|
  emit gpiChanged(live_id,slot,line,true);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::gpiReset(int slot,int line,unsigned interval)
 | 
						|
{
 | 
						|
  QString cmd=QString().sprintf("GPI %d ",slot+1);
 | 
						|
  for(int i=0;i<RD_LIVEWIRE_GPIO_BUNDLE_SIZE;i++) {
 | 
						|
    if(i==line) {
 | 
						|
      cmd+="h";
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      if(live_gpi_states[slot][i]) {
 | 
						|
	cmd+="l";
 | 
						|
      }
 | 
						|
      else {
 | 
						|
	cmd+="h";
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  cmd+="\"";
 | 
						|
  SendCommand(cmd);
 | 
						|
  live_gpi_states[slot][line]=false;
 | 
						|
  if(interval>0) {
 | 
						|
    live_gpi_timers[slot*RD_LIVEWIRE_GPIO_BUNDLE_SIZE+line]->
 | 
						|
      start(interval,true);
 | 
						|
  }
 | 
						|
  emit gpiChanged(live_id,slot,line,false);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::gpoSet(int slot,int line,unsigned interval)
 | 
						|
{
 | 
						|
  QString cmd=QString().sprintf("GPO %d ",slot+1);
 | 
						|
  for(int i=0;i<RD_LIVEWIRE_GPIO_BUNDLE_SIZE;i++) {
 | 
						|
    if(i==line) {
 | 
						|
      cmd+="l";
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      if(live_gpo_states[slot][i]) {
 | 
						|
	cmd+="l";
 | 
						|
      }
 | 
						|
      else {
 | 
						|
	cmd+="h";
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  SendCommand(cmd);
 | 
						|
  live_gpo_states[slot][line]=true;
 | 
						|
  if(interval>0) {
 | 
						|
    live_gpo_timers[slot*RD_LIVEWIRE_GPIO_BUNDLE_SIZE+line]->
 | 
						|
      start(interval,true);
 | 
						|
  }
 | 
						|
  emit gpoChanged(live_id,slot,line,true);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::gpoReset(int slot,int line,unsigned interval)
 | 
						|
{
 | 
						|
  QString cmd=QString().sprintf("GPO %d ",slot+1);
 | 
						|
  for(int i=0;i<RD_LIVEWIRE_GPIO_BUNDLE_SIZE;i++) {
 | 
						|
    if(i==line) {
 | 
						|
      cmd+="h";
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      if(live_gpo_states[slot][i]) {
 | 
						|
	cmd+="l";
 | 
						|
      }
 | 
						|
      else {
 | 
						|
	cmd+="h";
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  SendCommand(cmd);
 | 
						|
  live_gpo_states[slot][line]=false;
 | 
						|
  if(interval>0) {
 | 
						|
    live_gpo_timers[slot*RD_LIVEWIRE_GPIO_BUNDLE_SIZE+line]->
 | 
						|
      start(interval,true);
 | 
						|
  }
 | 
						|
  emit gpoChanged(live_id,slot,line,false);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::setRoute(int src_num,int dest_slot) const
 | 
						|
{
 | 
						|
  QString str;
 | 
						|
  str=QString().sprintf("DST %d ADDR:\"239.192.%d.%d\"\r\n",
 | 
						|
			dest_slot+1,src_num/256,src_num%256);
 | 
						|
  SendCommand(str);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::connectedData()
 | 
						|
{
 | 
						|
  QString str="LOGIN";
 | 
						|
  if(!live_password.isEmpty()) {
 | 
						|
    str+=(" "+live_password);
 | 
						|
  }
 | 
						|
  SendCommand(str);
 | 
						|
  SendCommand("VER");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::connectionClosedData()
 | 
						|
{
 | 
						|
  if(!live_watchdog_state) {
 | 
						|
    live_watchdog_state=true;
 | 
						|
    int holdoff=GetHoldoff();
 | 
						|
    emit watchdogStateChanged(live_id,QString().sprintf(
 | 
						|
       "Connection to LiveWire node at %s:%d closed, attempting reconnect, holdoff = %d mS",
 | 
						|
       (const char *)live_hostname,live_tcp_port,holdoff));
 | 
						|
    live_holdoff_timer->start(holdoff,true);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::readyReadData()
 | 
						|
{
 | 
						|
  char buf[RD_LIVEWIRE_MAX_CMD_LENGTH];
 | 
						|
 | 
						|
  int n;
 | 
						|
 | 
						|
  while((n=live_socket->readBlock(buf,RD_LIVEWIRE_MAX_CMD_LENGTH))>0) {
 | 
						|
    buf[n]=0;
 | 
						|
    for(int i=0;i<n;i++) {
 | 
						|
      if(buf[i]=='\n') {
 | 
						|
	live_buf[live_ptr]=0;
 | 
						|
	DespatchCommand(live_buf);
 | 
						|
	live_ptr=0;
 | 
						|
      }
 | 
						|
      else {
 | 
						|
	if(buf[i]!='\r') {
 | 
						|
	  live_buf[live_ptr++]=buf[i];
 | 
						|
	}
 | 
						|
      }
 | 
						|
      if(live_ptr>=RD_LIVEWIRE_MAX_CMD_LENGTH) {
 | 
						|
	fprintf(stderr,"LiveWire: status string truncated");
 | 
						|
	live_ptr=0;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::errorData(int err)
 | 
						|
{
 | 
						|
  int interval=RDLIVEWIRE_RECONNECT_MIN_INTERVAL;
 | 
						|
 | 
						|
  switch((Q3Socket::Error)err) {
 | 
						|
      case Q3Socket::ErrConnectionRefused:
 | 
						|
	live_watchdog_state=true;
 | 
						|
	interval=GetHoldoff();
 | 
						|
	emit watchdogStateChanged(live_id,QString().sprintf(
 | 
						|
	 "Connection to LiveWire node at %s:%d refused, attempting reconnect, holdoff = %d mS",
 | 
						|
				  (const char *)live_hostname,
 | 
						|
				  live_tcp_port,interval));
 | 
						|
	live_holdoff_timer->start(interval,true);
 | 
						|
	break;
 | 
						|
 | 
						|
      case Q3Socket::ErrHostNotFound:
 | 
						|
	emit watchdogStateChanged(live_id,QString().sprintf(
 | 
						|
	  "Error on connection to LiveWire node at %s:%d: Host Not Found",
 | 
						|
				  (const char *)live_hostname,
 | 
						|
				  live_tcp_port));
 | 
						|
	break;
 | 
						|
 | 
						|
      case Q3Socket::ErrSocketRead:
 | 
						|
	emit watchdogStateChanged(live_id,QString().sprintf(
 | 
						|
	  "Error on connection to LiveWire node at %s:%d: Socket Read Error",
 | 
						|
				  (const char *)live_hostname,
 | 
						|
				  live_tcp_port));
 | 
						|
	break;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::gpiTimeoutData(int id)
 | 
						|
{
 | 
						|
  int chan=id/RD_LIVEWIRE_GPIO_BUNDLE_SIZE;
 | 
						|
  int line=id%RD_LIVEWIRE_GPIO_BUNDLE_SIZE;
 | 
						|
 | 
						|
  QString cmd=QString().sprintf("GPI %d ",chan+1);
 | 
						|
  for(int i=0;i<RD_LIVEWIRE_GPIO_BUNDLE_SIZE;i++) {
 | 
						|
    if(i==line) {
 | 
						|
      if(live_gpi_states[chan][i]) {
 | 
						|
	cmd+="h";
 | 
						|
      }
 | 
						|
      else {
 | 
						|
	cmd+="l";
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      if(live_gpi_states[chan][i]) {
 | 
						|
	cmd+="l";
 | 
						|
      }
 | 
						|
      else {
 | 
						|
	cmd+="h";
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  cmd+="\"";
 | 
						|
  SendCommand(cmd);
 | 
						|
  live_gpi_states[chan][line]=!live_gpi_states[chan][line];
 | 
						|
  emit gpiChanged(live_id,chan,line,live_gpi_states[chan][line]);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::gpoTimeoutData(int id)
 | 
						|
{
 | 
						|
  int chan=id/RD_LIVEWIRE_GPIO_BUNDLE_SIZE;
 | 
						|
  int line=id%RD_LIVEWIRE_GPIO_BUNDLE_SIZE;
 | 
						|
 | 
						|
  QString cmd=QString().sprintf("GPO %d ",chan+1);
 | 
						|
  for(int i=0;i<RD_LIVEWIRE_GPIO_BUNDLE_SIZE;i++) {
 | 
						|
    if(i==line) {
 | 
						|
      if(live_gpo_states[chan][i]) {
 | 
						|
	cmd+="h";
 | 
						|
      }
 | 
						|
      else {
 | 
						|
	cmd+="l";
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      if(live_gpo_states[chan][i]) {
 | 
						|
	cmd+="l";
 | 
						|
      }
 | 
						|
      else {
 | 
						|
	cmd+="h";
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  SendCommand(cmd);
 | 
						|
  live_gpo_states[chan][line]=!live_gpo_states[chan][line];
 | 
						|
  emit gpoChanged(live_id,chan,line,live_gpo_states[chan][line]);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::watchdogData()
 | 
						|
{
 | 
						|
  SendCommand("VER");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::watchdogTimeoutData()
 | 
						|
{
 | 
						|
  live_watchdog_state=true;
 | 
						|
  live_connected=false;
 | 
						|
  live_gpi_initialized=false;
 | 
						|
  live_gpo_initialized=false;
 | 
						|
  int holdoff=GetHoldoff();
 | 
						|
  emit watchdogStateChanged(live_id,QString().sprintf(
 | 
						|
	 "Connection to LiveWire node at %s:%d lost, attempting reconnect, holdoff = %d mS",
 | 
						|
	 (const char *)live_hostname,live_tcp_port,holdoff));
 | 
						|
  live_holdoff_timer->start(holdoff,true);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::holdoffData()
 | 
						|
{
 | 
						|
  ResetConnection();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::resetConnectionData()
 | 
						|
{
 | 
						|
  live_socket->close();
 | 
						|
  connectToHost(live_hostname,live_tcp_port,live_password,live_base_output);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::DespatchCommand(const QString &cmd)
 | 
						|
{
 | 
						|
  int offset=cmd.find(" ");
 | 
						|
  QString opcode=cmd.left(offset);
 | 
						|
  QString str;
 | 
						|
  if(opcode=="VER") {
 | 
						|
    ReadVersion(cmd.right(cmd.length()-offset-1));
 | 
						|
  }
 | 
						|
    
 | 
						|
  if(opcode=="SET") {
 | 
						|
  }
 | 
						|
 | 
						|
  if(opcode=="SRC") {
 | 
						|
    ReadSources(cmd.right(cmd.length()-offset-1));
 | 
						|
  }
 | 
						|
 | 
						|
  if(opcode=="DST") {
 | 
						|
    ReadDestinations(cmd.right(cmd.length()-offset-1));
 | 
						|
  }
 | 
						|
 | 
						|
  if(opcode=="GPO") {
 | 
						|
    ReadGpos(cmd.right(cmd.length()-offset-1));
 | 
						|
  }
 | 
						|
 | 
						|
  if(opcode=="GPI") {
 | 
						|
    ReadGpis(cmd.right(cmd.length()-offset-1));
 | 
						|
  }
 | 
						|
 | 
						|
  if(opcode=="CFG") {
 | 
						|
    str=cmd.right(cmd.length()-offset-1);
 | 
						|
    offset=str.find(" ");
 | 
						|
    if(str.left(offset)=="GPO") {
 | 
						|
      ReadGpioConfig(str.right(str.length()-offset-1));
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::SendCommand(const QString &cmd) const
 | 
						|
{
 | 
						|
  live_socket->writeBlock((cmd+"\r\n").ascii(),cmd.length()+2);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::ReadVersion(const QString &cmd)
 | 
						|
{
 | 
						|
  QStringList f0;
 | 
						|
  QStringList f1;
 | 
						|
 | 
						|
  if(!live_connected) {
 | 
						|
    f0=AString(cmd).split(" ","\"");
 | 
						|
    for(int i=0;i<f0.size();i++) {
 | 
						|
      f1=f1.split(":",f0[i]);
 | 
						|
      if(f1.size()==2) {
 | 
						|
	if(f1[0]=="LWRP") {
 | 
						|
	  live_protocol_version=f1[1];
 | 
						|
	}
 | 
						|
	if(f1[0]=="DEVN") {
 | 
						|
	  live_device_name=f1[1];
 | 
						|
	}
 | 
						|
	if(f1[0]=="SYSV") {
 | 
						|
	  live_system_version=f1[1];
 | 
						|
	}
 | 
						|
	if(f1[0]=="NSRC") {
 | 
						|
	  int delimiter=f1[1].find("/");
 | 
						|
	  if(delimiter<0) {
 | 
						|
	    live_sources=f1[1].toInt();
 | 
						|
	  }
 | 
						|
	  else {
 | 
						|
	    live_sources=f1[1].left(delimiter).toInt();
 | 
						|
	    live_channels=f1[1].right(f1[1].length()-delimiter-1).toInt();
 | 
						|
	  }
 | 
						|
	  if(live_sources>0) {
 | 
						|
	    SendCommand("SRC");
 | 
						|
	  }
 | 
						|
	}
 | 
						|
	if(f1[0]=="NDST") {
 | 
						|
	  int delimiter=f1[1].find("/");
 | 
						|
	  if(delimiter<0) {
 | 
						|
	    live_destinations=f1[1].toInt();
 | 
						|
	  }
 | 
						|
	  else {
 | 
						|
	    live_destinations=f1[1].left(delimiter).toInt();
 | 
						|
	    live_channels=f1[1].right(f1[1].length()-delimiter-1).toInt();
 | 
						|
	  }
 | 
						|
	  if(live_destinations>0) {
 | 
						|
	    SendCommand("DST");
 | 
						|
	  }
 | 
						|
	}
 | 
						|
	if(f1[0]=="NGPI") {
 | 
						|
	  live_gpis=f1[1].toInt();
 | 
						|
	  QSignalMapper *mapper=new QSignalMapper(this,"gpi_mapper");
 | 
						|
	  connect(mapper,SIGNAL(mapped(int)),this,SLOT(gpiTimeoutData(int)));
 | 
						|
	  for(int i=0;i<live_gpis;i++) {
 | 
						|
	    live_gpi_states.push_back(new bool[RD_LIVEWIRE_GPIO_BUNDLE_SIZE]);
 | 
						|
	    live_gpi_channels.
 | 
						|
	      push_back(new unsigned[RD_LIVEWIRE_GPIO_BUNDLE_SIZE]);
 | 
						|
	    for(int j=0;j<RD_LIVEWIRE_GPIO_BUNDLE_SIZE;j++) {
 | 
						|
	      live_gpi_states.back()[j]=false;
 | 
						|
	      live_gpi_channels.back()[j]=i*RD_LIVEWIRE_GPIO_BUNDLE_SIZE+j;
 | 
						|
	      live_gpi_timers.push_back(new QTimer(this));
 | 
						|
	      mapper->setMapping(live_gpi_timers.back(),
 | 
						|
				 i*RD_LIVEWIRE_GPIO_BUNDLE_SIZE+j);
 | 
						|
	      connect(live_gpi_timers.back(),SIGNAL(timeout()),mapper,SLOT(map()));
 | 
						|
	    }	
 | 
						|
	  }
 | 
						|
	  if(!live_gpi_initialized) {
 | 
						|
	    if(live_gpis>0) {
 | 
						|
	      SendCommand("ADD GPI");
 | 
						|
	    }
 | 
						|
	    live_gpi_initialized=true;
 | 
						|
	  }
 | 
						|
	}
 | 
						|
	if(f1[0]=="NGPO") {
 | 
						|
	  live_gpos=f1[1].toInt();
 | 
						|
	  QSignalMapper *mapper=new QSignalMapper(this,"gpo_mapper");
 | 
						|
	  connect(mapper,SIGNAL(mapped(int)),this,SLOT(gpoTimeoutData(int)));
 | 
						|
	  for(int i=0;i<live_gpos;i++) {
 | 
						|
	    live_gpo_states.push_back(new bool[RD_LIVEWIRE_GPIO_BUNDLE_SIZE]);
 | 
						|
	    live_gpo_channels.
 | 
						|
	      push_back(new unsigned[RD_LIVEWIRE_GPIO_BUNDLE_SIZE]);
 | 
						|
	    for(int j=0;j<RD_LIVEWIRE_GPIO_BUNDLE_SIZE;j++) {
 | 
						|
	      live_gpo_states.back()[j]=false;
 | 
						|
	      live_gpo_channels.back()[j]=i*RD_LIVEWIRE_GPIO_BUNDLE_SIZE+j;
 | 
						|
	      live_gpo_timers.push_back(new QTimer(this));
 | 
						|
	      mapper->setMapping(live_gpo_timers.back(),
 | 
						|
				 i*RD_LIVEWIRE_GPIO_BUNDLE_SIZE+j);
 | 
						|
	      connect(live_gpo_timers.back(),SIGNAL(timeout()),mapper,SLOT(map()));
 | 
						|
	    }
 | 
						|
	  }
 | 
						|
	  if(!live_gpo_initialized) {
 | 
						|
	    if(live_gpos>0) {
 | 
						|
	      SendCommand("CFG GPO");
 | 
						|
	      SendCommand("ADD GPO");
 | 
						|
	    }
 | 
						|
	    live_gpo_initialized=true;
 | 
						|
	  }
 | 
						|
	}
 | 
						|
      }
 | 
						|
    }
 | 
						|
    live_connected=true;
 | 
						|
    emit connected(live_id);
 | 
						|
  }
 | 
						|
  if(live_load_ver_count>0) {
 | 
						|
    live_load_ver_count--;
 | 
						|
  }
 | 
						|
  if(live_watchdog_state) {
 | 
						|
    live_watchdog_state=false;
 | 
						|
    emit watchdogStateChanged(live_id,QString().sprintf(
 | 
						|
	    "Connection to LiveWire node at %s:%d restored",
 | 
						|
	 (const char *)live_hostname,live_tcp_port));
 | 
						|
  }
 | 
						|
  live_watchdog_timer->start(RDLIVEWIRE_WATCHDOG_INTERVAL,true);
 | 
						|
  live_watchdog_timeout_timer->stop();
 | 
						|
  live_watchdog_timeout_timer->start(RDLIVEWIRE_WATCHDOG_TIMEOUT,true);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::ReadSources(const QString &cmd)
 | 
						|
{
 | 
						|
  QHostAddress addr;
 | 
						|
  QStringList f1;
 | 
						|
  RDLiveWireSource *src=new RDLiveWireSource();
 | 
						|
  QStringList f0=AString(cmd).split(" ","\"");
 | 
						|
  src->setSlotNumber(f0[0].toInt());
 | 
						|
  for(int i=1;i<f0.size();i++) {
 | 
						|
    f1=f1.split(":",f0[i]);
 | 
						|
    if(f1.size()==2) {
 | 
						|
      if(f1[0]=="PSNM") {
 | 
						|
	src->setPrimaryName(f1[1]);
 | 
						|
      }
 | 
						|
      if(f1[0]=="LABL") {
 | 
						|
	src->setLabelName(f1[1]);
 | 
						|
      }
 | 
						|
      if(f1[0]=="FASM") {
 | 
						|
	// ????
 | 
						|
      }
 | 
						|
      if(f1[0]=="RTPE") {
 | 
						|
	src->setRtpEnabled(f1[1].toInt());
 | 
						|
      }
 | 
						|
      if(f1[0]=="RTPA") {
 | 
						|
	addr.setAddress(f1[1]);
 | 
						|
	src->setStreamAddress(addr);
 | 
						|
      }
 | 
						|
      if(f1[0]=="INGN") {
 | 
						|
	src->setInputGain(f1[1].toInt());
 | 
						|
      }
 | 
						|
      if(f1[0]=="SHAB") {
 | 
						|
	src->setShareable(f1[1].toInt());
 | 
						|
      }
 | 
						|
      if(f1[0]=="NCHN") {
 | 
						|
	src->setChannels(f1[1].toInt());
 | 
						|
      }
 | 
						|
      if(f1[0]=="RTPP") {
 | 
						|
	// ????
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  emit sourceChanged(live_id,src);
 | 
						|
  delete src;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::ReadDestinations(const QString &cmd)
 | 
						|
{
 | 
						|
  QHostAddress addr;
 | 
						|
  QStringList f1;
 | 
						|
  RDLiveWireDestination *dst=new RDLiveWireDestination();
 | 
						|
  QStringList f0=AString(cmd).split(" ","\"");
 | 
						|
  dst->setSlotNumber(f0[0].toInt());
 | 
						|
  for(int i=1;i<f0.size();i++) {
 | 
						|
    f1=f1.split(":",f0[i]);
 | 
						|
    if(f1.size()==2) {
 | 
						|
      if(f1[0]=="NAME") {
 | 
						|
	dst->setPrimaryName(f1[1]);
 | 
						|
      }
 | 
						|
      if(f1[0]=="ADDR") {
 | 
						|
	addr.setAddress(f1[1]);
 | 
						|
	dst->setStreamAddress(addr);
 | 
						|
      }
 | 
						|
      if(f1[0]=="NCHN") {
 | 
						|
	dst->setChannels(f1[1].toInt());
 | 
						|
      }
 | 
						|
      if(f1[0]=="LOAD") {
 | 
						|
	dst->setOutputGain((RDLiveWireDestination::Load)f1[1].toInt());
 | 
						|
      }
 | 
						|
      if(f1[0]=="OUGN") {
 | 
						|
	dst->setOutputGain(f1[1].toInt());
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  emit destinationChanged(live_id,dst);
 | 
						|
  delete dst;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::ReadGpis(const QString &cmd)
 | 
						|
{
 | 
						|
  //
 | 
						|
  // FIXME: This is currently emitting the relative slot number, which is 
 | 
						|
  //        wrong.  How do we get the associated source number?
 | 
						|
  //
 | 
						|
 | 
						|
//  printf("GPI: %s\n",(const char *)cmd);
 | 
						|
 | 
						|
  int offset=cmd.find(" ");
 | 
						|
  int slot=cmd.left(offset).toInt()-1;
 | 
						|
  QString str=cmd.right(cmd.length()-offset-1).lower();
 | 
						|
  for(int i=0;i<RD_LIVEWIRE_GPIO_BUNDLE_SIZE;i++) {
 | 
						|
    if((str[i]=='h')&&live_gpi_states[slot][i]) {
 | 
						|
      live_gpi_states[slot][i]=false;
 | 
						|
      emit gpiChanged(live_id,slot,i,false);
 | 
						|
    }
 | 
						|
    if((str[i]=='l')&&(!live_gpi_states[slot][i])) {
 | 
						|
      live_gpi_states[slot][i]=true;
 | 
						|
      emit gpiChanged(live_id,slot,i,true);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::ReadGpos(const QString &cmd)
 | 
						|
{
 | 
						|
  //
 | 
						|
  // FIXME: This is currently emitting the relative slot number, which is 
 | 
						|
  //        wrong.  How do we get the associated source number?
 | 
						|
  //
 | 
						|
 | 
						|
//  printf("GPO: %s\n",(const char *)cmd);
 | 
						|
 | 
						|
  int offset=cmd.find(" ");
 | 
						|
  int slot=cmd.left(offset).toInt()-1;
 | 
						|
  QString str=cmd.right(cmd.length()-offset-1).lower();
 | 
						|
  for(int i=0;i<RD_LIVEWIRE_GPIO_BUNDLE_SIZE;i++) {
 | 
						|
    if((str.mid(i,1)=="h")&&live_gpo_states[slot][i]) {
 | 
						|
      live_gpo_states[slot][i]=false;
 | 
						|
      emit gpoChanged(live_id,slot,i,false);
 | 
						|
    }
 | 
						|
      if((str.mid(i,1)=="l")&&(!live_gpo_states[slot][i])) {
 | 
						|
      live_gpo_states[slot][i]=true;
 | 
						|
      emit gpoChanged(live_id,slot,i,true);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::ReadGpioConfig(const QString &cmd)
 | 
						|
{
 | 
						|
  QStringList f0;
 | 
						|
  QStringList f1;
 | 
						|
 | 
						|
  f0=AString(cmd).split(" ","\"");
 | 
						|
  int slot=f0[0].toInt()-1;
 | 
						|
  for(int i=1;i<f0.size();i++) {
 | 
						|
    f1=f1.split(":",f0[i]);
 | 
						|
    if(f1.size()==2) {
 | 
						|
      if(f1[0]=="SRCA") {
 | 
						|
	int chan=PruneUrl(f1[1]).toInt();
 | 
						|
	for(unsigned i=0;i<RD_LIVEWIRE_GPIO_BUNDLE_SIZE;i++) {
 | 
						|
	  live_gpi_channels[slot][i]=chan*RD_LIVEWIRE_GPIO_BUNDLE_SIZE+i;
 | 
						|
	  live_gpo_channels[slot][i]=chan*RD_LIVEWIRE_GPIO_BUNDLE_SIZE+i;
 | 
						|
	  emit gpoConfigChanged(live_id,slot,live_gpo_channels[slot][i]);
 | 
						|
	}
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
QString RDLiveWire::PruneUrl(const QString &str)
 | 
						|
{
 | 
						|
  QString ret=str;
 | 
						|
  int offset=str.find("<");
 | 
						|
  if(offset>=0) {
 | 
						|
    ret=str.left(offset);
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void RDLiveWire::ResetConnection()
 | 
						|
{
 | 
						|
  live_socket->close();
 | 
						|
  connectToHost(live_hostname,live_tcp_port,live_password,live_base_output);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int RDLiveWire::GetHoldoff()
 | 
						|
{
 | 
						|
  return (int)(RDLIVEWIRE_RECONNECT_MIN_INTERVAL+
 | 
						|
	       (RDLIVEWIRE_RECONNECT_MAX_INTERVAL-
 | 
						|
		RDLIVEWIRE_RECONNECT_MIN_INTERVAL)*
 | 
						|
	       (double)random()/(double)RAND_MAX);
 | 
						|
}
 |