2022-12-30 Fred Gleason <fredg@paravelsystems.com>

* Added a 'RDLIBRARY.IS_SINGLETON' field to the database.
	* Added a 'RDLOGEDIT.IS_SINGLETON' field to the database.
	* Incremented the database version to 367.
	* Added 'RDLibraryConf::isSingleton()' and
	'RDLibraryConf::setIsSingleton()' methods.
	* Added 'RDLogeditConf::isSingleton()' and
	'RDLogeditConf::setIsSingleton()' methods.
	* Modified rdcartslots(1), rdcastmanager(1), rdcatch(1),
	rdlogmanager(1) and rdpanel(1) to allow only a single instance to
	run at a time.
	* Modified rdlibrary(1) and rdlogedit(1) to conditionally allow
	only a single instance to run at a time.
	* Added an rdsinglestart(1) utility.
	* Added a 'wmctrl' dependency to the 'rivendell' RPM package.

Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
This commit is contained in:
Fred Gleason 2022-12-30 15:41:22 -05:00
parent a1f2fa577f
commit 12bdbfc948
73 changed files with 759 additions and 146 deletions

1
.gitignore vendored
View File

@ -198,6 +198,7 @@ utils/rdselect_helper/rdconfig.h
utils/rdselect_helper/rdprofile.cpp
utils/rdselect_helper/rdprofile.h
utils/rdselect_helper/rdselect_helper
utils/rdsinglestart/rdsinglestart
utils/sas_shim/sas_shim
xdg/install_usermode.sh
xdg/rdalsaconfig-root-consolehelper

View File

@ -23873,3 +23873,18 @@
2022-12-27 Fred Gleason <fredg@paravelsystems.com>
* Incremented the package version to 4.0.0rc1.
* Incremented the Python API version to 4.0.0rc1.
2022-12-30 Fred Gleason <fredg@paravelsystems.com>
* Added a 'RDLIBRARY.IS_SINGLETON' field to the database.
* Added a 'RDLOGEDIT.IS_SINGLETON' field to the database.
* Incremented the database version to 367.
* Added 'RDLibraryConf::isSingleton()' and
'RDLibraryConf::setIsSingleton()' methods.
* Added 'RDLogeditConf::isSingleton()' and
'RDLogeditConf::setIsSingleton()' methods.
* Modified rdcartslots(1), rdcastmanager(1), rdcatch(1),
rdlogmanager(1) and rdpanel(1) to allow only a single instance to
run at a time.
* Modified rdlibrary(1) and rdlogedit(1) to conditionally allow
only a single instance to run at a time.
* Added an rdsinglestart(1) utility.
* Added a 'wmctrl' dependency to the 'rivendell' RPM package.

View File

