Fixed conflict in 'ChangeLog'

Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
This commit is contained in:
Fred Gleason 2021-12-03 14:34:47 -05:00
commit 2f45dee768
15 changed files with 201 additions and 8 deletions

View File

@ -22612,6 +22612,25 @@
2021-11-11 Fred Gleason <fredg@paravelsystems.com>
* Removed debugging code from 'web/rdxport/carts.cpp'.
* Removed debugging code from 'apis/rivwebpyapi/api/rivwebpyapi.py'.
2021-11-23 Fred Gleason <fredg@paravelsystems.com>
* Fixed a regression in caed(8) that made it impossible to stop
audio recordings manually.
2021-11-24 Fred Gleason <fredg@paravelsystems.com>
* Added a '--check-strings' switch to rddbmgr(8).
2021-12-01 Fred Gleason <fredg@paravelsystems.com>
* Added support for JACK promiscuous mode to the 'rivendell'
Systemd service.
2021-12-02 Fred Gleason <fredg@paravelsystems.com>
* Updated the RPM packaging to support JACK promiscuous mode.
2021-12-02 Fred Gleason <fredg@paravelsystems.com>
* Modified caed(8) to use promisucous mode when starting jackd(8).
2021-12-02 Fred Gleason <fredg@paravelsystems.com>
* Added a check to rdservice(8) to ensure that the 'rivendell'
service is run as 'root'
2021-12-02 Fred Gleason <fredg@paravelsystems.com>
* Fixed a regression in rdadmin(1) that caused IP address settings
to fail to be saved when creating a new 'Logitek vGuest' matrix
entry.
2021-12-03 Fred Gleason <fredg@paravelsystems.com>
* Modified the 'rivwebpyapi' so as to require only scheme and host
parts of the URL provided to the 'url' parameter.

View File

