2022-03-25 Fred Gleason <fredg@paravelsystems.com>

* Added '--by-isci' and '--dump-isci-xref' options to rdimport(1).

Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
This commit is contained in:
Fred Gleason 2022-03-25 08:39:52 -04:00
parent a473edf7dc
commit 672bd74a7c
4 changed files with 282 additions and 12 deletions

View File

@ -22947,3 +22947,5 @@
* Fixed a bug in the 'rdxport' service that caused the 'ListLog'
WebAPI call to return null values in the 'description', 'isrc',
'isci', 'recordingMbId' and 'releaseMbId' fields.
2022-03-25 Fred Gleason <fredg@paravelsystems.com>
* Added '--by-isci' and '--dump-isci-xref' options to rdimport(1).

View File

@ -80,6 +80,29 @@
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--by-isci</option>[=<replaceable>service-name</replaceable>]
</term>
<listitem>
<para>
Determine the target cart number by looking it up in the ISCI
cross-reference table, using the ISCI code provided by the
<option>--set-string-isci</option> or
<option>--metadata-pattern</option> options. If
<replaceable>service-name</replaceable> is given, prepend the
Program Code for the specified service followed by an underscore
to the ISCI code when doing the cart number lookup in the ISCI
cross-reference table. Useful for importing sets of copy-split
audio.
</para>
<para>
This option is mutually exclusive with the
<option>--to-cart</option> option.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--cart-number-offset=</option><replaceable>offset</replaceable>
@ -188,6 +211,18 @@
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--dump-isci-xref</option>
</term>
<listitem>
<para>
Print a copy of the current ISCI cross-reference table and then
exit. Useless except for debugging.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--enddate-offset=</option><replaceable>days</replaceable>

View File