@ -703,6 +703,7 @@ AC_CONFIG_FILES([rivendell.spec \
utils/rdpopup/Makefile \
utils/rdrender/Makefile \
utils/rdselect_helper/Makefile \
utils/rdsinglestart/Makefile \
utils/rdsoftkeys/Makefile \
utils/rmlsend/Makefile \
xdg/Makefile \

View File

@ -47,6 +47,7 @@ all-local: rdairplay.1\
rdrender.1\
rmlsend.1\
rdservice.8\
rdsinglestart.1\
rdsoftkeys.1
man_MANS = rdairplay.1\
@ -63,6 +64,7 @@ man_MANS = rdairplay.1\
rdrender.1\
rmlsend.1\
rdservice.8\
rdsinglestart.1\
rdsoftkeys.1
EXTRA_DIST = exitcodes.xml\
@ -94,6 +96,8 @@ EXTRA_DIST = exitcodes.xml\
rmlsend.xml\
rdservice.8\
rdservice.xml\
rdsinglestart.1\
rdsinglestart.xml\
rdsoftkeys.1\
rdsoftkeys.xml

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<refentry id="stdin" xmlns="http://docbook.org/ns/docbook" version="5.0">
<!--
Header
-->
<refmeta>
<refentrytitle>rdsinglestart</refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo class='source'>December 2022</refmiscinfo>
<refmiscinfo class='manual'>Linux Audio Manual</refmiscinfo>
</refmeta>
<refnamediv>
<refname>rdsinglestart</refname>
<refpurpose>
Start an X11 client program so as to ensure that only a
single instance is run
</refpurpose>
</refnamediv>
<info>
<author>
<personname>
<firstname>Fred</firstname>
<surname>Gleason</surname>
<email>fredg@paravelsystems.com</email>
</personname>
<contrib>Application Author</contrib>
</author>
</info>
<!--
Body
-->
<refsynopsisdiv id='synopsis'>
<cmdsynopsis>
<command>rdsinglestart</command>
<arg choice='req'><replaceable>cmd-name</replaceable></arg>
<arg choice='opt'><replaceable>cmd-opt1</replaceable></arg>
<arg choice='opt'><replaceable>..</replaceable></arg>
<sbr/>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1 id='description'><title>Description</title>
<para>
<command>rdsinglestart</command><manvolnum>1</manvolnum> is used to start
an X11 client program so as to ensure that only a single instance is run.
When invoked, <command>rdsinglestart</command><manvolnum>1</manvolnum>
will first look for existing windows whose title begins with the
string specified in <replaceable>cmd-name</replaceable> (case-insensitive).
If found, such windows will be raised, following which
<command>rdsinglestart</command><manvolnum>1</manvolnum> will exit.
If no matching windows are found,
<command>rdsinglestart</command><manvolnum>1</manvolnum>
will attempt to start <replaceable>cmd-name</replaceable>, using any
added options specified, following which it will exit.
</para>
</refsect1>
<refsect1 id='notes'><title>Notes</title>
<para>
<command>rdsinglestart</command><manvolnum>1</manvolnum> uses
<command>wmctrl</command><manvolnum>1</manvolnum> to query and interact
with the X11 windowing system. As such, it will work only with X11
client programs. Attempts to use it with non-X11 programs will have
undefined results.
</para>
</refsect1>
<refsect1 id='see_also'><title>See Also</title>
<para>
<citerefentry>
<refentrytitle>wmctrl</refentrytitle><manvolnum>1</manvolnum>
</citerefentry>
</para>
</refsect1>
</refentry>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

@ -1024,7 +1024,7 @@
<para>
<mediaobject>
<imageobject>
<imagedata align="center" fileref="rdadmin.configure_rdlibrary_dialog.png" width="87mm" depth="140mm"/>
<imagedata align="center" fileref="rdadmin.configure_rdlibrary_dialog.png" width="87mm"/>
</imageobject>
<caption>
<para>The Configure RDLibrary Dialog</para>
@ -1177,6 +1177,12 @@
<computeroutput>Show Only First 100 Matches</computeroutput> box
to be ticked when starting a new instance of rdlibrary(1).
</para>
<para>
The <computeroutput>Allow Multiple Instances</computeroutput>, if set
to <userinput>Yes</userinput>, will allow multiple, independent
instances of <command>rdlibrary</command><manvolnum>1</manvolnum> to
be run simultaneously.
</para>
<para>
The <computeroutput>Channels:</computeroutput> dropdown sets the
default value of the <computeroutput>Channels:</computeroutput>
@ -1658,7 +1664,7 @@
<para>
<mediaobject>
<imageobject>
<imagedata align="center" fileref="rdadmin.configure_rdlogedit_dialog.png" width="67mm" depth="89mm"/>
<imagedata align="center" fileref="rdadmin.configure_rdlogedit_dialog.png" width="67mm"/>
</imageobject>
<caption>
<para>The Configure RDLogEdit Dialog</para>
@ -1733,6 +1739,12 @@
the transition type to use by default when adding a new log
event.
</para>
<para>
The <computeroutput>Allow Multiple Instances</computeroutput>, if set
to <userinput>Yes</userinput>, will allow multiple, independent
instances of <command>rdlogedit</command><manvolnum>1</manvolnum> to
be run simultaneously.
</para>
</sect2>
<sect2 xml:id="sect.rdadmin.manage_hosts.configuring_rdcartslots">
<title>Configuring RDCartSlots</title>

View File

@ -31,3 +31,4 @@ ENABLE_EDITOR enum('N','Y')
SRC_CONVERTER int(11)
LIMIT_SEARCH int(11) 0 = No, 1 = Yes, 2 = Previous
SEARCH_LIMITED enum('N','Y')
IS_SINGLETON enum('N','Y')

View File

@ -24,3 +24,4 @@ REC_STOP_CART int(10) unsigned
TRIM_THRESHOLD int(11)
RIPPER_LEVEL int(11)
DEFAULT_TRANS_TYPE int(11)
IS_SINGLETON enum('N','Y')

View File

@ -63,7 +63,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("nexgen_filter","nexgen_filter",NEXGEN_FILTER_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,false)) {
fprintf(stderr,"nexgen_filter: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -51,7 +51,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("wings_filter","wings_filter",WINGS_FILTER_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,false)) {
fprintf(stderr,"wings_filter: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -24,7 +24,7 @@
/*
* Current Database Version
*/
#define RD_VERSION_DATABASE 366
#define RD_VERSION_DATABASE 367
#endif // DBVERSION_H

View File

@ -2,7 +2,7 @@
//
// Base GUI Application Class
//
// (C) Copyright 2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2021-2022 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
@ -18,6 +18,8 @@
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include <QProcess>
#include "rdapplication.h"
RDApplication *rda=NULL;
@ -36,6 +38,54 @@ RDApplication::~RDApplication()
}
bool RDApplication::makeSingleInstance(QString *err_msg)
{
//
// If we're already running, then just raise the window.
//
QStringList args;
args.clear();
args.push_back("-l");
QProcess *proc=new QProcess(this);
proc->start("wmctrl",args);
proc->waitForFinished();
if(proc->exitStatus()!=QProcess::NormalExit) {
*err_msg=tr("wmctrl(1) process crashed");
delete proc;
return false;
}
if(proc->exitCode()!=0) {
QString errs=QString::fromUtf8(proc->readAllStandardError());
if(errs.isEmpty()) {
*err_msg=tr("wmctrl(1) not found\n");
}
else {
*err_msg=QString::asprintf("wmctrl(1) process returned error [%s]",
errs.toUtf8().constData());
}
delete proc;
return false;
}
bool found=false;
QStringList f0=QString::fromUtf8(proc->readAllStandardOutput()).
split("\n",QString::SkipEmptyParts);
for(int i=0;i<f0.size();i++) {
QStringList f1=f0.at(i).split(" ",QString::SkipEmptyParts);
if(f1.size()>=4) {
if(f1.at(3).trimmed().toLower()==commandName()) {
Raise(f1.at(0));
found=true;
}
}
}
delete proc;
if(found) {
exit(0);
}
return true;
}
RDIconEngine *RDApplication::iconEngine() const
{
return app_icon_engine;
@ -51,3 +101,33 @@ QString RDApplication::locale()
}
return ret;
}
void RDApplication::Raise(const QString win_id)
{
QStringList args;
QProcess *proc=NULL;
args.push_back("-i");
args.push_back("-R");
args.push_back(win_id);
proc=new QProcess(this);
proc->start("wmctrl",args);
proc->waitForFinished();
if(proc->exitStatus()!=QProcess::NormalExit) {
perror("wmctrl(1) process crashed");
exit(1);
}
if(proc->exitCode()!=0) {
QString errs=QString::fromUtf8(proc->readAllStandardError());
if(errs.isEmpty()) {
fprintf(stderr,"rdsinglestart: wmctrl(1) not found\n");
}
else {
fprintf(stderr,"rdsinglestart: wmctrl(1) process returned error [%s]\n",
errs.toUtf8().constData());
}
exit(1);
}
delete proc;
}

View File

@ -2,7 +2,7 @@
//
// Base GUI Application Class
//
// (C) Copyright 2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2021-2022 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
@ -29,12 +29,15 @@ class RDApplication : public RDCoreApplication
Q_OBJECT;
public:
RDApplication(const QString &module_name,const QString &cmdname,
const QString &usage,QObject *parent=0);
const QString &usage,QObject *parent);
~RDApplication();
bool makeSingleInstance(QString *err_msg);
RDIconEngine *iconEngine() const;
static QString locale();
private:
void Raise(const QString win_id);
bool app_singleton;
RDIconEngine *app_icon_engine;
};

View File