@ -634,7 +634,10 @@ void MainObject::stopRecordingData(int id,unsigned card,unsigned stream)
cae_server->sendCommand(id,QString::asprintf("SR %u %u -!",card,stream));
return;
}
if(!dvr->stopRecord(card,stream)) {
if(dvr->stopRecord(card,stream)) {
cae_server->sendCommand(id,QString::asprintf("SR %u %u +!",card,stream));
}
else {
cae_server->sendCommand(id,QString::asprintf("SR %u %u -!",card,stream));
return;
}

View File

@ -22,6 +22,8 @@
#include <samplerate.h>
#include <QProcessEnvironment>
#include <rdconf.h>
#include <rddatedecode.h>
#include <rdescape_string.h>
@ -470,7 +472,10 @@ bool DriverJack::initialize(unsigned *next_cardnum)
if(args.size()) {
QString program=args.at(0);
args.removeFirst();
QProcessEnvironment penv=QProcessEnvironment::systemEnvironment();
QProcess *proc=new QProcess(this);
penv.insert("JACK_PROMISCUOUS_SERVER","audio");
proc->setProcessEnvironment(penv);
proc->start(program,args);
if(proc->waitForStarted()) {
rda->syslog(LOG_INFO,"JACK server started");

View File

@ -1,6 +1,6 @@
## Makefile.am
##
## (C) Copyright 2002-2020 Fred Gleason <fredg@paravelsystems.com>
## (C) Copyright 2002-2021 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
@ -33,6 +33,7 @@ EXTRA_DIST = asound.conf-sample\
rd-bin.conf.in\
rd.conf-sample\
rivendell.pam\
rivendell-env.sh\
rivendell-webapi.conf\
syslog.conf-sample

4
conf/rivendell-env.sh Normal file
View File

@ -0,0 +1,4 @@
#
# Run jackd(1) in promiscuous mode
#
export JACK_PROMISCUOUS_SERVER=audio

3
debian/postinst vendored
View File

@ -26,6 +26,9 @@ case "$1" in
mv /etc/rd.conf /etc/rivendell.d/rd-default.conf
ln -s /etc/rivendell.d/rd-default.conf /etc/rd.conf
fi
if test ! -e /etc/profile.d/rivendell-env.sh ; then
cp /usr/share/rivendell/rivendell-env.sh /etc/profile.d/
fi
#
# FIXME: Configure ALSA Here!
#

2
debian/rules vendored
View File

@ -137,6 +137,8 @@ binary:
rm -rf debian/tmp/var
mkdir -p debian/rivendell/etc/logrotate.d
cp conf/logrotate-sample debian/rivendell/etc/logrotate.d/rivendell
mkdir -p debian/rivendell/usr/share/rivendell
cp conf/rivendell-env.sh debian/rivendell/usr/share/rivendell
mkdir -p debian/rivendell/usr/share/rivendell/logos
cp icons/webget_logo.png debian/rivendell/usr/share/rivendell/logos/
mkdir -p debian/rivendell/usr/share/doc/rivendell/logos

View File

@ -166,6 +166,18 @@
<option>--check</option>:
</para>
<variablelist remap='TP'>
<varlistentry>
<term>
<option>--check-strings</option>
</term>
<listitem>
<para>
Check all database fields of type VARCHAR for null characters and
then exit.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--dump-cuts-dir=</option><replaceable>dir-name</replaceable>

View File

@ -113,9 +113,9 @@ EditMatrix::EditMatrix(RDMatrix *matrix,QWidget *parent)
edit_porttype_label->setGeometry(15,96,70,19);
edit_porttype_label->setFont(labelFont());
edit_porttype_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
edit_porttype_box->insertItem(0,tr("Serial"));
edit_porttype_box->insertItem(1,tr("TCP/IP"));
edit_porttype_box->insertItem(1,tr("None"));
edit_porttype_box->insertItem(RDMatrix::TtyPort,tr("Serial"));
edit_porttype_box->insertItem(RDMatrix::TcpPort,tr("TCP/IP"));
edit_porttype_box->insertItem(RDMatrix::NoPort,tr("None"));
connect(edit_porttype_box,SIGNAL(activated(int)),
this,SLOT(portTypeActivatedData(int)));
@ -217,9 +217,9 @@ EditMatrix::EditMatrix(RDMatrix *matrix,QWidget *parent)
edit_porttype2_label->setGeometry(15,243,70,19);
edit_porttype2_label->setFont(labelFont());
edit_porttype2_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
edit_porttype2_box->insertItem(0,tr("Serial"));
edit_porttype2_box->insertItem(1,tr("TCP/IP"));
edit_porttype2_box->insertItem(2,tr("None"));
edit_porttype2_box->insertItem(RDMatrix::TtyPort,tr("Serial"));
edit_porttype2_box->insertItem(RDMatrix::TcpPort,tr("TCP/IP"));
edit_porttype2_box->insertItem(RDMatrix::NoPort,tr("None"));
connect(edit_porttype2_box,SIGNAL(activated(int)),
this,SLOT(portType2ActivatedData(int)));

View File

@ -82,6 +82,14 @@ MainObject::MainObject(QObject *parent)
}
rda->syslog(LOG_DEBUG,"starting up");
//
// Ensure that we are 'root'
//
if(geteuid()!=0) {
rda->syslog(LOG_ERR,"this service requires root");
exit(RDApplication::ExitNoPerms);
}
//
// Process Startup Options
//

View File

@ -135,6 +135,8 @@ touch $RPM_BUILD_ROOT/.qt/qt
rm -rf $RPM_BUILD_ROOT/@libexecdir@/logos
mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d
cp conf/logrotate-sample $RPM_BUILD_ROOT/etc/logrotate.d/rivendell
mkdir -p $RPM_BUILD_ROOT%{_datadir}/rivendell
cp conf/rivendell-env.sh $RPM_BUILD_ROOT%{_datadir}/rivendell/
mkdir -p $RPM_BUILD_ROOT/@DOC_PATH@/logos
cp icons/webget_logo.png $RPM_BUILD_ROOT/@DOC_PATH@/logos/
cp AUTHORS $RPM_BUILD_ROOT/@DOC_PATH@/
@ -205,6 +207,9 @@ fi
if test ! -e /etc/asound.conf ; then
cp @DOC_PATH@/asound.conf-sample /etc/asound.conf
fi
if test ! -e /etc/profile.d/rivendell-env.sh ; then
cp /usr/share/rivendell/rivendell-env.sh /etc/profile.d/
fi
%{_sbindir}/rddbmgr --modify
/bin/systemctl restart rivendell
/bin/systemctl enable rivendell
@ -294,6 +299,7 @@ rm -rf $RPM_BUILD_ROOT
%{_bindir}/rdmemcheck.sh
%{_bindir}/rdrender
%{_datadir}/rivendell/*.qm
%{_datadir}/rivendell/rivendell-env.sh
%{_datadir}/icons/hicolor/16x16/apps/rivendell.png
%{_datadir}/icons/hicolor/16x16/apps/rdadmin.png
%{_datadir}/icons/hicolor/16x16/apps/rdairplay.png

View File

@ -8,6 +8,7 @@ After=network.target remote-fs.target nss-lookup.target
LimitNOFILE=4096
Type=simple
ExecStart=@prefix@/sbin/rdservice
Environment=JACK_PROMISCUOUS_SERVER=audio
PrivateTmp=false
Restart=always
RestartSec=2

View File

@ -135,6 +135,15 @@ bool MainObject::Check(QString *err_msg)
printf("done.\n\n");
}
//
// Validate Strings
//
if(db_check_all||db_check_strings) {
printf("Validating character strings (this may take some time)...\n");
ValidateDbStrings();
printf("done.\n\n");
}
//
// Rehash
//
@ -1161,3 +1170,110 @@ void MainObject::CheckSchedCodeRules(bool prompt_user) const
}
delete clock_q;
}
void MainObject::ValidateDbStrings() const
{
QString sql;
RDSqlQuery *q;
sql="show tables";
q=new RDSqlQuery(sql);
while(q->next()) {
ValidateTableStrings(q->value(0).toString());
}
delete q;
}
void MainObject::ValidateTableStrings(const QString &tbl_name) const
{
QString sql;
RDSqlQuery *q;
QString pri_col;
QString pri_type;
sql=QString("describe ")+"`"+tbl_name+"`";
q=new RDSqlQuery(sql);
while(q->next()) {
if(q->value(3).toString()=="PRI") {
pri_col=q->value(0).toString();
pri_type=q->value(1).toString();
}
if(q->value(1).toString().left(8)=="varchar(") {
ValidateFieldString(pri_col,pri_type,tbl_name,q->value(0).toString());
}
}
delete q;
}
void MainObject::ValidateFieldString(const QString &pri_col,
const QString &pri_type,
const QString &tbl_name,
const QString &col_name) const
{
QString sql;
RDSqlQuery *q;
sql=QString("select `")+col_name+"` from `"+tbl_name+"` where "+
"`"+col_name+"` like '%\\0'";
q=new RDSqlQuery(sql);
while(q->next()) {
FixFieldString(pri_col,pri_type,tbl_name,col_name);
}
delete q;
}
void MainObject::FixFieldString(const QString &pri_col,const QString &pri_type,
const QString &tbl_name,
const QString &col_name) const
{
QString sql;
RDSqlQuery *q;
if(pri_col==col_name) {
printf(" Field `%s`.`%s` contains invalid characters but is also primary key, unable to fix!\n",
tbl_name.toUtf8().constData(),
col_name.toUtf8().constData());
return;
}
if(pri_col.isEmpty()||pri_type.isEmpty()) {
printf(" Field `%s`.`%s` contains invalid characters but no primary key found, unable to fix!\n",
tbl_name.toUtf8().constData(),
col_name.toUtf8().constData());
return;
}
printf(" Field `%s`.`%s` contains invalid characters. Fix? (y/N) ",
tbl_name.toUtf8().constData(),
col_name.toUtf8().constData());
fflush(NULL);
if(UserResponse()) {
sql=QString("select ")+
"`"+pri_col+"`,"+ // 00
"`"+col_name+"` "+ // 01
"from `"+tbl_name+"` where "+
"`"+col_name+"` like '%\\0'";
q=new RDSqlQuery(sql);
while(q->next()) {
sql=QString("update `")+tbl_name+"` set "+
"`"+col_name+"`='"+RDEscapeString(q->value(1).toByteArray())+"' ";
if(pri_type.left(3)=="int") {
sql+="where `"+pri_col+QString::asprintf("`=%d",q->value(0).toInt());
}
else {
if(pri_type.left(7)=="varchar") {
sql+="where `"+pri_col+"`='"+
RDEscapeString(q->value(0).toString())+"'";
}
else {
printf(" Unknown primary key type \"%s\", skipping...\n",
pri_type.toUtf8().constData());
return;
}
}
RDSqlQuery::apply(sql);
}
}
}

View File

@ -58,6 +58,7 @@ MainObject::MainObject(QObject *parent)
db_check_orphaned_carts=false;
db_check_orphaned_cuts=false;
db_check_orphaned_tracks=false;
db_check_strings=false;
//
// Check that we're 'root'
@ -230,6 +231,11 @@ MainObject::MainObject(QObject *parent)
db_check_orphaned_tracks=true;
cmd->setProcessed(i,true);
}
if(cmd->key(i)=="--check-strings") {
db_check_all=false;
db_check_strings=true;
cmd->setProcessed(i,true);
}
if(!cmd->processed(i)) {
fprintf(stderr,"rddbmgr: unrecognized option \"%s\"\n",

View File

@ -71,6 +71,12 @@ class MainObject : public QObject
void RemoveCart(unsigned cartnum);
bool CopyToAudioStore(const QString &destfile,const QString &srcfile) const;
void CheckSchedCodeRules(bool prompt_user) const;
void ValidateDbStrings() const;
void ValidateTableStrings(const QString &tbl_name) const;
void ValidateFieldString(const QString &pri_col,const QString &pri_type,
const QString &tbl_name,const QString &col_name) const;
void FixFieldString(const QString &pri_col,const QString &pri_type,
const QString &tbl_name,const QString &col_name) const;
bool UserResponse() const;
//
@ -148,6 +154,7 @@ class MainObject : public QObject
bool db_check_orphaned_tracks;
bool db_check_orphaned_carts;
bool db_check_orphaned_cuts;
bool db_check_strings;
QString db_orphan_group_name;
QString db_dump_cuts_dir;
QString db_rehash;