@ -2,7 +2,7 @@
//
// A Batch Importer 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
@ -41,6 +41,7 @@
#include <rddisclookup.h>
#include <rdescape_string.h>
#include <rdlibrary_conf.h>
#include <rdstringlist.h>
#include <rdtempdirectory.h>
#include "rdimport.h"
@ -99,7 +100,10 @@ MainObject::MainObject(QObject *parent)
import_send_mail=false;
import_mail_per_file=false;
import_journal=NULL;
import_dump_isci_xref=false;
import_by_isci_program_code="";
import_by_isci=false;
//
// Open the Database
//
@ -171,6 +175,42 @@ MainObject::MainObject(QObject *parent)
import_delete_cuts=true;
rda->cmdSwitch()->setProcessed(i,true);
}
if(rda->cmdSwitch()->key(i)=="--dump-isci-xref") {
import_dump_isci_xref=true;
rda->cmdSwitch()->setProcessed(i,true);
}
if(rda->cmdSwitch()->key(i)=="--by-isci") {
import_by_isci=true;
if(!rda->cmdSwitch()->value(i).isEmpty()) {
RDSvc *svc=new RDSvc(rda->cmdSwitch()->value(i),
rda->station(),rda->config(),this);
if(!svc->exists()) {
Log(LOG_ERR,QString("rdimport: no such service\n"));
ErrorExit(RDApplication::ExitNoSvc);
}
import_by_isci_program_code=svc->programCode();
delete svc;
}
rda->cmdSwitch()->setProcessed(i,true);
}
if(rda->cmdSwitch()->key(i)=="--dump-isci-xref") {
import_dump_isci_xref=true;
rda->cmdSwitch()->setProcessed(i,true);
}
if(rda->cmdSwitch()->key(i)=="--by-isci") {
import_by_isci=true;
if(!rda->cmdSwitch()->value(i).isEmpty()) {
RDSvc *svc=new RDSvc(rda->cmdSwitch()->value(i),
rda->station(),rda->config(),this);
if(!svc->exists()) {
Log(LOG_ERR,QString("rdimport: no such service\n"));
ErrorExit(RDApplication::ExitNoSvc);
}
import_by_isci_program_code=svc->programCode();
delete svc;
}
rda->cmdSwitch()->setProcessed(i,true);
}
if(rda->cmdSwitch()->key(i)=="--startdate-offset") {
import_startdate_offset=rda->cmdSwitch()->value(i).toInt(&ok);
if(!ok) {
@ -476,7 +516,11 @@ MainObject::MainObject(QObject *parent)
Log(LOG_ERR,QString::asprintf("rdimport: --log-filename and --log-syslog are mutually exclusive\n"));
ErrorExit(RDApplication::ExitInvalidOption);
}
if((import_cart_number>0)&&import_by_isci) {
Log(LOG_ERR,QString().sprintf("rdimport: --to-cart and --by-isci are mutually exclusive\n"));
ErrorExit(RDApplication::ExitInvalidOption);
}
import_cut_markers=new MarkerSet();
import_cut_markers->loadMarker(rda->cmdSwitch(),"cut");
import_talk_markers=new MarkerSet();
@ -667,6 +711,18 @@ MainObject::MainObject(QObject *parent)
else {
Log(LOG_INFO,QString(" Delete cuts mode is OFF\n"));
}
if(import_dump_isci_xref) {
Log(LOG_INFO,QString(" Dump ISCI Cross Reference File is ON\n"));
}
else {
Log(LOG_INFO,QString(" Dump ISCI Cross Reference File is OFF\n"));
}
if(import_by_isci) {
Log(LOG_INFO,QString(" Import by ISCI Code is ON\n"));
}
else {
Log(LOG_INFO,QString(" Import by ISCI Code is OFF\n"));
}
if(import_drop_box) {
Log(LOG_INFO,QString(" DropBox mode is ON\n"));
}
@ -838,6 +894,36 @@ MainObject::MainObject(QObject *parent)
}
}
//
// ISCI Code Lookups
//
if(import_dump_isci_xref) {
QString err_msg;
if(LoadIsciXref(&err_msg,rda->system()->isciXreferencePath())) {
for(QMap<QString,RDWaveData *>::const_iterator it=
import_isci_xref.begin();
it!=import_isci_xref.end();it++) {
printf("%32s : %06u | %s\n",it.key().toUtf8().constData(),
it.value()->cartNumber(),
it.value()->title().toUtf8().constData());
}
exit(RDApplication::ExitOk);
}
else {
fprintf(stderr,"rdimport: isci Xref load failed [%s]\n",
err_msg.toUtf8().constData());
exit(RDApplication::ExitImportFailed);
}
}
if(import_by_isci) {
QString err_msg;
if(!LoadIsciXref(&err_msg,rda->system()->isciXreferencePath())) {
fprintf(stderr,"rdimport: isci Xref load failed [%s]\n",
err_msg.toUtf8().constData());
exit(RDApplication::ExitImportFailed);
}
}
//
// Start the email journal
//
@ -977,7 +1063,6 @@ void MainObject::ProcessFileEntry(const QString &entry)
VerifyFile(QString::fromUtf8(globbuf.gl_pathv[i]),&import_cart_number);
}
else {
//ImportFile(QString::fromUtf8(globbuf.gl_pathv[i]),&import_cart_number);
switch(ImportFile(QString::fromUtf8(globbuf.gl_pathv[i]),&import_cart_number)) {
case MainObject::Success:
break;
@ -1118,6 +1203,7 @@ MainObject::Result MainObject::ImportFile(const QString &filename,
wavedata->setTitle(effective_group->generateTitle(filename));
}
/*
//
// Attempt to find a free cart
//
@ -1136,15 +1222,93 @@ MainObject::Result MainObject::ImportFile(const QString &filename,
if(!import_temp_fix_filename.isEmpty()) {
QFile::remove(import_temp_fix_filename);
import_temp_fix_filename="";
*/
if(import_by_isci) {
QString isci=wavedata->isci().trimmed();
if(isci.isEmpty()) {
isci=import_string_isci.trimmed();
if(isci.isEmpty()) {
Log(LOG_WARNING,QString().sprintf(" File \"%s\" has no ISCI code, skipping...\n",
RDGetBasePart(filename).toUtf8().constData()));
wavefile->closeWave();
import_failed_imports++;
import_journal->addFailure(effective_group->name(),filename,
tr("no isci code"));
delete wavefile;
delete wavedata;
delete effective_group;
return MainObject::FileBad;
}
}
if(!import_by_isci_program_code.isEmpty()) {
isci=import_by_isci_program_code+"_"+isci;
}
RDWaveData *wd=import_isci_xref.value(isci,NULL);
if(wd==NULL) {
*cartnum=0;
}
else {
*cartnum=wd->cartNumber();
}
if(*cartnum==0) {
Log(LOG_WARNING,QString().sprintf(" File \"%s\" has no ISCI xreference entry, skipping...\n",
RDGetBasePart(filename).toUtf8().constData()));
wavefile->closeWave();
import_failed_imports++;
import_journal->addFailure(effective_group->name(),filename,
tr("no free cart available in group"));
tr("no isci xref entry"));
delete wavefile;
delete wavedata;
delete effective_group;
return MainObject::NoCart;
return MainObject::FileBad;
}
if(!effective_group->cartNumberValid(*cartnum)) {
Log(LOG_WARNING,QString().sprintf(" File \"%s\" cart number %06u is is not valid in group \"%s\", skipping...\n",
RDGetBasePart(filename).toUtf8().constData(),
*cartnum,
effective_group->name().toUtf8().constData()));
wavefile->closeWave();
import_failed_imports++;
import_journal->addFailure(effective_group->name(),filename,
tr("forbidden cart number"));
delete wavefile;
delete wavedata;
delete effective_group;
return MainObject::FileBad;
}
if(import_string_title.isEmpty()) {
wavedata->setTitle(import_isci_xref.value(isci)->title());
}
}
else {
//
// Attempt to find a free cart
//
if(*cartnum==0) {
*cartnum=effective_group->nextFreeCart();
}
if(*cartnum==0) {
Log(LOG_ERR,QString().sprintf("rdimport: no free carts available in specified group\n"));
wavefile->closeWave();
import_failed_imports++;
import_failed_imports++;
if(import_drop_box) {
if(!import_run) {
NormalExit();
}
if(!import_temp_fix_filename.isEmpty()) {
QFile::remove(import_temp_fix_filename);
import_temp_fix_filename="";
}
import_journal->addFailure(effective_group->name(),filename,
tr("no free cart available in group"));
delete wavefile;
delete wavedata;
delete effective_group;
return MainObject::NoCart;
}
ErrorExit(RDApplication::ExitImportFailed);
}
ErrorExit(RDApplication::ExitImportFailed);
}
//
@ -2136,6 +2300,7 @@ bool MainObject::VerifyPattern(const QString &pattern)
return false;
}
switch(pattern.at(++i).cell()) {
case 'c':
case 'i':
case 'm':
case 'r':
@ -2214,6 +2379,68 @@ void MainObject::WriteTimestampCache(const QString &filename,
}
bool MainObject::LoadIsciXref(QString *err_msg,const QString &filename)
{
char line[1024];
FILE *f=NULL;
bool ok=false;
*err_msg=tr("OK");
for(QMap<QString,RDWaveData *>::const_iterator it=import_isci_xref.begin();
it!=import_isci_xref.end();it++) {
delete it.value();
}
import_isci_xref.clear();
if((f=fopen(filename.toUtf8(),"r"))==NULL) {
*err_msg=strerror(errno);
return false;
}
//
// Skip Header
//
fgets(line,1024,f);
fgets(line,1024,f);
//
// Load Records
//
while(fgets(line,1024,f)!=NULL) {
RDStringList fields=fields.split(',',line,"\"");
if(fields.size()==9) {
for(int i=0;i<fields.size();i++) {
fields[i]=fields[i].replace("\"","").trimmed();
}
unsigned cartnum=fields[3].right(fields[3].length()-1).toUInt(&ok);
if(ok&&(cartnum<=RD_MAX_CART_NUMBER)) {
if(!fields[4].isEmpty()) {
RDWaveData *wd=new RDWaveData();
wd->setCartNumber(cartnum);
wd->setIsci(fields[4].trimmed());
if(!fields[1].trimmed().isEmpty()) {
if(fields[7].isEmpty()) {
wd->setTitle(fields[1].trimmed());
}
else {
wd->setTitle(fields[1].trimmed()+" - "+fields[7]);
}
}
import_isci_xref[fields[4].trimmed()]=wd;
}
}
}
else {
*err_msg=tr("invalid/corrupt data at line")+
QString().sprintf("%d",3+fields.size());
return false;
}
}
return true;
}
bool MainObject::SchedulerCodeExists(const QString &code) const
{
QString sql;

View File

@ -2,7 +2,7 @@
//
// A Batch Importer for Rivendell.
//
// (C) Copyright 2002-2020 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
@ -24,11 +24,11 @@
#include <list>
#include <vector>
#include <qobject.h>
#include <qsqldatabase.h>
#include <qfileinfo.h>
#include <qdatetime.h>
#include <QDateTime>
#include <QFileInfo>
#include <QList>
#include <QMap>
#include <QObject>
#include <QStringList>
#include <rdapplication.h>
@ -36,6 +36,7 @@
#include <rdcut.h>
#include <rdgroup.h>
#include <rdnotification.h>
#include <rdsvc.h>
#include <rdwavedata.h>
#include <rdwavefile.h>
@ -75,6 +76,7 @@ class MainObject : public QObject
void DeleteCuts(unsigned cartnum);
QDateTime GetCachedTimestamp(const QString &filename);
void WriteTimestampCache(const QString &filename,const QDateTime &dt);
bool LoadIsciXref(QString *err_msg,const QString &filename);
bool SchedulerCodeExists(const QString &code) const;
void ReadXmlFile(const QString &basename,RDWaveData *wavedata) const;
void Log(int prio,const QString &msg) const;
@ -160,6 +162,10 @@ class MainObject : public QObject
MarkerSet *import_fadedown_marker;
MarkerSet *import_fadeup_marker;
Journal *import_journal;
QMap<QString,RDWaveData *> import_isci_xref;
bool import_dump_isci_xref;
bool import_by_isci;
QString import_by_isci_program_code;
};