@ -620,6 +620,18 @@ void RDCoreApplication::userChangedData()
}
QString RDCoreApplication::moduleName() const
{
return app_module_name;
}
QString RDCoreApplication::commandName() const
{
return app_command_name;
}
bool RDCoreApplication::CheckService(QString *err_msg)
{
bool ret=false;

View File

@ -58,7 +58,7 @@ class RDCoreApplication : public QObject
RDCoreApplication(const QString &module_name,const QString &cmdname,
const QString &usage,QObject *parent=0);
~RDCoreApplication();
bool open(QString *err_msg,ErrorType *err_type=NULL,bool check_svc=true);
bool open(QString *err_msg,ErrorType *err_type,bool check_svc);
RDAirPlayConf *airplayConf();
RDCae *cae();
RDCmdSwitch *cmdSwitch();
@ -94,6 +94,10 @@ class RDCoreApplication : public QObject
signals:
void userChanged();
protected:
QString moduleName() const;
QString commandName() const;
private:
bool CheckService(QString *err_msg);
RDAirPlayConf *app_airplay_conf;

View File

@ -370,6 +370,19 @@ void RDLibraryConf::setSearchLimited(bool state) const
}
bool RDLibraryConf::isSingleton() const
{
return RDBool(RDGetSqlValue("RDLIBRARY","ID",lib_id,"IS_SINGLETON").
toString());
}
void RDLibraryConf::setIsSingleton(bool state) const
{
SetRow("IS_SINGLETON",RDYesNo(state));
}
void RDLibraryConf::getSettings(RDSettings *s) const
{
QString sql;

View File

@ -83,6 +83,8 @@ class RDLibraryConf
void setLimitSearch(RDLibraryConf::SearchLimit lmt) const;
bool searchLimited() const;
void setSearchLimited(bool state) const;
bool isSingleton() const;
void setIsSingleton(bool state) const;
static QString cdServerTypeText(CdServerType type);
static QPixmap cdServerLogo(CdServerType type);

View File

@ -328,6 +328,19 @@ void RDLogeditConf::getSettings(RDSettings *s) const
}
bool RDLogeditConf::isSingleton() const
{
return RDBool(RDGetSqlValue("RDLOGEDIT","STATION",lib_station,"IS_SINGLETON").
toString());
}
void RDLogeditConf::setIsSingleton(bool state) const
{
SetRow("IS_SINGLETON",RDYesNo(state));
}
void RDLogeditConf::SetRow(const QString &param,int value) const
{
RDSqlQuery *q;

View File

@ -70,6 +70,8 @@ class RDLogeditConf
RDLogLine::TransType defaultTransType() const;
void setDefaultTransType(RDLogLine::TransType type);
void getSettings(RDSettings *s) const;
bool isSingleton() const;
void setIsSingleton(bool state) const;
private:
void SetRow(const QString &param,int value) const;

View File

@ -843,6 +843,20 @@ bool RDStation::create(const QString &name,QString *err_msg,
QString::asprintf("`MACHINE`=%d",i);
RDSqlQuery::apply(sql);
}
//
// RDLibrary Parameters
//
sql=QString("insert into `RDLIBRARY` set ")+
"`STATION`='"+RDEscapeString(name)+"'";
RDSqlQuery::apply(sql);
//
// RDLogEdit Parameters
//
sql=QString("insert into `RDLOGEDIT` set ")+
"`STATION`='"+RDEscapeString(name)+"'";
RDSqlQuery::apply(sql);
}
else { // Use Template Host
sql=QString("select ")+
@ -964,7 +978,8 @@ bool RDStation::create(const QString &name,QString *err_msg,
"`ENABLE_EDITOR`,"+ // 20
"`SRC_CONVERTER`,"+ // 21
"`LIMIT_SEARCH`,"+ // 22
"`SEARCH_LIMITED` "+ // 23
"`SEARCH_LIMITED`,"+ // 23
"`IS_SINGLETON` "+ // 24
"from `RDLIBRARY` where "+
"`STATION`='"+RDEscapeString(exemplar)+"'";
q=new RDSqlQuery(sql);
@ -994,6 +1009,7 @@ bool RDStation::create(const QString &name,QString *err_msg,
QString::asprintf("`SRC_CONVERTER`=%d,",q->value(21).toInt())+
QString::asprintf("`LIMIT_SEARCH`=%d,",q->value(22).toInt())+
"`SEARCH_LIMITED`='"+RDEscapeString(q->value(23).toString())+"',"+
"`IS_SINGLETON`='"+q->value(24).toString()+"',"+
"`STATION`='"+RDEscapeString(name)+"'";
RDSqlQuery::apply(sql);
}
@ -1020,7 +1036,8 @@ bool RDStation::create(const QString &name,QString *err_msg,
"`TRIM_THRESHOLD`,"+ // 14
"`RIPPER_LEVEL`,"+ // 15
"`DEFAULT_TRANS_TYPE`,"+ // 16
"`ENABLE_SECOND_START` "+ // 17
"`ENABLE_SECOND_START`,"+ // 17
"`IS_SINGLETON` "+ // 18
"from `RDLOGEDIT` where "+
"`STATION`='"+RDEscapeString(exemplar)+"'";
q=new RDSqlQuery(sql);
@ -1044,7 +1061,8 @@ bool RDStation::create(const QString &name,QString *err_msg,
QString::asprintf("`TRIM_THRESHOLD`=%d,",q->value(14).toInt())+
QString::asprintf("`RIPPER_LEVEL`=%d,",q->value(15).toInt())+
QString::asprintf("`DEFAULT_TRANS_TYPE`=%d,",q->value(16).toInt())+
"`ENABLE_SECOND_START`='"+RDEscapeString(q->value(17).toString())+"'";
"`ENABLE_SECOND_START`='"+RDEscapeString(q->value(17).toString())+"',"+
"`IS_SINGLETON`='"+q->value(18).toString()+"'";
RDSqlQuery::apply(sql);
}
delete q;

View File

@ -91,8 +91,7 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
QLabel *lib_maxlength_label=new QLabel(tr("Max Record Time:"),this);
lib_maxlength_label->setFont(labelFont());
lib_maxlength_label->setGeometry(25,101,160,19);
lib_maxlength_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_maxlength_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
//
// VOX threshold
@ -104,13 +103,11 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
QLabel *lib_vox_spin_label=new QLabel(tr("VOX Threshold:"),this);
lib_vox_spin_label->setFont(labelFont());
lib_vox_spin_label->setGeometry(25,122,160,19);
lib_vox_spin_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_vox_spin_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
QLabel *lib_vox_spin_unit=new QLabel(tr("dbFS"),this);
lib_vox_spin_unit->setFont(labelFont());
lib_vox_spin_unit->setGeometry(235,122,120,19);
lib_vox_spin_unit->
setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
lib_vox_spin_unit->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
//
// AutoTrim threshold
@ -122,13 +119,11 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
QLabel *lib_trim_spin_label=new QLabel(tr("AutoTrim Threshold:"),this);
lib_trim_spin_label->setFont(labelFont());
lib_trim_spin_label->setGeometry(25,144,160,19);
lib_trim_spin_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_trim_spin_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
QLabel *lib_trim_spin_unit=new QLabel(tr("dbFS"),this);
lib_trim_spin_unit->setFont(labelFont());
lib_trim_spin_unit->setGeometry(235,144,120,19);
lib_trim_spin_unit->
setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
lib_trim_spin_unit->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
//
// Tail Preroll
@ -141,13 +136,11 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
QLabel *lib_preroll_spin_label=new QLabel(tr("Tail Preroll:"),this);
lib_preroll_spin_label->setFont(labelFont());
lib_preroll_spin_label->setGeometry(25,166,160,19);
lib_preroll_spin_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_preroll_spin_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
QLabel *lib_preroll_spin_unit=new QLabel(tr("milliseconds"),this);
lib_preroll_spin_unit->setFont(labelFont());
lib_preroll_spin_unit->setGeometry(245,166,120,19);
lib_preroll_spin_unit->
setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
lib_preroll_spin_unit->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
//
// Ripper Device
@ -158,8 +151,7 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
QLabel *lib_ripdev_label=new QLabel(tr("Ripper Device:"),this);
lib_ripdev_label->setFont(labelFont());
lib_ripdev_label->setGeometry(25,188,160,19);
lib_ripdev_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_ripdev_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
//
// Paranoia Level
@ -169,8 +161,7 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
QLabel *lib_paranoia_label=new QLabel(tr("Paranoia Level:"),this);
lib_paranoia_label->setFont(labelFont());
lib_paranoia_label->setGeometry(25,210,160,19);
lib_paranoia_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_paranoia_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
//
// Read ISRC
@ -180,8 +171,7 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
QLabel *lib_isrc_label=new QLabel(tr("Read ISRCs from CD:"),this);
lib_isrc_label->setFont(labelFont());
lib_isrc_label->setGeometry(25,232,160,19);
lib_isrc_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_isrc_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
//
// CD Server Type
@ -195,12 +185,10 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
}
connect(lib_cd_server_type_box,SIGNAL(activated(int)),
this,SLOT(cdServerTypeData(int)));
lib_cd_server_label=
new QLabel(tr("CD Metadata Source:"),this);
lib_cd_server_label=new QLabel(tr("CD Metadata Source:"),this);
lib_cd_server_label->setFont(labelFont());
lib_cd_server_label->setGeometry(25,256,160,19);
lib_cd_server_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_cd_server_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
//
// CD Server
@ -214,8 +202,7 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
lib_cd_server_label=new QLabel(tr("CDDB Server:"),this);
lib_cd_server_label->setFont(labelFont());
lib_cd_server_label->setGeometry(25,278,160,19);
lib_cd_server_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_cd_server_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
//
// Format
@ -226,8 +213,7 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
QLabel *lib_format_label=new QLabel(tr("Format:"),this);
lib_format_label->setFont(labelFont());
lib_format_label->setGeometry(25,302,160,19);
lib_format_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_format_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
//
// Bitrate
@ -242,8 +228,7 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
QLabel *lib_bitrate_unit=new QLabel("kbps/chan",this);
lib_bitrate_unit->setFont(labelFont());
lib_bitrate_unit->setGeometry(245,326,160,19);
lib_bitrate_unit->
setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
lib_bitrate_unit->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
//
// Enable Editor
@ -255,8 +240,7 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
QLabel *lib_editor_label=new QLabel(tr("Allow External Editing:"),this);
lib_editor_label->setFont(labelFont());
lib_editor_label->setGeometry(25,350,160,19);
lib_editor_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_editor_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
//
// Sample Rate Converter
@ -271,8 +255,7 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
QLabel *lib_converter_label=new QLabel(tr("Sample Rate Converter:"),this);
lib_converter_label->setFont(labelFont());
lib_converter_label->setGeometry(10,374,175,19);
lib_converter_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_converter_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
//
// Limit Searches at Startup
@ -286,14 +269,26 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
new QLabel(tr("Limit Searches at Startup")+":",this);
lib_limit_search_label->setFont(labelFont());
lib_limit_search_label->setGeometry(10,398,175,19);
lib_limit_search_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_limit_search_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
//
// Allow Multiple Instances
//
lib_singleton_box=new QComboBox(this);
lib_singleton_box->setGeometry(190,422,80,19);
lib_singleton_box->insertItem(0,tr("No"));
lib_singleton_box->insertItem(1,tr("Yes"));
QLabel *lib_singleton_label=
new QLabel(tr("Allow Multiple Instances")+":",this);
lib_singleton_label->setFont(labelFont());
lib_singleton_label->setGeometry(10,422,175,19);
lib_singleton_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
//
// Defaults
//
QLabel *default_label=new QLabel(tr("Defaults"),this);
default_label->setGeometry(25,436,120,19);
default_label->setGeometry(25,460,120,19);
default_label->setFont(sectionLabelFont());
default_label->setAlignment(Qt::AlignRight);
@ -301,52 +296,47 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
// Default Channels
//
lib_channels_box=new QComboBox(this);
lib_channels_box->setGeometry(190,454,60,19);
lib_channels_box->setGeometry(190,478,60,19);
QLabel *lib_channels_label=new QLabel(tr("Channels:"),this);
lib_channels_label->setFont(labelFont());
lib_channels_label->setGeometry(25,454,160,19);
lib_channels_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_channels_label->setGeometry(25,478,160,19);
lib_channels_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
//
// Default Record Mode
//
lib_recmode_box=new QComboBox(this);
lib_recmode_box->setGeometry(190,478,100,19);
lib_recmode_box->setGeometry(190,502,100,19);
QLabel *lib_recmode_label=new QLabel(tr("Record Mode:"),this);
lib_recmode_label->setFont(labelFont());
lib_recmode_label->setGeometry(25,478,160,19);
lib_recmode_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_recmode_label->setGeometry(25,502,160,19);
lib_recmode_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
//
// Default Trim State
//
lib_trimstate_box=new QComboBox(this);
lib_trimstate_box->setGeometry(190,502,100,19);
lib_trimstate_box->setGeometry(190,526,100,19);
QLabel *lib_trimstate_label=new QLabel(tr("AutoTrim:"),this);
lib_trimstate_label->setFont(labelFont());
lib_trimstate_label->setGeometry(25,502,160,19);
lib_trimstate_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_trimstate_label->setGeometry(25,526,160,19);
lib_trimstate_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
//
// Normalization Level
//
lib_riplevel_spin=new QSpinBox(this);
lib_riplevel_spin->setGeometry(190,526,40,19);
lib_riplevel_spin->setGeometry(190,550,40,19);
lib_riplevel_spin->setMinimum(-99);
lib_riplevel_spin->setMaximum(0);
QLabel *lib_riplevel_spin_label=new QLabel(tr("Normalization Level:"),this);
lib_riplevel_spin_label->setFont(labelFont());
lib_riplevel_spin_label->setGeometry(25,526,160,19);
lib_riplevel_spin_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_riplevel_spin_label->setGeometry(25,550,160,19);
lib_riplevel_spin_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
QLabel *lib_riplevel_spin_unit=new QLabel(tr("dbFS"),this);
lib_riplevel_spin_unit->setFont(labelFont());
lib_riplevel_spin_unit->setGeometry(235,526,120,19);
lib_riplevel_spin_unit->
setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
lib_riplevel_spin_unit->setGeometry(235,550,120,19);
lib_riplevel_spin_unit->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
//
// Ok Button
@ -450,6 +440,7 @@ EditRDLibrary::EditRDLibrary(RDStation *station,RDStation *cae_station,
lib_editor_box->setCurrentIndex(lib_lib->enableEditor());
lib_converter_box->setCurrentIndex(lib_lib->srcConverter());
lib_limit_search_box->setCurrentIndex((int)lib_lib->limitSearch());
lib_singleton_box->setCurrentIndex(!lib_lib->isSingleton());
}
@ -466,7 +457,7 @@ EditRDLibrary::~EditRDLibrary()
QSize EditRDLibrary::sizeHint() const
{
return QSize(405,630);
return QSize(405,654);
}
@ -574,6 +565,7 @@ void EditRDLibrary::okData()
lib_lib->setSrcConverter(lib_converter_box->currentIndex());
lib_lib->setLimitSearch((RDLibraryConf::SearchLimit)
lib_limit_search_box->currentIndex());
lib_lib->setIsSingleton(lib_singleton_box->currentIndex()==0);
done(0);
}

View File

@ -2,7 +2,7 @@
//
// Edit an RDLibrry Configuration
//
// (C) Copyright 2002-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2002-2022 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
@ -71,6 +71,7 @@ class EditRDLibrary : public RDDialog
QComboBox *lib_editor_box;
QComboBox *lib_converter_box;
QComboBox *lib_limit_search_box;
QComboBox *lib_singleton_box;
};

