mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2025-05-19 14:43:30 +02:00
2023-08-24 Fred Gleason <fredg@paravelsystems.com>
* Added a 'TestOutputStreams=' directive to the '[Caed]' section of rd.conf(5). * Added code to the 'Unload Playback' ['UP'] CAE command to mute all output port volume controls from the subject output stream. * Added a feature to the 'Set Output Port' ['OP'] CAE command where passing a '-1' for the 'port-num' argument will cause all output stream volume controls for the specified stream to be muted. Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
This commit is contained in:
parent
d9e16f65a0
commit
ba1e2d84ab
@ -24365,3 +24365,11 @@
|
||||
2023-08-24 Fred Gleason <fredg@paravelsystems.com>
|
||||
* Fixed a regression in the 'RDHPIPlayStream' that could cause
|
||||
audio play-out to be truncated.
|
||||
2023-08-24 Fred Gleason <fredg@paravelsystems.com>
|
||||
* Added a 'TestOutputStreams=' directive to the '[Caed]' section
|
||||
of rd.conf(5).
|
||||
* Added code to the 'Unload Playback' ['UP'] CAE command to mute all
|
||||
output port volume controls from the subject output stream.
|
||||
* Added a feature to the 'Set Output Port' ['OP'] CAE command where
|
||||
passing a '-1' for the 'port-num' argument will cause all output
|
||||
stream volume controls for the specified stream to be muted.
|
||||
|
109
cae/cae.cpp
109
cae/cae.cpp
@ -178,9 +178,13 @@ MainObject::MainObject(QObject *parent)
|
||||
connect(cae_server,SIGNAL(setInputVolumeReq(int,unsigned,unsigned,int)),
|
||||
this,SLOT(setInputVolumeData(int,unsigned,unsigned,int)));
|
||||
connect(cae_server,
|
||||
SIGNAL(setOutputVolumeReq(int,unsigned,unsigned,unsigned,int)),
|
||||
SIGNAL(setOutputPortReq(int,unsigned,unsigned,unsigned,int)),
|
||||
this,
|
||||
SLOT(setOutputVolumeData(int,unsigned,unsigned,unsigned,int)));
|
||||
SLOT(setOutputPortData(int,unsigned,unsigned,unsigned,int)));
|
||||
connect(cae_server,
|
||||
SIGNAL(setOutputVolumeReq(int,unsigned,unsigned,int,int)),
|
||||
this,
|
||||
SLOT(setOutputVolumeData(int,unsigned,unsigned,int,int)));
|
||||
connect(cae_server,SIGNAL(fadeOutputVolumeReq(int,unsigned,unsigned,
|
||||
unsigned,int,unsigned)),
|
||||
this,SLOT(fadeOutputVolumeData(int,unsigned,unsigned,
|
||||
@ -318,6 +322,9 @@ MainObject::MainObject(QObject *parent)
|
||||
if(rda->config()->enableMixerLogging()) {
|
||||
rda->syslog(LOG_INFO,"mixer logging enabled");
|
||||
}
|
||||
if(rda->config()->testOutputStreams()) {
|
||||
rda->syslog(LOG_INFO,"output stream testing enabled");
|
||||
}
|
||||
rda->syslog(LOG_INFO,"cae started");
|
||||
}
|
||||
|
||||
@ -379,6 +386,11 @@ void MainObject::unloadPlaybackData(int id,unsigned handle)
|
||||
}
|
||||
if((play_owner[card][stream]==-1)||(play_owner[card][stream]==id)) {
|
||||
if(dvr->unloadPlayback(card,stream)) {
|
||||
if(!rda->config()->testOutputStreams()) {
|
||||
for(int i=0;i<RD_MAX_PORTS;i++) {
|
||||
dvr->setOutputVolume(card,stream,i,RD_MUTE_DEPTH); // Clear mixer
|
||||
}
|
||||
}
|
||||
play_owner[card][stream]=-1;
|
||||
rda->syslog(LOG_INFO,"UnloadPlayback - Card: %d Stream: %d Handle: %d",
|
||||
card,stream,handle);
|
||||
@ -668,8 +680,38 @@ void MainObject::setInputVolumeData(int id,unsigned card,unsigned stream,
|
||||
}
|
||||
|
||||
|
||||
void MainObject::setOutputPortData(int id,unsigned card,unsigned stream,
|
||||
unsigned port,int level)
|
||||
{
|
||||
Driver *dvr=GetDriver(card);
|
||||
|
||||
if(dvr==NULL) {
|
||||
cae_server->sendCommand(id,QString::asprintf("OP %u %u %u %d -!",
|
||||
card,stream,port,level));
|
||||
return;
|
||||
}
|
||||
if(!rda->config()->testOutputStreams()) {
|
||||
for(unsigned i=0;i<RD_MAX_STREAMS;i++) {
|
||||
if(i==port) {
|
||||
dvr->setOutputVolume(card,i,port,level);
|
||||
}
|
||||
else {
|
||||
dvr->setOutputVolume(card,i,port,RD_FADE_DEPTH);
|
||||
}
|
||||
}
|
||||
if(rda->config()->enableMixerLogging()) {
|
||||
rda->syslog(LOG_INFO,
|
||||
"SetOutputPort - Card: %d Stream: %d Port: %d Level: %d",
|
||||
card,stream,port,level);
|
||||
}
|
||||
}
|
||||
cae_server->sendCommand(id,QString::asprintf("OV %u %u %u %d +!",
|
||||
card,stream,port,level));
|
||||
}
|
||||
|
||||
|
||||
void MainObject::setOutputVolumeData(int id,unsigned card,unsigned stream,
|
||||
unsigned port,int level)
|
||||
int port,int level)
|
||||
{
|
||||
Driver *dvr=GetDriver(card);
|
||||
|
||||
@ -678,15 +720,24 @@ void MainObject::setOutputVolumeData(int id,unsigned card,unsigned stream,
|
||||
card,stream,port,level));
|
||||
return;
|
||||
}
|
||||
if(!dvr->setOutputVolume(card,stream,port,level)) {
|
||||
cae_server->sendCommand(id,QString::asprintf("OV %u %u %u %d -!",
|
||||
card,stream,port,level));
|
||||
return;
|
||||
}
|
||||
if(rda->config()->enableMixerLogging()) {
|
||||
rda->syslog(LOG_INFO,
|
||||
"SetOutputVolume - Card: %d Stream: %d Port: %d Level: %d",
|
||||
card,stream,port,level);
|
||||
if(!rda->config()->testOutputStreams()) {
|
||||
if(port>=0) {
|
||||
if(!dvr->setOutputVolume(card,stream,port,level)) {
|
||||
cae_server->sendCommand(id,QString::asprintf("OV %u %u %u %d -!",
|
||||
card,stream,port,level));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(int i=0;i<RD_MAX_PORTS;i++) {
|
||||
dvr->setOutputVolume(card,stream,i,level);
|
||||
}
|
||||
}
|
||||
if(rda->config()->enableMixerLogging()) {
|
||||
rda->syslog(LOG_INFO,
|
||||
"SetOutputVolume - Card: %d Stream: %d Port: %d Level: %d",
|
||||
card,stream,port,level);
|
||||
}
|
||||
}
|
||||
cae_server->sendCommand(id,QString::asprintf("OV %u %u %u %d +!",
|
||||
card,stream,port,level));
|
||||
@ -704,16 +755,18 @@ void MainObject::fadeOutputVolumeData(int id,unsigned card,unsigned stream,
|
||||
card,stream,port,level,length));
|
||||
return;
|
||||
}
|
||||
if(!dvr->fadeOutputVolume(card,stream,port,level,length)) {
|
||||
cae_server->
|
||||
sendCommand(id,QString::asprintf("FV %u %u %u %d %u -!",
|
||||
card,stream,port,level,length));
|
||||
return;
|
||||
}
|
||||
if(rda->config()->enableMixerLogging()) {
|
||||
rda->syslog(LOG_INFO,
|
||||
"FadeOutputVolume - Card: %d Stream: %d Port: %d Level: %d Length: %d",
|
||||
card,stream,port,level,length);
|
||||
if(!rda->config()->testOutputStreams()) {
|
||||
if(!dvr->fadeOutputVolume(card,stream,port,level,length)) {
|
||||
cae_server->
|
||||
sendCommand(id,QString::asprintf("FV %u %u %u %d %u -!",
|
||||
card,stream,port,level,length));
|
||||
return;
|
||||
}
|
||||
if(rda->config()->enableMixerLogging()) {
|
||||
rda->syslog(LOG_INFO,
|
||||
"FadeOutputVolume - Card: %d Stream: %d Port: %d Level: %d Length: %d",
|
||||
card,stream,port,level,length);
|
||||
}
|
||||
}
|
||||
cae_server->
|
||||
sendCommand(id,QString::asprintf("FV %u %u %u %d %u +!",
|
||||
@ -1620,6 +1673,8 @@ Driver *MainObject::GetDriver(unsigned card) const
|
||||
|
||||
void MainObject::MakeDriver(unsigned *next_card,RDStation::AudioDriver type)
|
||||
{
|
||||
unsigned first_card=*next_card;
|
||||
int initial_output_volume=RD_MUTE_DEPTH;
|
||||
Driver *dvr=NULL;
|
||||
|
||||
switch(type) {
|
||||
@ -1653,6 +1708,9 @@ void MainObject::MakeDriver(unsigned *next_card,RDStation::AudioDriver type)
|
||||
case RDStation::None:
|
||||
break;
|
||||
}
|
||||
if(rda->config()->testOutputStreams()) {
|
||||
initial_output_volume=0;
|
||||
}
|
||||
if(dvr!=NULL) {
|
||||
if(dvr->initialize(next_card)) {
|
||||
connect(dvr,SIGNAL(playStateChanged(int,int,int)),
|
||||
@ -1660,6 +1718,13 @@ void MainObject::MakeDriver(unsigned *next_card,RDStation::AudioDriver type)
|
||||
connect(dvr,SIGNAL(recordStateChanged(int,int,int)),
|
||||
this,SLOT(stateRecordUpdate(int,int,int)));
|
||||
d_drivers.push_back(dvr);
|
||||
for(unsigned i=first_card;i<*next_card;i++) {
|
||||
for(int j=0;j<RD_MAX_STREAMS;j++) {
|
||||
for(int k=0;k<RD_MAX_PORTS;k++) {
|
||||
dvr->setOutputVolume(i,j,k,initial_output_volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
delete dvr;
|
||||
|
@ -85,7 +85,9 @@ class MainObject : public QObject
|
||||
int threshold_level);
|
||||
void stopRecordingData(int id,unsigned card,unsigned stream);
|
||||
void setInputVolumeData(int id,unsigned card,unsigned stream,int level);
|
||||
void setOutputVolumeData(int id,unsigned card,unsigned stream,unsigned port,
|
||||
void setOutputPortData(int id,unsigned card,unsigned stream,unsigned port,
|
||||
int level);
|
||||
void setOutputVolumeData(int id,unsigned card,unsigned stream,int port,
|
||||
int level);
|
||||
void fadeOutputVolumeData(int id,unsigned card,unsigned stream,unsigned port,
|
||||
int level,unsigned length);
|
||||
|
@ -413,13 +413,31 @@ bool CaeServer::ProcessCommand(int id,const QString &cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
if((f0.at(0)=="OV")&&(f0.size()==5)) { // Set Output Volume
|
||||
if((f0.at(0)=="OP")&&(f0.size()==5)) { // Set Output Port
|
||||
unsigned card=f0.at(1).toUInt(&ok);
|
||||
if(ok&&(card<RD_MAX_CARDS)) {
|
||||
unsigned stream=f0.at(2).toUInt(&ok);
|
||||
if(ok&&(stream<RD_MAX_STREAMS)) {
|
||||
if(ok) {
|
||||
unsigned port=f0.at(3).toUInt(&ok);
|
||||
if(ok&&(port<RD_MAX_PORTS)) {
|
||||
int level=f0.at(4).toInt(&ok);
|
||||
if(ok) {
|
||||
emit setOutputPortReq(id,card,stream,port,level);
|
||||
was_processed=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if((f0.at(0)=="OV")&&(f0.size()==5)) { // Set Output Volume
|
||||
unsigned card=f0.at(1).toUInt(&ok);
|
||||
if(ok&&(card<RD_MAX_CARDS)) {
|
||||
unsigned stream=f0.at(2).toUInt(&ok);
|
||||
if(ok&&(stream<RD_MAX_STREAMS)) {
|
||||
if(ok) {
|
||||
int port=f0.at(3).toInt(&ok);
|
||||
if(ok&&(port<RD_MAX_PORTS)) {
|
||||
int level=f0.at(4).toInt(&ok);
|
||||
if(ok) {
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// Network server for caed(8).
|
||||
//
|
||||
// (C) Copyright 2019 Fred Gleason <fredg@paravelsystems.com>
|
||||
// (C) Copyright 2019-2023 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
|
||||
@ -79,7 +79,9 @@ class CaeServer : public QObject
|
||||
int threshold_level);
|
||||
void stopRecordingReq(int id,unsigned card,unsigned stream);
|
||||
void setInputVolumeReq(int id,unsigned card,unsigned stream,int level);
|
||||
void setOutputVolumeReq(int id,unsigned card,unsigned stream,unsigned port,
|
||||
void setOutputPortReq(int id,unsigned card,unsigned stream,unsigned port,
|
||||
int level);
|
||||
void setOutputVolumeReq(int id,unsigned card,unsigned stream,int port,
|
||||
int level);
|
||||
void fadeOutputVolumeReq(int id,unsigned card,unsigned stream,unsigned port,
|
||||
int level,unsigned length);
|
||||
|
@ -225,6 +225,16 @@ TranscodingDelay=0
|
||||
;
|
||||
;SuppressRdcatchMeterUpdates=No
|
||||
|
||||
[Caed]
|
||||
; When set to 'Yes', log all CAE mixer operations to syslog.
|
||||
;EnableMixerLogging=No
|
||||
|
||||
; When set to 'Yes', set all output stream to port volume settings to 0 dB
|
||||
; and disable 'Set Output Port' ['OP'], 'Set Output Volume' ['OV'] and
|
||||
; 'Fade Output Volume' ['FV'] CAE commands.
|
||||
; TestOutputStreams=No
|
||||
TestOutputStreams=No
|
||||
|
||||
[Debugging]
|
||||
; IMPORTANT NOTE:
|
||||
; The directives in this section can send large amounts of data to the
|
||||
|
@ -173,7 +173,8 @@
|
||||
<sect2>
|
||||
<title><command>Unload Playback</command></title>
|
||||
<para>
|
||||
Free an audio playback interface.
|
||||
Free an audio playback interface. This will also mute all associated
|
||||
output stream->output port volume controls.
|
||||
</para>
|
||||
<para>
|
||||
<userinput>UP <replaceable>conn-handle</replaceable>!</userinput>
|
||||
@ -662,6 +663,70 @@
|
||||
</variablelist>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title><command>Set Output Port</command></title>
|
||||
<para>
|
||||
Configure an output stream to use a particular output port.
|
||||
</para>
|
||||
<para>
|
||||
This will cause the <replaceable>stream-num</replaceable> output volume
|
||||
control feeding the <replaceable>port-num</replaceable> port to be set
|
||||
to the level given by <replaceable>level</replaceable>, while all other
|
||||
output_volume controls for that stream to be muted --e.g. set to
|
||||
-100 dB.
|
||||
</para>
|
||||
<para>
|
||||
<userinput>OP <replaceable>card-num</replaceable>
|
||||
<replaceable>stream-num</replaceable>
|
||||
<replaceable>port-num</replaceable>
|
||||
<replaceable>level</replaceable>!</userinput>
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<replaceable>card-num</replaceable>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
The number of the audio adapter to use.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<replaceable>stream-num</replaceable>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
The stream number to use. This is relative to the audio adapter
|
||||
selected.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<replaceable>port-num</replaceable>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
The port number to use. This is relative to the audio adapter
|
||||
selected.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<replaceable>level</replaceable>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
The level, in hundreths of a dB.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title><command>Set Output Volume</command></title>
|
||||
<para>
|
||||
@ -702,7 +767,10 @@
|
||||
<listitem>
|
||||
<para>
|
||||
The port number to use. This is relative to the audio adapter
|
||||
selected.
|
||||
selected. If a value less than <userinput>0</userinput> is
|
||||
provided, then <emphasis>all</emphasis> output ports for
|
||||
<replaceable>stream-num</replaceable> will have their volume
|
||||
controls set to <replaceable>level</replaceable>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// Connection to the Rivendell Core Audio Engine
|
||||
//
|
||||
// (C) Copyright 2002-2021 Fred Gleason <fredg@paravelsystems.com>
|
||||
// (C) Copyright 2002-2023 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
|
||||
@ -278,12 +278,7 @@ void RDCae::setOutputVolume(int card,int stream,int port,int level)
|
||||
|
||||
void RDCae::setOutputPort(int card,int stream,int port)
|
||||
{
|
||||
for(int i=0;i<RD_MAX_PORTS;i++) {
|
||||
if(i!=port) {
|
||||
setOutputVolume(card,stream,i,-10000);
|
||||
}
|
||||
}
|
||||
setOutputVolume(card,stream,port,0);
|
||||
SendCommand(QString::asprintf("OP %d %d %d 0!",card,stream,port));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// Connection to the Rivendell Core Audio Engine
|
||||
//
|
||||
// (C) Copyright 2002-2021 Fred Gleason <fredg@paravelsystems.com>
|
||||
// (C) Copyright 2002-2023 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
|
||||
@ -55,9 +55,7 @@ class RDCae : public QObject
|
||||
void setClockSource(int card,RDCae::ClockSource src);
|
||||
void setInputVolume(int card,int stream,int level);
|
||||
void setOutputVolume(int card,int stream,int port,int level);
|
||||
|
||||
void setOutputPort(int card,int stream,int port);
|
||||
|
||||
void fadeOutputVolume(int card,int stream,int port,int level,int length);
|
||||
void setInputLevel(int card,int port,int level);
|
||||
void setOutputLevel(int card,int port,int level);
|
||||
|
@ -489,6 +489,12 @@ bool RDConfig::enableMixerLogging() const
|
||||
}
|
||||
|
||||
|
||||
bool RDConfig::testOutputStreams() const
|
||||
{
|
||||
return conf_test_output_streams;
|
||||
}
|
||||
|
||||
|
||||
bool RDConfig::useRealtime()
|
||||
{
|
||||
return conf_use_realtime;
|
||||
@ -707,6 +713,7 @@ bool RDConfig::load()
|
||||
conf_syslog_facility=profile->intValue("Identity","SyslogFacility",LOG_USER);
|
||||
|
||||
conf_enable_mixer_logging=profile->boolValue("Caed","EnableMixerLogging");
|
||||
conf_test_output_streams=profile->boolValue("Caed","TestOutputStreams");
|
||||
conf_use_realtime=profile->boolValue("Tuning","UseRealtime",false);
|
||||
conf_realtime_priority=profile->intValue("Tuning","RealtimePriority",9);
|
||||
conf_transcoding_delay=profile->intValue("Tuning","TranscodingDelay");
|
||||
@ -824,6 +831,7 @@ void RDConfig::clear()
|
||||
conf_rn_rml_uid=65535;
|
||||
conf_rn_rml_gid=65535;
|
||||
conf_enable_mixer_logging=false;
|
||||
conf_test_output_streams=false;
|
||||
conf_use_realtime=false;
|
||||
conf_realtime_priority=9;
|
||||
conf_transcoding_delay=0;
|
||||
|
@ -112,6 +112,7 @@ class RDConfig
|
||||
bool logSqlQueries() const;
|
||||
int logSqlQueriesLevel() const;
|
||||
bool enableMixerLogging() const;
|
||||
bool testOutputStreams() const;
|
||||
uid_t uid() const;
|
||||
gid_t gid() const;
|
||||
uid_t pypadUid() const;
|
||||
@ -204,6 +205,7 @@ class RDConfig
|
||||
uid_t conf_rn_rml_uid;
|
||||
gid_t conf_rn_rml_gid;
|
||||
bool conf_enable_mixer_logging;
|
||||
bool conf_test_output_streams;
|
||||
bool conf_use_realtime;
|
||||
int conf_transcoding_delay;
|
||||
int conf_realtime_priority;
|
||||
|
@ -465,9 +465,7 @@ void RDPlayDeck::play(unsigned pos,int segue_start,int segue_end,
|
||||
pause_called=false;
|
||||
play_cae->positionPlay(play_handle,play_audio_point[0]+pos);
|
||||
play_cae->setPlayPortActive(play_card,play_port,play_stream);
|
||||
for(int i=0;i<RD_MAX_PORTS;i++) {
|
||||
play_cae->setOutputVolume(play_card,play_stream,i,RD_MUTE_DEPTH);
|
||||
}
|
||||
play_cae->setOutputVolume(play_card,play_stream,-1,RD_MUTE_DEPTH);
|
||||
if((play_fade_point[0]==-1)||(play_fade_point[0]==play_audio_point[0])||
|
||||
((fadeup=play_fade_point[0]-play_audio_point[0]-pos)<=0)||
|
||||
(play_state==RDPlayDeck::Paused)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user