From 32714fb6f77e9812d6cdaf408a5c6bec1abcce6a Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Sat, 16 Jun 2018 13:39:03 +0000 Subject: [PATCH 1/3] 2018-06-16 Fred Gleason * Added a 'TranscodingDelay=' parameter to the '[Tuning]' section of rd.conf(5). --- ChangeLog | 3 +++ conf/rd.conf-sample | 4 ++++ lib/rdaudioconvert.cpp | 16 +++++++++++++--- lib/rdaudioconvert.h | 4 +++- lib/rdconfig.cpp | 8 ++++++++ lib/rdconfig.h | 2 ++ lib/rdfeed.cpp | 2 +- lib/rdrenderer.cpp | 2 +- rdcatchd/batch.cpp | 4 ++-- rdrepld/citadelxds.cpp | 2 +- tests/audio_convert_test.cpp | 2 +- utils/rdconvert/rdconvert.cpp | 2 +- web/rdxport/export.cpp | 2 +- web/rdxport/import.cpp | 2 +- 14 files changed, 42 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index e4848da4..c0c38088 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16656,3 +16656,6 @@ 2018-05-08 Fred Gleason * Updated 'NEWS'. * Incremented the package version to 2.19.2int01. +2018-06-16 Fred Gleason + * Added a 'TranscodingDelay=' parameter to the '[Tuning]' section + of rd.conf(5). diff --git a/conf/rd.conf-sample b/conf/rd.conf-sample index 1855cdad..cc133119 100644 --- a/conf/rd.conf-sample +++ b/conf/rd.conf-sample @@ -130,6 +130,10 @@ ChannelsPerPcm=-1 UseRealtime=Yes RealtimePriority=9 +; Introduce a delay of this many microseconds in each loop iteration +; when transcoding files. +TranscodingDelay=0 + [Format] ; This value is used when testing and developing new features in the ; audio drivers. It should never be altered on a production system. diff --git a/lib/rdaudioconvert.cpp b/lib/rdaudioconvert.cpp index 5da0db17..3a10ad3e 100644 --- a/lib/rdaudioconvert.cpp +++ b/lib/rdaudioconvert.cpp @@ -58,9 +58,10 @@ #define STAGE2_XFER_SIZE 2048 #define STAGE2_BUFFER_SIZE 49152 -RDAudioConvert::RDAudioConvert(const QString &station_name,QObject *parent) +RDAudioConvert::RDAudioConvert(RDConfig *config,QObject *parent) : QObject(parent) { + conv_config=config; conv_start_point=-1; conv_end_point=-1; conv_speed_ratio=1.0; @@ -68,7 +69,7 @@ RDAudioConvert::RDAudioConvert(const QString &station_name,QObject *parent) conv_settings=NULL; conv_src_wavedata=new RDWaveData(); conv_dst_wavedata=NULL; - RDLibraryConf *conf=new RDLibraryConf(station_name,0); + RDLibraryConf *conf=new RDLibraryConf(config->stationName(),0); conv_src_converter=conf->srcConverter(); delete conf; @@ -658,7 +659,7 @@ RDAudioConvert::ErrorCode RDAudioConvert::Stage1Mpeg(const QString &dstfile, return RDAudioConvert::ErrorFormatError; } memmove(buffer,mad_stream.next_frame,left_over); - + usleep(conv_config->transcodingDelay()); } memset(buffer+left_over,0,MAD_BUFFER_GUARD); mad_stream_buffer(&mad_stream,buffer,MAD_BUFFER_GUARD+left_over); @@ -888,6 +889,7 @@ RDAudioConvert::ErrorCode RDAudioConvert::Stage1SndFile(const QString &dstfile, if((end-start)transcodingDelay()); } delete buffer; sf_close(sf_dst); @@ -1076,6 +1078,7 @@ RDAudioConvert::ErrorCode RDAudioConvert::Stage2Convert(const QString &srcfile, sf_close(dst_sf); return RDAudioConvert::ErrorNoSpace; } + usleep(conv_config->transcodingDelay()); } // @@ -1099,6 +1102,7 @@ RDAudioConvert::ErrorCode RDAudioConvert::Stage2Convert(const QString &srcfile, sf_close(dst_sf); return RDAudioConvert::ErrorNoSpace; } + usleep(conv_config->transcodingDelay()); } delete st_conv; } @@ -1511,6 +1515,7 @@ RDAudioConvert::ErrorCode RDAudioConvert::Stage3Layer3(SNDFILE *src_sf, return RDAudioConvert::ErrorNoSpace; } } + usleep(conv_config->transcodingDelay()); } } else { @@ -1521,6 +1526,7 @@ RDAudioConvert::ErrorCode RDAudioConvert::Stage3Layer3(SNDFILE *src_sf, ::close(dst_fd); return RDAudioConvert::ErrorNoSpace; } + usleep(conv_config->transcodingDelay()); } } } @@ -1650,6 +1656,7 @@ RDAudioConvert::ErrorCode RDAudioConvert::Stage3Layer2Wav(SNDFILE *src_sf, else { fprintf(stderr,"TwoLAME encode error\n"); } + usleep(conv_config->transcodingDelay()); } if((s=twolame_encode_flush(lameopts,mpeg,2048))>=0) { if(wave->writeWave(mpeg,s)!=s) { @@ -1752,6 +1759,7 @@ RDAudioConvert::ErrorCode RDAudioConvert::Stage3Layer2(SNDFILE *src_sf, else { fprintf(stderr,"TwoLAME encode error\n"); } + usleep(conv_config->transcodingDelay()); } if((s=twolame_encode_flush(lameopts,mpeg,2048))>=0) { if(write(dst_fd,mpeg,s)!=s) { @@ -1818,6 +1826,7 @@ RDAudioConvert::ErrorCode RDAudioConvert::Stage3Pcm16(SNDFILE *src_sf, delete wave; return RDAudioConvert::ErrorNoSpace; } + usleep(conv_config->transcodingDelay()); } delete sf_buffer; wave->closeWave(); @@ -1867,6 +1876,7 @@ RDAudioConvert::ErrorCode RDAudioConvert::Stage3Pcm24(SNDFILE *src_sf, delete wave; return RDAudioConvert::ErrorNoSpace; } + usleep(conv_config->transcodingDelay()); } delete sf_buffer; delete pcm24; diff --git a/lib/rdaudioconvert.h b/lib/rdaudioconvert.h index bba529ed..b66f9b9d 100644 --- a/lib/rdaudioconvert.h +++ b/lib/rdaudioconvert.h @@ -36,6 +36,7 @@ #include +#include "rdconfig.h" #include "rdsettings.h" #include "rdwavedata.h" #include "rdwavefile.h" @@ -48,7 +49,7 @@ class RDAudioConvert : public QObject ErrorNoDestination=3,ErrorInvalidSource=4,ErrorInternal=5, ErrorFormatNotSupported=6,ErrorNoDisc=7,ErrorNoTrack=8, ErrorInvalidSpeed=9,ErrorFormatError=10,ErrorNoSpace=11}; - RDAudioConvert(const QString &station_name,QObject *parent=0); + RDAudioConvert(RDConfig *config,QObject *parent=0); ~RDAudioConvert(); void setSourceFile(const QString &filename); void setDestinationFile(const QString &filename); @@ -117,6 +118,7 @@ class RDAudioConvert : public QObject void *conv_mad_handle; void *conv_lame_handle; void *conv_twolame_handle; + RDConfig *conv_config; #ifdef HAVE_MAD void (*mad_stream_init)(struct mad_stream *); void (*mad_frame_init)(struct mad_frame *); diff --git a/lib/rdconfig.cpp b/lib/rdconfig.cpp index 35f32682..10448807 100644 --- a/lib/rdconfig.cpp +++ b/lib/rdconfig.cpp @@ -467,6 +467,12 @@ int RDConfig::realtimePriority() return conf_realtime_priority; } + +int RDConfig::transcodingDelay() const +{ + return conf_transcoding_delay; +} + // Don't use this method in application code, use RDTempDirectory() QString RDConfig::tempDirectory() { @@ -633,6 +639,7 @@ void RDConfig::load() conf_enable_mixer_logging=profile->boolValue("Caed","EnableMixerLogging"); conf_use_realtime=profile->boolValue("Tuning","UseRealtime",false); conf_realtime_priority=profile->intValue("Tuning","RealtimePriority",9); + conf_transcoding_delay=profile->intValue("Tuning","TranscodingDelay"); conf_temp_directory=profile->stringValue("Tuning","TempDirectory",""); conf_sas_station=profile->stringValue("SASFilter","Station",""); conf_sas_matrix=profile->intValue("SASFilter","Matrix",0); @@ -743,6 +750,7 @@ void RDConfig::clear() conf_enable_mixer_logging=false; conf_use_realtime=false; conf_realtime_priority=9; + conf_transcoding_delay=0; conf_temp_directory=""; conf_sas_station=""; conf_sas_matrix=-1; diff --git a/lib/rdconfig.h b/lib/rdconfig.h index 5f32238e..fdda95b2 100644 --- a/lib/rdconfig.h +++ b/lib/rdconfig.h @@ -110,6 +110,7 @@ class RDConfig #endif bool useRealtime(); int realtimePriority(); + int transcodingDelay() const; QString tempDirectory(); QString sasStation() const; int sasMatrix() const; @@ -177,6 +178,7 @@ class RDConfig QString conf_cae_logfile; bool conf_enable_mixer_logging; bool conf_use_realtime; + int conf_transcoding_delay; int conf_realtime_priority; QString conf_temp_directory; QString conf_sas_station; diff --git a/lib/rdfeed.cpp b/lib/rdfeed.cpp index 61e85626..19e4cf2b 100644 --- a/lib/rdfeed.cpp +++ b/lib/rdfeed.cpp @@ -660,7 +660,7 @@ unsigned RDFeed::postFile(RDStation *station,const QString &srcfile,Error *err, // Convert Cut // tmpfile=GetTempFilename(); - RDAudioConvert *conv=new RDAudioConvert(station->name(),this); + RDAudioConvert *conv=new RDAudioConvert(feed_config,this); conv->setSourceFile(srcfile); conv->setDestinationFile(tmpfile); RDSettings *settings=new RDSettings(); diff --git a/lib/rdrenderer.cpp b/lib/rdrenderer.cpp index 39cb7e18..227e533b 100644 --- a/lib/rdrenderer.cpp +++ b/lib/rdrenderer.cpp @@ -586,7 +586,7 @@ bool RDRenderer::ConvertAudio(const QString &srcfile,const QString &dstfile, { RDAudioConvert::ErrorCode err_code; - RDAudioConvert *conv=new RDAudioConvert(render_station->name(),this); + RDAudioConvert *conv=new RDAudioConvert(render_config,this); conv->setSourceFile(srcfile); conv->setDestinationFile(dstfile); conv->setDestinationSettings(s); diff --git a/rdcatchd/batch.cpp b/rdcatchd/batch.cpp index 7daae048..aca8b6b3 100644 --- a/rdcatchd/batch.cpp +++ b/rdcatchd/batch.cpp @@ -400,7 +400,7 @@ bool MainObject::Export(CatchEvent *evt) return false; } RDCart *cart=new RDCart(cut->cartNumber()); - RDAudioConvert *conv=new RDAudioConvert(catch_config->stationName(),this); + RDAudioConvert *conv=new RDAudioConvert(catch_config,this); conv->setSourceFile(RDCut::pathName(evt->cutName())); conv->setRange(cut->startPoint(),cut->endPoint()); conv->setDestinationFile(RDEscapeString(evt->tempName())); @@ -472,7 +472,7 @@ bool MainObject::Import(CatchEvent *evt) unsigned msecs=wave->getExtTimeLength(); delete wave; RDCart *cart=new RDCart(cut->cartNumber()); - RDAudioConvert *conv=new RDAudioConvert(catch_config->stationName(),this); + RDAudioConvert *conv=new RDAudioConvert(catch_config,this); conv->setSourceFile(RDEscapeString(evt->tempName())); conv->setDestinationFile(RDCut::pathName(evt->cutName())); RDSettings *settings=new RDSettings(); diff --git a/rdrepld/citadelxds.cpp b/rdrepld/citadelxds.cpp index 8078123c..4c2eef43 100644 --- a/rdrepld/citadelxds.cpp +++ b/rdrepld/citadelxds.cpp @@ -347,7 +347,7 @@ bool CitadelXds::PostCut(const QString &cutname,const QString &filename) } RDSettings *settings=new RDSettings(); QString tempfile=RDTempDirectory::basePath()+"/"+filename; - RDAudioConvert *conv=new RDAudioConvert(rdconfig->stationName()); + RDAudioConvert *conv=new RDAudioConvert(rdconfig); conv->setSourceFile(RDCut::pathName(cutname)); conv->setDestinationFile(tempfile); conv->setRange(cut->startPoint(),cut->endPoint()); diff --git a/tests/audio_convert_test.cpp b/tests/audio_convert_test.cpp index 63a6269c..72dab668 100644 --- a/tests/audio_convert_test.cpp +++ b/tests/audio_convert_test.cpp @@ -179,7 +179,7 @@ MainObject::MainObject(QObject *parent) exit(256); } - RDAudioConvert *conv=new RDAudioConvert(rdconfig->stationName(),this); + RDAudioConvert *conv=new RDAudioConvert(rdconfig,this); conv->setSourceFile(source_filename); conv->setDestinationFile(destination_filename); conv->setDestinationSettings(destination_settings); diff --git a/utils/rdconvert/rdconvert.cpp b/utils/rdconvert/rdconvert.cpp index b87f61e2..c3c0ecc9 100644 --- a/utils/rdconvert/rdconvert.cpp +++ b/utils/rdconvert/rdconvert.cpp @@ -186,7 +186,7 @@ MainObject::MainObject(QObject *parent) exit(256); } - RDAudioConvert *conv=new RDAudioConvert(rdconfig->stationName(),this); + RDAudioConvert *conv=new RDAudioConvert(rdconfig,this); conv->setSourceFile(source_filename); conv->setDestinationFile(destination_filename); conv->setDestinationSettings(destination_settings); diff --git a/web/rdxport/export.cpp b/web/rdxport/export.cpp index 85c496f1..cc8032e7 100644 --- a/web/rdxport/export.cpp +++ b/web/rdxport/export.cpp @@ -145,7 +145,7 @@ void Xport::Export() XmlExit("unable to create temporary directory ["+err_msg+"]",500); } QString tmpfile=tempdir->path()+"/exported_audio"; - RDAudioConvert *conv=new RDAudioConvert(xport_config->stationName()); + RDAudioConvert *conv=new RDAudioConvert(xport_config); conv->setSourceFile(RDCut::pathName(cartnum,cutnum)); conv->setDestinationFile(tmpfile); conv->setDestinationSettings(settings); diff --git a/web/rdxport/import.cpp b/web/rdxport/import.cpp index f13442a6..7133c11e 100644 --- a/web/rdxport/import.cpp +++ b/web/rdxport/import.cpp @@ -200,7 +200,7 @@ void Xport::Import() XmlExit("Duplicate Cart Title Not Allowed",404,"import.cpp",LINE_NUMBER); } } - RDAudioConvert *conv=new RDAudioConvert(xport_config->stationName()); + RDAudioConvert *conv=new RDAudioConvert(xport_config); conv->setSourceFile(filename); conv->setDestinationFile(RDCut::pathName(cartnum,cutnum)); conv->setDestinationSettings(settings); From 8f2fbcab9ff074b00dc975e322e00178d252f9fa Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Tue, 21 Aug 2018 18:37:20 +0000 Subject: [PATCH 2/3] 2018-06-21 Fred Gleason * Added support for the Broadcast Tools SS 2.1 switcher. --- ChangeLog | 2 + docs/opsguide/gpio_switcher_devices.xml | 34 +++++++ lib/rdmatrix.cpp | 15 ++- lib/rdmatrix.h | 4 +- ripcd/Makefile.am | 2 + ripcd/btss21.cpp | 122 ++++++++++++++++++++++++ ripcd/btss21.h | 55 +++++++++++ ripcd/loaddrivers.cpp | 5 + 8 files changed, 233 insertions(+), 6 deletions(-) create mode 100644 ripcd/btss21.cpp create mode 100644 ripcd/btss21.h diff --git a/ChangeLog b/ChangeLog index 7f5bfa93..317ec0f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16661,3 +16661,5 @@ 2018-06-20 Fred Gleason * Added a 'TranscodingDelay=' parameter to the '[Tuning]' section of rd.conf(5). +2018-06-21 Fred Gleason + * Added support for the Broadcast Tools SS 2.1 switcher. diff --git a/docs/opsguide/gpio_switcher_devices.xml b/docs/opsguide/gpio_switcher_devices.xml index a71b83da..8a7041e4 100644 --- a/docs/opsguide/gpio_switcher_devices.xml +++ b/docs/opsguide/gpio_switcher_devices.xml @@ -467,6 +467,40 @@ + + BroadcastTools SS 2.1 + + + Driver Name: + + + BroadcastTools SS 2.1 + + + + + Supported RML Commands: + + + + Switch Take ['ST'] + + + + + + + Control is done by means of an RS-232C connection to a four pin RJ11 + modular jack on the back of the unit (an adapter to a standard DB9 + connector is supplied by Broadcast Tools with the unit). Serial port + parameters should be set to 9600 baud rate, no parity, 8 data bits, 1 + stop bit, CR/LF termination. + + + Operation in 'multidrop' mode is not supported. + + + BroadcastTools SS 16.4 diff --git a/lib/rdmatrix.cpp b/lib/rdmatrix.cpp index 61943747..c532fa35 100644 --- a/lib/rdmatrix.cpp +++ b/lib/rdmatrix.cpp @@ -2,7 +2,7 @@ // // Abstract a Rivendell Switcher Matrix // -// (C) Copyright 2002-2016 Fred Gleason +// (C) Copyright 2002-2018 Fred Gleason // // 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 @@ -71,7 +71,8 @@ bool __mx_primary_controls[RDMatrix::LastType][RDMatrix::LastControl]= {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, // Kernel GPIO {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, // WheatNet SLIO {0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, // WheatNet LIO - {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0} // BT Universale 4.1 MLR>>Web + {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, // BT Universale 4.1 MLR>>Web + {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0} // BT SS 2.1 }; bool __mx_backup_controls[RDMatrix::LastType][RDMatrix::LastControl]= { @@ -119,7 +120,8 @@ bool __mx_backup_controls[RDMatrix::LastType][RDMatrix::LastControl]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // Kernel GPIO {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // WheatNet SLIO {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // WheatNet LIO - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // BT Universal 4.1 MLR>>Web + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // BT Universal 4.1 MLR>>Web + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // BT SS 2.1 }; int __mx_default_values[RDMatrix::LastType][RDMatrix::LastControl]= @@ -168,7 +170,8 @@ int __mx_default_values[RDMatrix::LastType][RDMatrix::LastControl]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // Kernel GPIO {1,0,0,55776,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // WheatNet SLIO {1,0,0,55776,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // WheatNet LIO - {1,0,0,56,0,0,0,0,0,0,0,4,1,5,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0} // BT Universal 4.1 MLR>>Web + {1,0,0,56,0,0,0,0,0,0,0,4,1,5,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // BT Universal 4.1 MLR>>Web + {0,0,0,0,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0} // BT SS 2.1 }; RDMatrix::RDMatrix(const QString &station,int matrix) @@ -652,6 +655,10 @@ QString RDMatrix::typeString(RDMatrix::Type type) return QString("Logitek vGuest"); break; + case RDMatrix::BtSs21: + return QString("BroadcastTools SS2.1"); + break; + case RDMatrix::BtSs164: return QString("BroadcastTools SS16.4"); break; diff --git a/lib/rdmatrix.h b/lib/rdmatrix.h index 3641d2dd..7d317899 100644 --- a/lib/rdmatrix.h +++ b/lib/rdmatrix.h @@ -2,7 +2,7 @@ // // Abstract a Rivendell Switcher Matrix // -// (C) Copyright 2002-2017 Fred Gleason +// (C) Copyright 2002-2018 Fred Gleason // // 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 @@ -39,7 +39,7 @@ class RDMatrix LiveWireLwrpGpio=29,BtSentinel4Web=30,BtGpi16=31,ModemLines=32, SoftwareAuthority=33,Sas16000=34,RossNkScp=35,BtAdms4422=36, BtSs41Mlr=37,Modbus=38,KernelGpio=39,WheatnetSlio=40, - WheatnetLio=41,BtU41MlrWeb=42,LastType=43}; + WheatnetLio=41,BtU41MlrWeb=42,BtSs21=43,LastType=44}; enum Endpoint {Input=0,Output=1}; enum Mode {Stereo=0,Left=1,Right=2}; enum VguestAttribute {VguestEngine=0,VguestDevice=1,VguestSurface=2, diff --git a/ripcd/Makefile.am b/ripcd/Makefile.am index 0353209d..db843ad0 100644 --- a/ripcd/Makefile.am +++ b/ripcd/Makefile.am @@ -42,6 +42,7 @@ dist_ripcd_SOURCES = acu1p.cpp acu1p.h\ btgpi16.cpp btgpi16.h\ btsentinel4web.cpp btsentinel4web.h\ btss124.cpp btss124.h\ + btss21.cpp btss21.h\ btss164.cpp btss164.h\ btss41mlr.cpp btss41mlr.h\ btss42.cpp btss42.h\ @@ -95,6 +96,7 @@ nodist_ripcd_SOURCES = moc_am16.cpp\ moc_btsrc8iii.cpp\ moc_btss124.cpp\ moc_btss164.cpp\ + moc_btss21.cpp\ moc_btss41mlr.cpp\ moc_btss42.cpp\ moc_btss44.cpp\ diff --git a/ripcd/btss21.cpp b/ripcd/btss21.cpp new file mode 100644 index 00000000..4952f279 --- /dev/null +++ b/ripcd/btss21.cpp @@ -0,0 +1,122 @@ +// btss21.cpp +// +// A Rivendell switcher driver for the BroadcastTools SS 2.1 +// +// (C) Copyright 2002-2018 Fred Gleason +// +// 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 +#include + +#include + +#include +#include + + +BtSs21::BtSs21(RDMatrix *matrix,QObject *parent) + : Switcher(matrix,parent) +{ + // + // Get Matrix Parameters + // + bt_matrix=matrix->matrix(); + bt_inputs=matrix->inputs(); + bt_outputs=matrix->outputs(); + + // + // Initialize the TTY Port + // + RDTty *tty=new RDTty(rdstation->name(),matrix->port(RDMatrix::Primary)); + bt_device=new RDTTYDevice(); + if(tty->active()) { + bt_device->setName(tty->port()); + bt_device->setSpeed(tty->baudRate()); + bt_device->setWordLength(tty->dataBits()); + bt_device->setParity(tty->parity()); + bt_device->open(IO_Raw|IO_ReadWrite); + } + delete tty; +} + + +BtSs21::~BtSs21() +{ + delete bt_device; +} + + +RDMatrix::Type BtSs21::type() +{ + return RDMatrix::BtSs21; +} + + +unsigned BtSs21::gpiQuantity() +{ + return 0; +} + + +unsigned BtSs21::gpoQuantity() +{ + return 0; +} + + +bool BtSs21::primaryTtyActive() +{ + return true; +} + + +bool BtSs21::secondaryTtyActive() +{ + return false; +} + + +void BtSs21::processCommand(RDMacro *cmd) +{ + QString str; + + switch(cmd->command()) { + case RDMacro::ST: + if((cmd->arg(1).toInt()<0)||(cmd->arg(1).toInt()>bt_inputs)|| + (cmd->arg(2).toInt()<1)||(cmd->arg(2).toInt()>1)) { + cmd->acknowledge(false); + emit rmlEcho(cmd); + return; + } + if(cmd->arg(1).toInt()==0) { + str=QString().sprintf("*%dM",BTSS21_UNIT_ID); + bt_device->writeBlock(str,str.length()); + } + else { + str=QString().sprintf("*%d%d",BTSS21_UNIT_ID, + cmd->arg(1).toInt()); + bt_device->writeBlock(str,str.length()); + } + cmd->acknowledge(true); + emit rmlEcho(cmd); + break; + + default: + cmd->acknowledge(false); + emit rmlEcho(cmd); + break; + } +} diff --git a/ripcd/btss21.h b/ripcd/btss21.h new file mode 100644 index 00000000..3ef22b1f --- /dev/null +++ b/ripcd/btss21.h @@ -0,0 +1,55 @@ +// btss21.h +// +// A Rivendell switcher driver for the BroadcastTools SS 2.1 +// +// (C) Copyright 2002-2018 Fred Gleason +// +// 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. +// + +#ifndef BTSS21_H +#define BTSS21_H + +#include +#include +#include +#include +#include + +#include + +#define BTSS21_UNIT_ID 0 + +class BtSs21 : public Switcher +{ + Q_OBJECT + public: + BtSs21(RDMatrix *matrix,QObject *parent=0); + ~BtSs21(); + RDMatrix::Type type(); + unsigned gpiQuantity(); + unsigned gpoQuantity(); + bool primaryTtyActive(); + bool secondaryTtyActive(); + void processCommand(RDMacro *cmd); + + private: + RDTTYDevice *bt_device; + int bt_matrix; + int bt_inputs; + int bt_outputs; +}; + + +#endif // BTSS21_H diff --git a/ripcd/loaddrivers.cpp b/ripcd/loaddrivers.cpp index 084da9f2..642ce41e 100644 --- a/ripcd/loaddrivers.cpp +++ b/ripcd/loaddrivers.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -126,6 +127,10 @@ bool MainObject::LoadSwitchDriver(int matrix_num) ripcd_switcher[matrix_num]=new BtSs164(matrix,this); break; + case RDMatrix::BtSs21: + ripcd_switcher[matrix_num]=new BtSs21(matrix,this); + break; + case RDMatrix::BtSs41Mlr: ripcd_switcher[matrix_num]=new BtSs41Mlr(matrix,this); break; From 58fa103f6e30e601f770ee83327dc320d7af3587 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Thu, 23 Aug 2018 01:23:59 +0000 Subject: [PATCH 3/3] 2018-06-22 Fred Gleason * Added GPIO support for HPI devices to the 'Local Audio Adapter' switcher/gpio driver. --- ChangeLog | 3 + docs/opsguide/gpio_switcher_devices.xml | 3 + ripcd/Makefile.am | 6 +- ripcd/hpigpio.cpp | 425 ++++++++++++++++++++++++ ripcd/hpigpio.h | 77 +++++ ripcd/loaddrivers.cpp | 90 ++--- ripcd/local_audio.cpp | 225 ++++++++++++- ripcd/local_audio.h | 37 ++- 8 files changed, 813 insertions(+), 53 deletions(-) create mode 100644 ripcd/hpigpio.cpp create mode 100644 ripcd/hpigpio.h diff --git a/ChangeLog b/ChangeLog index 317ec0f5..3d8d034a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16663,3 +16663,6 @@ of rd.conf(5). 2018-06-21 Fred Gleason * Added support for the Broadcast Tools SS 2.1 switcher. +2018-06-22 Fred Gleason + * Added GPIO support for HPI devices to the 'Local Audio Adapter' + switcher/gpio driver. diff --git a/docs/opsguide/gpio_switcher_devices.xml b/docs/opsguide/gpio_switcher_devices.xml index 8a7041e4..b95557c3 100644 --- a/docs/opsguide/gpio_switcher_devices.xml +++ b/docs/opsguide/gpio_switcher_devices.xml @@ -1016,6 +1016,9 @@ + GPI Enable ['GE'] + GPI Set ['GI'] + GPO Set ['GO'] Switch Add ['SA'] Switch Add With Gain ['SX'] Switch Remove ['SR'] diff --git a/ripcd/Makefile.am b/ripcd/Makefile.am index db843ad0..eb073d58 100644 --- a/ripcd/Makefile.am +++ b/ripcd/Makefile.am @@ -2,7 +2,7 @@ ## ## Rivendell Interprocess Communication Daemon Makefile.am ## -## (C) Copyright 2002-2006 Fred Gleason +## (C) Copyright 2002-2018 Fred Gleason ## ## 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 @@ -21,7 +21,7 @@ ## Use automake to process this into a Makefile.in AM_CPPFLAGS = -Wall -DPREFIX=\"$(prefix)\" -DQTDIR=\"@QT_DIR@\" @QT_CXXFLAGS@ -I$(top_srcdir)/lib -LIBS = @QT_LIBS@ -L$(top_srcdir)/lib +LIBS = @QT_LIBS@ -L$(top_srcdir)/lib -L$(top_srcdir)/rdhpi MOC = @QT_MOC@ # The dependency for qt's Meta Object Compiler (moc) @@ -128,7 +128,7 @@ nodist_ripcd_SOURCES = moc_am16.cpp\ moc_wheatnet_lio.cpp\ moc_wheatnet_slio.cpp -ripcd_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ +ripcd_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ @LIBHPI@ EXTRA_DIST = ripcd.pro diff --git a/ripcd/hpigpio.cpp b/ripcd/hpigpio.cpp new file mode 100644 index 00000000..268d80f5 --- /dev/null +++ b/ripcd/hpigpio.cpp @@ -0,0 +1,425 @@ +// hpigpio.cpp +// +// A Rivendell switcher driver for AudioScience HPI GPIO devices +// +// (C) Copyright 2002-2018 Fred Gleason +// +// 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 + +#include + +#include "globals.h" +#include "hpigpio.h" + +HpiGpio::HpiGpio(RDMatrix *matrix,QObject *parent) + : Switcher(matrix,parent) +{ +/* + // + // Initialize Data Structures + // + hpi_istate=0; + for(int i=0;imatrix(); + hpi_card=matrix->card(); + hpi_gpis=0; + hpi_gpos=0; + +#ifdef HPI + struct hpi_control_t cntl; + hpi_handle_t block; + size_t value_size=0; + size_t value_items=0; + uint8_t *value; + + // + // Open Mixer + // + if(LogHpi(HPI_MixerOpen(NULL,hpi_card,&hpi_mixer),__LINE__)!=0) { + UpdateDb(matrix); + return; + } + memset(&cntl,0,sizeof(cntl)); + cntl.wSrcNodeType=HPI_SOURCENODE_ADAPTER; + if(LogHpi(HPI_Object_BlockHandle(hpi_mixer,HPI_SOURCENODE_ADAPTER,0,0,0, + "GPIO",&block),__LINE__)!=0) { + UpdateDb(matrix); + return; + } + + // + // GPIs Handle + // + if(LogHpi(HPI_Object_ParameterHandle(hpi_mixer,block,"Inputs",&hpi_gpis_param),__LINE__)!=0) { + UpdateDb(matrix); + return; + } + if(LogHpi(HPI_Object_GetInfo(hpi_gpis_param,entity_type_boolean, + entity_role_value,NULL,&value_size,&value_items), + __LINE__)!=0) { + UpdateDb(matrix); + return; + } + hpi_gpis=value_items; + + // + // GPOs Handle + // + if(LogHpi(HPI_Object_ParameterHandle(hpi_mixer,block,"Outputs",&hpi_gpos_param),__LINE__)!=0) { + return; + } + if(LogHpi(HPI_Object_GetInfo(hpi_gpos_param,entity_type_boolean, + entity_role_value,NULL,&value_size,&value_items), + __LINE__)!=0) { + hpi_gpis=0; + UpdateDb(matrix); + return; + } + hpi_gpos=value_items; + + UpdateDb(matrix); + + /* + // + // Interval OneShots + // + hpi_gpi_oneshot=new RDOneShot(this); + connect(hpi_gpi_oneshot,SIGNAL(timeout(int)),this,SLOT(gpiOneshotData(int))); + hpi_gpo_oneshot=new RDOneShot(this); + connect(hpi_gpo_oneshot,SIGNAL(timeout(int)),this,SLOT(gpoOneshotData(int))); + + // + // The Poll Timer + // + QTimer *timer=new QTimer(this,"poll_timer"); + connect(timer,SIGNAL(timeout()),this,SLOT(processStatus())); + timer->start(HPIGPIO_POLL_INTERVAL); +*/ +#endif // HPI +} + + +HpiGpio::~HpiGpio() +{ +#ifdef HPI +/* + delete hpi_device; + delete hpi_gpi_oneshot; + delete hpi_gpo_oneshot; +*/ +#endif // HPI +} + + +RDMatrix::Type HpiGpio::type() +{ + return RDMatrix::HpiGpio; +} + + +unsigned HpiGpio::gpiQuantity() +{ + return hpi_gpis; +} + + +unsigned HpiGpio::gpoQuantity() +{ + return hpi_gpos; +} + + +bool HpiGpio::primaryTtyActive() +{ + return false; +} + + +bool HpiGpio::secondaryTtyActive() +{ + return false; +} + + +void HpiGpio::processCommand(RDMacro *cmd) +{ +#ifdef HPI + /* + char str[20]; + + switch(cmd->command()) { + case RDMacro::GO: + if((cmd->argQuantity()!=5)|| + ((cmd->arg(1).toString().lower()!="i")&& + (cmd->arg(1).toString().lower()!="o"))|| + (cmd->arg(2).toInt()<1)||(cmd->arg(3).toInt()>hpi_gpos)|| + (cmd->arg(2).toInt()>hpi_gpos)|| + ((cmd->arg(3).toInt()!=1)&&(cmd->arg(3).toInt()!=0)&& + (cmd->arg(1).toString().lower()!="i"))|| + ((cmd->arg(3).toInt()!=1)&&(cmd->arg(3).toInt()!=0)&& + (cmd->arg(3).toInt()!=-1)&&(cmd->arg(1).toString().lower()=="i"))|| + (cmd->arg(4).toInt()<0)) { + cmd->acknowledge(false); + emit rmlEcho(cmd); + return; + } + if(cmd->arg(3).toInt()==0) { // Turn OFF + if(cmd->arg(4).toInt()==0) { + if(cmd->arg(1).toString().lower()=="i") { + if(hpi_gpi_state[cmd->arg(2).toInt()-1]) { + emit gpiChanged(hpi_matrix,cmd->arg(2).toInt()-1,false); + hpi_gpi_state[cmd->arg(2).toInt()-1]=false; + } + hpi_gpi_mask[cmd->arg(2).toInt()-1]=true; + } + if(cmd->arg(1).toString().lower()=="o") { + sprintf(str,"*%dOR%02dF\r\n",HPIGPIO_UNIT_ID,cmd->arg(2).toInt()); + hpi_device->writeBlock(str,9); + emit gpoChanged(hpi_matrix,cmd->arg(2).toInt()-1,false); + } + } + else { + if(cmd->echoRequested()) { + cmd->acknowledge(false); + emit rmlEcho(cmd); + } + return; + } + } + else { + if(cmd->arg(3).toInt()==-1) { // Clear input + hpi_gpi_mask[cmd->arg(2).toInt()-1]=false; + hpi_device->writeBlock("*0SPA\r\n",7); + } + else { + if(cmd->arg(4).toInt()==0) { // Turn ON + if(cmd->arg(1).toString().lower()=="i") { + if(!hpi_gpi_state[cmd->arg(2).toInt()-1]) { + emit gpiChanged(hpi_matrix,cmd->arg(2).toInt()-1,true); + hpi_gpi_state[cmd->arg(2).toInt()-1]=true; + } + hpi_gpi_mask[cmd->arg(2).toInt()-1]=true; + } + if(cmd->arg(1).toString().lower()=="o") { + sprintf(str,"*%dOR%02dL\r\n", + HPIGPIO_UNIT_ID,cmd->arg(2).toInt()); + hpi_device->writeBlock(str,9); + emit gpoChanged(hpi_matrix,cmd->arg(2).toInt()-1,true); + } + } + else { // Pulse + if(cmd->arg(1).toString().lower()=="i") { + if(!hpi_gpi_state[cmd->arg(2).toInt()-1]) { + emit gpiChanged(hpi_matrix,cmd->arg(2).toInt()-1,true); + hpi_gpi_state[cmd->arg(2).toInt()-1]=true; + } + hpi_gpi_mask[cmd->arg(2).toInt()-1]=true; + hpi_gpi_oneshot->start(cmd->arg(2).toInt()-1,500); + } + if(cmd->arg(1).toString().lower()=="o") { + sprintf(str,"*%dOR%02dP%02d\r\n", + HPIGPIO_UNIT_ID,cmd->arg(2).toInt(), + cmd->arg(4).toInt()/100+1); + hpi_device->writeBlock(str,11); + emit gpoChanged(hpi_matrix,cmd->arg(2).toInt()-1,true); + hpi_gpo_oneshot->start(cmd->arg(2).toInt()-1,500); + } + } + } + } + if(cmd->echoRequested()) { + cmd->acknowledge(true); + emit rmlEcho(cmd); + } + break; + + default: + cmd->acknowledge(false); + emit rmlEcho(cmd); + break; + } + */ +#endif // HPI +} + + +void HpiGpio::processStatus() +{ +#ifdef HPI + /* + char buffer[256]; + int n; + int gpi; + + while((n=hpi_device->readBlock(buffer,255))>0) { + for(int i=0;iwriteBlock("*0SPA",5); + */ +#endif // HPI +} + + +void HpiGpio::gpoOneshotData(int value) +{ +#ifdef HPI + // emit gpoChanged(hpi_matrix,value,false); +#endif // HPI +} + + +void HpiGpio::UpdateDb(RDMatrix *matrix) const +{ + matrix->setGpis(hpi_gpis); + matrix->setGpos(hpi_gpos); +} + + +#ifdef HPI +hpi_err_t HpiGpio::LogHpi(hpi_err_t err,int lineno) +{ + char err_txt[200]; + + if(err!=0) { + HPI_GetErrorText(err,err_txt); + syslog(LOG_NOTICE,"HPI Error: %s, %s line %d",err_txt,__FILE__,lineno); + } + return err; +} +#endif // HPI diff --git a/ripcd/hpigpio.h b/ripcd/hpigpio.h new file mode 100644 index 00000000..cdd24244 --- /dev/null +++ b/ripcd/hpigpio.h @@ -0,0 +1,77 @@ +// hpigpio.h +// +// A Rivendell switcher driver for AudioScience HPI GPIO devices +// +// (C) Copyright 2002-2018 Fred Gleason +// +// 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. +// + +#ifndef HPIGPIO_H +#define HPIGPIO_H + +#include +#include +#include +#include +#include + +#ifdef HPI +#include +#endif // HPI + +#include "switcher.h" + +#define HPIGPIO_POLL_INTERVAL 100 +#define HPIGPIO_GPIO_PINS 16 + +class HpiGpio : public Switcher +{ + Q_OBJECT + public: + HpiGpio(RDMatrix *matrix,QObject *parent=0); + ~HpiGpio(); + RDMatrix::Type type(); + unsigned gpiQuantity(); + unsigned gpoQuantity(); + bool primaryTtyActive(); + bool secondaryTtyActive(); + void processCommand(RDMacro *cmd); + + private slots: + void processStatus(); + void gpiOneshotData(int value); + void gpoOneshotData(int value); + + private: +#ifdef HPI + void UpdateDb(RDMatrix *matrix) const; + hpi_err_t LogHpi(hpi_err_t err,int lineno); + hpi_handle_t hpi_mixer; + hpi_handle_t hpi_gpis_param; + hpi_handle_t hpi_gpos_param; +#endif // HPI + RDOneShot *hpi_gpi_oneshot; + RDOneShot *hpi_gpo_oneshot; + int hpi_matrix; + int hpi_card; + int hpi_gpis; + int hpi_gpos; + int hpi_istate; + bool hpi_gpi_state[HPIGPIO_GPIO_PINS]; + bool hpi_gpi_mask[HPIGPIO_GPIO_PINS]; +}; + + +#endif // HPIGPIO_H diff --git a/ripcd/loaddrivers.cpp b/ripcd/loaddrivers.cpp index 642ce41e..78316403 100644 --- a/ripcd/loaddrivers.cpp +++ b/ripcd/loaddrivers.cpp @@ -20,51 +20,51 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "ripcd.h" +#include "switcher.h" +#include "globals.h" +#include "acu1p.h" +#include "am16.h" +#include "bt10x1.h" +#include "bt16x1.h" +#include "bt16x2.h" +#include "bt8x2.h" +#include "btacs82.h" +#include "btadms4422.h" +#include "btgpi16.h" +#include "btsentinel4web.h" +#include "btsrc16.h" +#include "btsrc8iii.h" +#include "btss124.h" +#include "btss164.h" +#include "btss21.h" +#include "btss41mlr.h" +#include "btss42.h" +#include "btss44.h" +#include "btss82.h" +#include "btu41mlrweb.h" +#include "harlond.h" +#include "kernelgpio.h" +#include "livewire_lwrpaudio.h" +#include "livewire_lwrpgpio.h" +#include "livewire_mcastgpio.h" +#include "local_audio.h" +#include "local_gpio.h" +#include "modbus.h" +#include "modemlines.h" +#include "quartz1.h" +#include "rossnkscp.h" +#include "sas16000.h" +#include "sas32000.h" +#include "sas64000.h" +#include "sas64000gpi.h" +#include "sasusi.h" +#include "starguide3.h" +#include "swauthority.h" +#include "unity4000.h" +#include "vguest.h" +#include "wheatnet_lio.h" +#include "wheatnet_slio.h" bool MainObject::LoadSwitchDriver(int matrix_num) { diff --git a/ripcd/local_audio.cpp b/ripcd/local_audio.cpp index 7723749d..7e078b96 100644 --- a/ripcd/local_audio.cpp +++ b/ripcd/local_audio.cpp @@ -1,8 +1,8 @@ // local_audio.cpp // -// A Rivendell switcher driver for the BroadcastTools 10x1 +// A Rivendell switcher driver for local audio cards. // -// (C) Copyright 2002-2003,2016 Fred Gleason +// (C) Copyright 2002-2018 Fred Gleason // // 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 @@ -28,17 +28,40 @@ LocalAudio::LocalAudio(RDMatrix *matrix,QObject *parent) : Switcher(matrix,parent) { + bt_poll_timer=NULL; + bt_gpi_values=NULL; + bt_gpo_values=NULL; + // // Get Matrix Parameters // bt_inputs=matrix->inputs(); bt_outputs=matrix->outputs(); bt_card=matrix->card(); + bt_gpis=0; + bt_gpos=0; + + // + // Interval OneShot + // + bt_gpo_oneshot=new RDOneShot(this); + connect(bt_gpo_oneshot,SIGNAL(timeout(int)),this,SLOT(gpoOneshotData(int))); + + InitializeHpi(matrix); } LocalAudio::~LocalAudio() { + if(bt_poll_timer!=NULL) { + delete bt_poll_timer; + } + if(bt_gpi_values!=NULL) { + delete bt_gpi_values; + } + if(bt_gpo_values!=NULL) { + delete bt_gpo_values; + } } @@ -75,6 +98,60 @@ bool LocalAudio::secondaryTtyActive() void LocalAudio::processCommand(RDMacro *cmd) { switch(cmd->command()) { + case RDMacro::GO: + if((cmd->argQuantity()!=5)|| + ((cmd->arg(1).toString().lower()!="i")&& + (cmd->arg(1).toString().lower()!="o"))|| + (cmd->arg(2).toInt()<1)||(cmd->arg(3).toInt()>bt_gpos)|| + (cmd->arg(2).toInt()>bt_gpos)|| + ((cmd->arg(3).toInt()!=1)&&(cmd->arg(3).toInt()!=0)&& + (cmd->arg(1).toString().lower()!="i"))|| + ((cmd->arg(3).toInt()!=1)&&(cmd->arg(3).toInt()!=0)&& + (cmd->arg(3).toInt()!=-1)&&(cmd->arg(1).toString().lower()=="i"))|| + (cmd->arg(4).toInt()<0)) { + cmd->acknowledge(false); + emit rmlEcho(cmd); + return; + } + if(cmd->arg(3).toInt()==0) { // Turn OFF + if(cmd->arg(4).toInt()==0) { + if(cmd->arg(1).toString().lower()=="o") { + SetGpo(cmd->arg(2).toInt()-1,false); + emit gpoChanged(matrixNumber(),cmd->arg(2).toInt()-1,false); + } + } + else { + if(cmd->echoRequested()) { + cmd->acknowledge(false); + emit rmlEcho(cmd); + } + return; + } + } + else { + if(cmd->arg(3).toInt()!=-1) { + if(cmd->arg(4).toInt()==0) { // Turn ON + if(cmd->arg(1).toString().lower()=="o") { + SetGpo(cmd->arg(2).toInt()-1,true); + emit gpoChanged(matrixNumber(),cmd->arg(2).toInt()-1,true); + } + } + else { // Pulse + if(cmd->arg(1).toString().lower()=="o") { + SetGpo(cmd->arg(2).toInt()-1,true); + emit gpoChanged(matrixNumber(),cmd->arg(2).toInt()-1,true); + bt_gpo_oneshot-> + start(cmd->arg(2).toInt()-1,cmd->arg(4).toInt()); + } + } + } + } + if(cmd->echoRequested()) { + cmd->acknowledge(true); + emit rmlEcho(cmd); + } + break; + case RDMacro::ST: if((cmd->arg(1).toInt()<0)||(cmd->arg(1).toInt()>bt_inputs)|| (cmd->arg(2).toInt()<=0)||(cmd->arg(2).toInt()>bt_outputs)) { @@ -150,3 +227,147 @@ void LocalAudio::processCommand(RDMacro *cmd) break; } } + + +void LocalAudio::pollData() +{ +#ifdef HPI + if(LogHpi(HPI_Object_GetValue(bt_gpis_param,entity_type_boolean, + bt_gpis,bt_gpi_values, + bt_gpis),__LINE__)==0) { + for(int i=0;istart(LOCALAUDIO_POLL_INTERVAL); + + // + // GPOs Handle + // + if(LogHpi(HPI_Object_ParameterHandle(bt_mixer,block,"Outputs",&bt_gpos_param),__LINE__)!=0) { + return; + } + if(LogHpi(HPI_Object_GetInfo(bt_gpos_param,entity_type_boolean, + entity_role_value,NULL,&value_size,&value_items), + __LINE__)!=0) { + bt_gpis=0; + UpdateDb(matrix); + return; + } + bt_gpos=value_items; + bt_gpo_values=new uint8_t[bt_gpos]; + if(LogHpi(HPI_Object_GetValue(bt_gpos_param,entity_type_boolean,value_items,bt_gpo_values,value_size),__LINE__)!=0) { + bt_gpis=0; + bt_gpos=0; + UpdateDb(matrix); + return; + } + + UpdateDb(matrix); +#endif // HPI +} + + +void LocalAudio::SetGpo(int line,bool state) +{ +#ifdef HPI + if(LogHpi(HPI_Object_GetValue(bt_gpos_param,entity_type_boolean, + bt_gpos,bt_gpo_values, + bt_gpos),__LINE__)==0) { + if(state) { + bt_gpo_values[line]='T'; + } + else { + bt_gpo_values[line]='F'; + } + LogHpi(HPI_Object_SetValue(bt_gpos_param,entity_type_boolean,bt_gpos, + bt_gpo_values,bt_gpos),__LINE__); + } +#endif // HPI +} + + +void LocalAudio::UpdateDb(RDMatrix *matrix) const +{ + matrix->setGpis(bt_gpis); + matrix->setGpos(bt_gpos); +} + + +#ifdef HPI +hpi_err_t LocalAudio::LogHpi(hpi_err_t err,int lineno) +{ + char err_txt[200]; + + if(err!=0) { + HPI_GetErrorText(err,err_txt); + syslog(LOG_NOTICE,"HPI Error: %s, %s line %d",err_txt,__FILE__,lineno); + } + return err; +} +#endif // HPI diff --git a/ripcd/local_audio.h b/ripcd/local_audio.h index 6887eeb0..b6bde78f 100644 --- a/ripcd/local_audio.h +++ b/ripcd/local_audio.h @@ -1,8 +1,8 @@ // local_audio.h // -// A Rivendell switcher driver for the BroadcastTools 10x1 +// A Rivendell switcher driver for local audio cards. // -// (C) Copyright 2002-2003,2016 Fred Gleason +// (C) Copyright 2002-2018 Fred Gleason // // 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 @@ -21,12 +21,23 @@ #ifndef LOCAL_AUDIO_H #define LOCAL_AUDIO_H +#include + +#include + #include #include #include +#include #include -#include +#ifdef HPI +#include +#endif // HPI + +#include "switcher.h" + +#define LOCALAUDIO_POLL_INTERVAL 100 class LocalAudio : public Switcher { @@ -41,9 +52,29 @@ class LocalAudio : public Switcher bool secondaryTtyActive(); void processCommand(RDMacro *cmd); + private slots: + void pollData(); + void gpoOneshotData(int value); + private: + void InitializeHpi(RDMatrix *matrix); + void SetGpo(int line,bool state); + void UpdateDb(RDMatrix *matrix) const; +#ifdef HPI + hpi_err_t LogHpi(hpi_err_t err,int lineno); + hpi_handle_t bt_mixer; + hpi_handle_t bt_gpis_param; + hpi_handle_t bt_gpos_param; + std::vector bt_gpi_states; +#endif // HPI + RDOneShot *bt_gpo_oneshot; + uint8_t *bt_gpi_values; + uint8_t *bt_gpo_values; + QTimer *bt_poll_timer; int bt_inputs; int bt_outputs; + int bt_gpis; + int bt_gpos; int bt_card; };