View File

@ -282,6 +282,20 @@ EditRDLogedit::EditRDLogedit(RDStation *station,RDStation *cae_station,
lib_default_transtype_box->insertItem(1,tr("Segue"));
lib_default_transtype_box->insertItem(2,tr("Stop"));
//
// Allow Multiple Instances
//
lib_singleton_box=new QComboBox(this);
lib_singleton_box->setGeometry(180,434,100,19);
QLabel *lib_singleton_label=
new QLabel(tr("Allow Multiple Instances")+":",this);
lib_singleton_label->setFont(labelFont());
lib_singleton_label->setGeometry(0,434,175,19);
lib_singleton_label->
setAlignment(Qt::AlignRight|Qt::AlignVCenter);
lib_singleton_box->insertItem(0,tr("No"));
lib_singleton_box->insertItem(1,tr("Yes"));
//
// Ok Button
//
@ -365,6 +379,7 @@ EditRDLogedit::EditRDLogedit(RDStation *station,RDStation *cae_station,
ShowBitRates(lib_format_box->currentIndex(),lib_lib->bitrate());
lib_enable_second_start_box->setCurrentIndex(lib_lib->enableSecondStart());
lib_default_transtype_box->setCurrentIndex(lib_lib->defaultTransType());
lib_singleton_box->setCurrentIndex(!lib_lib->isSingleton());
}
@ -381,7 +396,7 @@ EditRDLogedit::~EditRDLogedit()
QSize EditRDLogedit::sizeHint() const
{
return QSize(395,500);
return QSize(395,524);
}
@ -493,6 +508,8 @@ void EditRDLogedit::okData()
lib_lib->setEnableSecondStart(lib_enable_second_start_box->currentIndex());
lib_lib->setDefaultTransType(
(RDLogLine::TransType)lib_default_transtype_box->currentIndex());
lib_lib->setIsSingleton(lib_singleton_box->currentIndex()==0);
done(0);
}

View File

@ -2,7 +2,7 @@
//
// Edit an RDLogEdit Configuration
//
// (C) Copyright 2002-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2002-2022 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
@ -66,6 +66,7 @@ class EditRDLogedit : public RDDialog
QLineEdit *lib_recstartcart_edit;
QLineEdit *lib_recendcart_edit;
QComboBox *lib_default_transtype_box;
QComboBox *lib_singleton_box;
QString lib_filter;
QString lib_group;
};

View File

@ -67,19 +67,18 @@ MainWidget::MainWidget(RDConfig *config,QWidget *parent)
// Open the Database
//
rda=new RDApplication("RDAirPlay","rdairplay",RDAIRPLAY_USAGE,this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
QMessageBox::critical(this,"RDAirPlay - "+tr("Error"),err_msg);
exit(1);
}
//
// Ensure Single Instance
// Ensure that we're the only instance
//
air_lock=new RDInstanceLock(RDHomeDir()+"/.rdairplaylock");
if(!air_lock->lock()) {
QMessageBox::information(this,tr("RDAirPlay"),
tr("Multiple instances not allowed!"));
exit(1);
if(!rda->makeSingleInstance(&err_msg)) {
QMessageBox::critical(this,"RDAirPlay - "+tr("Error"),
tr("Startup error")+": "+err_msg+".");
exit(RDCoreApplication::ExitPriorInstance);
}
//
@ -1767,7 +1766,6 @@ void MainWidget::closeEvent(QCloseEvent *e)
}
rda->airplayConf()->setExitCode(RDAirPlayConf::ExitClean);
rda->syslog(LOG_INFO,"RDAirPlay exiting");
air_lock->unlock();
saveSettings();
exit(0);
}
@ -1782,7 +1780,6 @@ void MainWidget::closeEvent(QCloseEvent *e)
}
rda->airplayConf()->setExitCode(RDAirPlayConf::ExitClean);
rda->syslog(LOG_INFO,"RDAirPlay exiting");
air_lock->unlock();
saveSettings();
exit(0);
}

View File

@ -22,7 +22,6 @@
#define RDAIRPLAY_H
#include <rdemptycart.h>
#include <rdinstancelock.h>
#include <rdmainwindow.h>
#include <rdmeterstrip.h>
@ -142,7 +141,6 @@ class MainWidget : public RDMainWindow
int air_cue_card;
int air_cue_port;
RDLogLine::TransType air_default_trans_type;
RDInstanceLock *air_lock;
bool air_clear_filter;
RDAirPlayConf::BarAction air_bar_action;
bool air_pause_enabled;

View File

@ -35,11 +35,20 @@ MainWidget::MainWidget(RDConfig *c,QWidget *parent)
// Open the Database
//
rda=new RDApplication("RDCartSlots","rdcartslots",RDCARTSLOTS_USAGE,this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,false)) {
QMessageBox::critical(this,"RDCartSlots - "+tr("Error"),err_msg);
exit(1);
}
//
// Ensure that we're the only instance
//
if(!rda->makeSingleInstance(&err_msg)) {
QMessageBox::critical(this,"RDCartSlots - "+tr("Error"),
tr("Startup error")+": "+err_msg+".");
exit(RDCoreApplication::ExitPriorInstance);
}
//
// Read Command Options
//

View File

@ -59,13 +59,22 @@ MainWidget::MainWidget(RDConfig *c,QWidget *parent)
//
rda=new RDApplication("RDCastManager","rdcastmanager",RDCASTMANAGER_USAGE,
this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
QMessageBox::critical(this,"RDCastManager - "+tr("Error"),err_msg);
exit(1);
}
setWindowIcon(rda->iconEngine()->
applicationIcon(RDIconEngine::RdCastManager,22));
//
// Ensure that we're the only instance
//
if(!rda->makeSingleInstance(&err_msg)) {
QMessageBox::critical(this,"RDCastManager - "+tr("Error"),
tr("Startup error")+": "+err_msg+".");
exit(RDCoreApplication::ExitPriorInstance);
}
//
// Read Command Options
//

View File

@ -67,11 +67,20 @@ MainWidget::MainWidget(RDConfig *c,QWidget *parent)
// Open the Database
//
rda=new RDApplication("RDCatch","rdcatch",RDCATCH_USAGE,this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
QMessageBox::critical(this,"RDCatch - "+tr("Error"),err_msg);
exit(1);
}
//
// Ensure that we're the only instance
//
if(!rda->makeSingleInstance(&err_msg)) {
QMessageBox::critical(this,"RDCatch - "+tr("Error"),
tr("Startup error")+": "+err_msg+".");
exit(RDCoreApplication::ExitPriorInstance);
}
//
// Read Command Options
//

View File

@ -87,12 +87,23 @@ MainWidget::MainWidget(RDConfig *c,QWidget *parent)
// Open the Database
//
rda=new RDApplication("RDLibrary","rdlibrary",RDLIBRARY_USAGE,this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
QMessageBox::critical(this,"RDLibrary - "+tr("Error"),err_msg);
exit(1);
}
setWindowIcon(rda->iconEngine()->applicationIcon(RDIconEngine::RdLibrary,22));
if(rda->libraryConf()->isSingleton()) {
//
// Ensure that we're the only instance
//
if(!rda->makeSingleInstance(&err_msg)) {
QMessageBox::critical(this,"RDLibrary - "+tr("Error"),
tr("Startup error")+": "+err_msg+".");
exit(RDCoreApplication::ExitPriorInstance);
}
}
//
// Read Command Options
//

View File

@ -61,12 +61,23 @@ MainWidget::MainWidget(RDConfig *c,QWidget *parent)
// Open the Database
//
rda=new RDApplication("RDLogEdit","rdlogedit",RDLOGEDIT_USAGE,this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
QMessageBox::critical(this,"RDLogEdit - "+tr("Error"),err_msg);
exit(1);
}
log_import_path=RDGetHomeDir();
if(rda->logeditConf()->isSingleton()) {
//
// Ensure that we're the only instance
//
if(!rda->makeSingleInstance(&err_msg)) {
QMessageBox::critical(this,"RDLogEdit - "+tr("Error"),
tr("Startup error")+": "+err_msg+".");
exit(RDCoreApplication::ExitPriorInstance);
}
}
//
// Read Command Options
//

View File

@ -2,7 +2,7 @@
//
// The User Login/Logout Utility for Rivendell.
//
// (C) Copyright 2002-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2002-2022 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
@ -44,13 +44,25 @@ MainWidget::MainWidget(RDConfig *c,QWidget *parent)
setMinimumSize(sizeHint());
setMaximumHeight(sizeHint().height());
//
// Open the database
//
rda=new RDApplication("RDLogin","rdlogin",RDLOGIN_USAGE,this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
QMessageBox::critical(this,"RDLogin - "+tr("Error"),err_msg);
exit(1);
}
setWindowIcon(rda->iconEngine()->applicationIcon(RDIconEngine::Rivendell,22));
//
// Ensure that we're the only instance
//
if(!rda->makeSingleInstance(&err_msg)) {
QMessageBox::critical(this,"RDLogin - "+tr("Error"),
tr("Startup error")+": "+err_msg+".");
exit(RDCoreApplication::ExitPriorInstance);
}
//
// Read Command Options
//

View File

@ -45,8 +45,9 @@ int RunReportOperation(int argc,char *argv[],const QString &rptname,
return 256;
}
rda=static_cast<RDApplication *>(new RDCoreApplication("RDLogManager","rdlogmanager",RDLOGMANAGER_USAGE));
if(!rda->open(&err_msg)) {
rda=static_cast<RDApplication *>(new RDCoreApplication("RDLogManager",
"rdlogmanager",RDLOGMANAGER_USAGE));
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"rdlogmanager: %s\n",err_msg.toUtf8().constData());
exit(RDApplication::ExitNoDb);
}

View File

@ -45,7 +45,7 @@ LogObject::LogObject(const QString &svcname,int start_offset,
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("RDLogManager","rdlogmanager",""));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,false)) {
fprintf(stderr,"rdlogmanager: %s\n",err_msg.toUtf8().constData());
exit(RDApplication::ExitNoDb);
}

View File

@ -53,7 +53,7 @@ MainWidget::MainWidget(RDConfig *c,QWidget *parent)
// Open the Database
//
rda=new RDApplication("RDLogManager","rdlogmanager",RDLOGMANAGER_USAGE,this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
QMessageBox::critical(this,"RDLogManager - "+tr("Error"),err_msg);
exit(RDApplication::ExitNoDb);
}
@ -61,6 +61,15 @@ MainWidget::MainWidget(RDConfig *c,QWidget *parent)
applicationIcon(RDIconEngine::RdLogManager,22));
setWindowTitle(tr("RDLogManager"));
//
// Ensure that we're the only instance
//
if(!rda->makeSingleInstance(&err_msg)) {
QMessageBox::critical(this,"RDLogManager - "+tr("Error"),
tr("Startup error")+": "+err_msg+".");
exit(RDCoreApplication::ExitPriorInstance);
}
//
// CAE Connection
//

View File

@ -54,12 +54,21 @@ MainWidget::MainWidget(RDConfig *c,QWidget *parent)
// Open the Database
//
rda=new RDApplication("RDPanel","rdpanel",RDPANEL_USAGE,this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
QMessageBox::critical(this,"RDPanel - "+tr("Error"),err_msg);
exit(1);
}
setWindowIcon(rda->iconEngine()->applicationIcon(RDIconEngine::RdPanel,22));
//
// Ensure that we're the only instance
//
if(!rda->makeSingleInstance(&err_msg)) {
QMessageBox::critical(this,"RDPanel - "+tr("Error"),
tr("Startup error")+": "+err_msg+".");
exit(RDCoreApplication::ExitPriorInstance);
}
//
// Read Command Options
//
@ -191,14 +200,12 @@ MainWidget::MainWidget(RDConfig *c,QWidget *parent)
int next_output=1;
for(int i=0;i<RD_SOUNDPANEL_MAX_OUTPUTS;i++) {
bool unique=true;
int output=next_output;
QString label=
rda->portNames()->portName(panel_panel->card(i),panel_panel->port(i));
for(int j=0;j<i;j++) {
if((panel_panel->card(i)==panel_panel->card(j))&&
(panel_panel->port(i)==panel_panel->port(j))) {
unique=false;
output=panel_panel->outputText(j).toInt();
}
}
if(unique) {

View File

@ -30,7 +30,7 @@ Release: @RPM_RELEASE@
License: GPL
Packager: Fred Gleason <fredg@paravelsystems.com>
Source: rivendell-@VERSION@.tar.gz
Requires: @MYSQL_PKG@ @QT_MYSQL_PKG@ @APACHE_PKG@ curl @USERMODE_PKG@ rsyslog qt5-qtstyleplugins qt5-qttranslations @PYPAD_DEPS@ libxslt icedax
Requires: @MYSQL_PKG@ @QT_MYSQL_PKG@ @APACHE_PKG@ curl @USERMODE_PKG@ rsyslog qt5-qtstyleplugins qt5-qttranslations @PYPAD_DEPS@ libxslt icedax wmctrl
BuildRequires: qt5-qtbase-devel qt5-linguist
BuildRoot: /var/tmp/rivendell-@VERSION@
Obsoletes: rivendell-base < 4.0.0 rivendell-opsguide < 4.0.0 rivendell-pypad < 4.0.0
@ -465,6 +465,7 @@ rm -rf $RPM_BUILD_ROOT
%{_mandir}/man1/rdmetadata.1.gz
%{_mandir}/man1/rdrender.1.gz
%{_mandir}/man1/rmlsend.1.gz
%{_mandir}/man1/rdsinglestart.1.gz
%{_mandir}/man1/rdsoftkeys.1.gz
%{_mandir}/man5/rd.conf.5.gz
%{_mandir}/man8/rddbmgr.8.gz
@ -488,6 +489,7 @@ rm -rf $RPM_BUILD_ROOT
%{_sbindir}/rdrssd
%{_sbindir}/rdmarkerset
%{_sbindir}/rdcleandirs
%{_bindir}/rdsinglestart
%{_sbindir}/rddbmgr
@HPI_FILE1@
@HPI_FILE2@

View File

@ -2,7 +2,7 @@
//
// Test the Rivendell file format converter.
//
// (C) Copyright 2010-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2010-2022 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
@ -43,7 +43,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("audio_convert_test","audio_convert_test",AUDIO_CONVERT_TEST_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"audio_convert_test: %s\n",(const char *)err_msg.toUtf8());
exit(1);
}

View File

@ -2,7 +2,7 @@
//
// Test the Rivendell file format exporter.
//
// (C) Copyright 2010-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2010-2022 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
@ -45,7 +45,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("audio_export_test","audio_export_test",AUDIO_EXPORT_TEST_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"audio_export_test: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -2,7 +2,7 @@
//
// Test Rivendell file importing.
//
// (C) Copyright 2010-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2010-2022 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
@ -46,7 +46,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("audio_import_test","audio_import_test",AUDIO_IMPORT_TEST_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"audio_import_test: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -2,7 +2,7 @@
//
// Test the Rivendell audio file metadata reader.
//
// (C) Copyright 2018-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2018-2022 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
@ -36,7 +36,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("audio_metadata_test","audio_metadata_test",AUDIO_METADATA_TEST_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"audio_metadata_test: %s\n",(const char *)err_msg.toUtf8());
exit(1);
}

View File

@ -2,7 +2,7 @@
//
// Display charset/collation parameters for a DB connection
//
// (C) Copyright 2018-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2018-2022 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
@ -43,7 +43,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDApplication("db_charset_test","rdvairplayd",DB_CHARSET_TEST_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"db_charset_test: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -40,7 +40,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=new RDApplication("delete_test","delete_test",DELETE_TEST_USAGE,this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"delete_test: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -2,7 +2,7 @@
//
// Test Rivendell file downloading.
//
// (C) Copyright 2010-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2010-2022 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
@ -42,7 +42,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=new RDApplication("download_test","download_test",DOWNLOAD_TEST_USAGE,this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"download_test: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -2,7 +2,7 @@
//
// Test Rivendell image storage
//
// (C) Copyright 2010-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2010-2022 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
@ -46,7 +46,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=new RDApplication("feed_image_test","feed_image_test",FEED_IMAGE_TEST_USAGE,this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"feed_image_test: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -2,7 +2,7 @@
//
// Test the Rivendell multicast receiver routines
//
// (C) Copyright 2018-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2018-2022 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
@ -41,7 +41,7 @@ MainObject::MainObject(QObject *parent)
//
rda=new RDApplication("metadata_wildcard_test","metadata_wildcard_test",
METADATA_WILDCARD_TEST_USAGE,this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"metadata_wildcard_test: %s\n",(const char *)err_msg.toUtf8());
exit(1);
}

View File

@ -2,7 +2,7 @@
//
// Test harness for RDWaveWidget
//
// (C) Copyright 2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2021-2022 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
@ -36,7 +36,7 @@ MainWidget::MainWidget(QWidget *parent)
//
rda=new RDApplication("meterstrip_test","meterstrip_test",METERSTRIP_TEST_USAGE,
this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
QMessageBox::critical(this,"meterstrip_test - "+tr("Error"),err_msg);
exit(RDApplication::ExitNoDb);
}

View File

@ -30,7 +30,7 @@ MainObject::MainObject(QObject *parent)
QString err_msg;
rda=new RDApplication("notification_test","notification_test",NOTIFICATION_TEST_USAGE,this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"notification_test: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -41,7 +41,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=new RDApplication("upload_test","upload_test",UPLOAD_TEST_USAGE,this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"upload_test: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -2,7 +2,7 @@
//
// Test harness for RDWavefactory
//
// (C) Copyright 2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2022 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
@ -44,7 +44,7 @@ MainWidget::MainWidget(QWidget *parent)
//
rda=new RDApplication("wavefactory_test","wavefactory_test",WAVEFACTORY_TEST_USAGE,
this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
QMessageBox::critical(this,"wavefactory_test - "+tr("Error"),err_msg);
exit(RDApplication::ExitNoDb);
}

View File

@ -2,7 +2,7 @@
//
// Test harness for RDWaveScene
//
// (C) Copyright 2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2022 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
@ -43,7 +43,7 @@ MainWidget::MainWidget(QWidget *parent)
//
rda=new RDApplication("wavescene_test","wavescene_test",WAVESCENE_TEST_USAGE,
this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
QMessageBox::critical(this,"wavescene_test - "+tr("Error"),err_msg);
exit(RDApplication::ExitNoDb);
}

View File

@ -2,7 +2,7 @@
//
// Test harness for RDWaveWidget
//
// (C) Copyright 2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2021-2022 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
@ -42,7 +42,7 @@ MainWidget::MainWidget(QWidget *parent)
//
rda=new RDApplication("wavewidget_test","wavewidget_test",WAVEWIDGET_TEST_USAGE,
this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
QMessageBox::critical(this,"wavewidget_test - "+tr("Error"),err_msg);
exit(RDApplication::ExitNoDb);
}

View File

@ -2,7 +2,7 @@
##
## Automake.am for rivendell/utils
##
## (C) Copyright 2002-2021 Fred Gleason <fredg@paravelsystems.com>
## (C) Copyright 2002-2022 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 as
@ -42,6 +42,7 @@ SUBDIRS = $(ALSACONFIG_RD_OPT)\
rdpopup\
rdrender\
rdselect_helper\
rdsinglestart\
rdsoftkeys\
rmlsend

View File

@ -362,7 +362,7 @@ Autogen::Autogen()
//
// Open the Database
//
rda=new RDApplication("RDAlsaConfig","rdalsaconfig",RDALSACONFIG_USAGE);
rda=new RDApplication("RDAlsaConfig","rdalsaconfig",RDALSACONFIG_USAGE,this);
if(!rda->open(&err_msg,NULL,false)) {
fprintf(stderr,"rdalsaconfig: unable to open database [%s]\n",
(const char *)err_msg.toUtf8());

View File

@ -2,7 +2,7 @@
//
// Check Rivendell Cuts for Valid Audio
//
// (C) Copyright 2012-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2012-2022 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
@ -43,7 +43,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("rdcheckcuts","rdcheckcuts",RDCHECKCUTS_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"rdcheckcuts: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -49,7 +49,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("rdclilogedit","rdclilogedit",RDCLILOGEDIT_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"rdclilogedit: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -2,7 +2,7 @@
//
// Rivendell file format converter.
//
// (C) Copyright 2017-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2017-2022 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
@ -43,7 +43,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("rdconvert","rdconvert",RDCONVERT_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"rdconvert: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -41,6 +41,16 @@ bool MainObject::RevertSchema(int cur_schema,int set_schema,QString *err_msg)
// NEW SCHEMA REVERSIONS GO HERE...
//
// Revert 367
//
if((cur_schema==367)&&(set_schema<cur_schema)) {
DropColumn("RDLIBRARY","IS_SINGLETON");
DropColumn("RDLOGEDIT","IS_SINGLETON");
WriteSchemaVersion(--cur_schema);
}
//
// Revert 366
//

View File

@ -160,7 +160,7 @@ void MainObject::InitializeSchemaMap() {
global_version_map["3.4"]=317;
global_version_map["3.5"]=346;
global_version_map["3.6"]=347;
global_version_map["4.0"]=366;
global_version_map["4.0"]=367;
}

View File

@ -11359,6 +11359,25 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg)
if(!RDSqlQuery::apply(sql,err_msg)) {
return false;
}
WriteSchemaVersion(++cur_schema);
}
if((cur_schema<367)&&(set_schema>cur_schema)) {
sql=QString("alter table `RDLIBRARY` ")+
"add column `IS_SINGLETON` enum('N','Y') not null default 'Y' "+
"after `SEARCH_LIMITED`";
if(!RDSqlQuery::apply(sql,err_msg)) {
return false;
}
sql=QString("alter table `RDLOGEDIT` ")+
"add column `IS_SINGLETON` enum('N','Y') not null default 'Y' "+
"after `DEFAULT_TRANS_TYPE`";
if(!RDSqlQuery::apply(sql,err_msg)) {
return false;
}
WriteSchemaVersion(++cur_schema);
}

View File

@ -2,7 +2,7 @@
//
// A Batch Deleter for Rivendell.
//
// (C) Copyright 2013-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2013-2022 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
@ -44,7 +44,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("rddelete","rddelete",RDDELETE_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"rddelete: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -2,7 +2,7 @@
//
// A Batch Exporter for Rivendell.
//
// (C) Copyright 2016-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2016-2022 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
@ -57,7 +57,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("rdexport","rdexport",RDEXPORT_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"rdexport: %s\n",(const char *)err_msg.toUtf8());
exit(1);
}

View File

@ -39,7 +39,7 @@ MainWidget::MainWidget(RDConfig *c,QWidget *parent)
// Open the Database
//
rda=new RDApplication("RDGpiMon","rdgpimon",RDGPIMON_USAGE,this);
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
QMessageBox::critical(this,"RDGpiMon - "+tr("Error"),err_msg);
exit(1);
}

View File

@ -109,7 +109,7 @@ MainObject::MainObject(QObject *parent)
//
rda=static_cast<RDApplication *>(new RDCoreApplication("rdimport","rdimport",
RDIMPORT_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"rdimport: %s\n",err_msg.toUtf8().constData());
ErrorExit(RDApplication::ExitNoDb);
}

View File

@ -2,7 +2,7 @@
//
// Command-line tool for setting Rivendell Cut Markers
//
// (C) Copyright 2014-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2014-2022 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
@ -58,7 +58,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("rdmarkerset","rdmarkerset",RDMARKERSET_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"rdmarkerset: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -3,7 +3,7 @@
// Command-line tool for setting Rivendell Cart Metadata
//
// Patrick Linstruth <patrick@deltecent.com>
// (C) Copyright 2019-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2019-2022 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
@ -50,7 +50,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("rdmetadata","rdmetadata",RDMETADATA_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"rdmetadata: %s\n",err_msg.toUtf8().constData());
exit(1);
}

View File

@ -68,7 +68,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("rdrender","rdrender",RDRENDER_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
fprintf(stderr,"rdrender: %s\n",(const char *)err_msg.toUtf8());
exit(1);
}

View File

@ -0,0 +1,48 @@
## Makefile.am
##
## (C) Copyright 2022 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.
##
## Use automake to process this into a Makefile.in
AM_CPPFLAGS = -Wall -DPREFIX=\"$(prefix)\" -Wno-strict-aliasing -std=c++11 -fPIC -I$(top_srcdir)/lib @QT5_CFLAGS@ @MUSICBRAINZ_CFLAGS@ @IMAGEMAGICK_CFLAGS@
LIBS = -L$(top_srcdir)/lib
MOC = @QT_MOC@
# The dependency for qt's Meta Object Compiler (moc)
moc_%.cpp: %.h
$(MOC) $< -o $@
bin_PROGRAMS = rdsinglestart
dist_rdsinglestart_SOURCES = rdsinglestart.cpp rdsinglestart.h
rdsinglestart_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ @QT5_LIBS@ @MUSICBRAINZ_LIBS@ @IMAGEMAGICK_LIBS@
CLEANFILES = *~\
*.exe\
*.idb\
*ilk\
*.obj\
*.pdb\
*.qm\
moc_*
MAINTAINERCLEANFILES = *~\
*.tar.gz\
aclocal.m4\
configure\
Makefile.in\
moc_*

View File

@ -0,0 +1,149 @@
// rdsinglestart.cpp
//
// Start a program so as to allow only a single instance.
//
// (C) Copyright 2022 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 <unistd.h>
#include <QApplication>
#include <QProcess>
#include "rdsinglestart.h"
MainObject::MainObject(QObject *parent)
:QObject(parent)
{
QStringList args;
QProcess *proc=NULL;
//
// Read Command Options
//
RDCmdSwitch *cmd=new RDCmdSwitch("rdsinglestart",RDSINGLESTART_USAGE);
if(cmd->keys()<1) {
perror("missing argument");
exit(1);
}
for(unsigned i=0;i<(cmd->keys()-1);i++) {
}
QStringList f0=cmd->key(cmd->keys()-1).split("/",QString::SkipEmptyParts);
QString program=f0.last().trimmed();
//
// If we're already running, then just raise the window.
//
args.clear();
args.push_back("-l");
proc=new QProcess(this);
proc->start("wmctrl",args);
proc->waitForFinished();
if(proc->exitStatus()!=QProcess::NormalExit) {
perror("wmctrl(1) process crashed");
exit(1);
}
if(proc->exitCode()!=0) {
QString errs=QString::fromUtf8(proc->readAllStandardError());
if(errs.isEmpty()) {
fprintf(stderr,"rdsinglestart: wmctrl(1) not found\n");
}
else {
fprintf(stderr,"rdsinglestart: wmctrl(1) process returned error [%s]\n",
errs.toUtf8().constData());
}
exit(1);
}
bool found=false;
f0=QString::fromUtf8(proc->readAllStandardOutput()).
split("\n",QString::SkipEmptyParts);
for(int i=0;i<f0.size();i++) {
QStringList f1=f0.at(i).split(" ",QString::SkipEmptyParts);
if(f1.size()>=4) {
if(f1.at(3).trimmed().toLower()==program) {
Raise(f1.at(0));
found=true;
}
}
}
delete proc;
if(found) {
exit(0);
}
//
// Otherwise, start a new process
//
Start(cmd);
exit(0);
}
void MainObject::Raise(const QString win_id)
{
QStringList args;
QProcess *proc=NULL;
args.push_back("-i");
args.push_back("-R");
args.push_back(win_id);
proc=new QProcess(this);
proc->start("wmctrl",args);
proc->waitForFinished();
if(proc->exitStatus()!=QProcess::NormalExit) {
perror("wmctrl(1) process crashed");
exit(1);
}
if(proc->exitCode()!=0) {
QString errs=QString::fromUtf8(proc->readAllStandardError());
if(errs.isEmpty()) {
fprintf(stderr,"rdsinglestart: wmctrl(1) not found\n");
}
else {
fprintf(stderr,"rdsinglestart: wmctrl(1) process returned error [%s]\n",
errs.toUtf8().constData());
}
exit(1);
}
delete proc;
}
void MainObject::Start(RDCmdSwitch *cmd)
{
char *args[cmd->keys()+1];
memset(args,0,sizeof(char *)*(cmd->keys()+1));
for(unsigned i=0;i<cmd->keys();i++) {
args[i]=(char *)malloc(cmd->key(i).toUtf8().size()+1);
strcpy(args[i],cmd->key(i).toUtf8().constData());
}
if(fork()==0) {
execvp(args[0],args);
perror("rdsinglestart");
}
exit(0);
}
int main(int argc,char *argv[])
{
QApplication a(argc,argv,false);
new MainObject();
return a.exec();
}

View File

@ -0,0 +1,41 @@
// rdsinglestart.h
//
// Start a program so as to allow only a single instance.
//
// (C) Copyright 2022 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.
//
#ifndef RDSINGLESTART_H
#define RDSINGLESTART_H
#include <QObject>
#include <rdcmd_switch.h>
#define RDSINGLESTART_USAGE "<program>\n"
class MainObject : public QObject
{
public:
MainObject(QObject *parent=0);
private:
void Raise(const QString win_id);
void Start(RDCmdSwitch *cmd);
};
#endif // RDSINGLESTART_H

View File

@ -2,7 +2,7 @@
//
// Rivendell upload/download utility
//
// (C) Copyright 2018-2021 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2018-2022 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
@ -51,7 +51,7 @@ MainObject::MainObject(QObject *parent)
// Open the Database
//
rda=static_cast<RDApplication *>(new RDCoreApplication("webget.cgi","webget.cgi",WEBGET_CGI_USAGE,this));
if(!rda->open(&err_msg)) {
if(!rda->open(&err_msg,NULL,true)) {
TextExit(err_msg,500,LINE_NUMBER);
}