Initial import of CVS-v2_8_branch

This commit is contained in:
Fred Gleason
2014-08-12 15:13:02 -04:00
commit afd67c7af8
1508 changed files with 405304 additions and 0 deletions

76
importers/Makefile.am Normal file
View File

@@ -0,0 +1,76 @@
## automake.am
##
## Automake.am for rivendell/importers
##
## (C) Copyright 2002-2006 Fred Gleason <fredg@paravelsystems.com>
##
## $Id: Makefile.am,v 1.18.8.2 2012/11/29 01:37:35 cvs Exp $
## $Date: 2012/11/29 01:37:35 $
##
## 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 @QT_CXXFLAGS@
INCLUDES = -I$(top_srcdir)/lib
LIBS = @QT_LIBS@ -L$(top_srcdir)/lib
MOC = @QT_MOC@
# The dependency for qt's Meta Object Compiler (moc)
moc_%.cpp: %.h
$(MOC) $< -o $@
bin_PROGRAMS = nexgen_filter\
panel_copy\
rdcatch_copy\
rivendell_filter\
sas_filter\
wings_filter
dist_nexgen_filter_SOURCES = nexgen_filter.cpp nexgen_filter.h
nodist_nexgen_filter_SOURCES = moc_nexgen_filter.cpp
nexgen_filter_LDADD = @LIB_RDLIBS@ @LIBVORBIS@
dist_panel_copy_SOURCES = panel_copy.cpp panel_copy.h
nodist_panel_copy_SOURCES = moc_panel_copy.cpp
panel_copy_LDADD = @LIB_RDLIBS@ @LIBVORBIS@
dist_rdcatch_copy_SOURCES = rdcatch_copy.cpp rdcatch_copy.h
nodist_rdcatch_copy_SOURCES = moc_rdcatch_copy.cpp
rdcatch_copy_LDADD = @LIB_RDLIBS@ @LIBVORBIS@
dist_rivendell_filter_SOURCES = rivendell_filter.cpp rivendell_filter.h
nodist_rivendell_filter_SOURCES = moc_rivendell_filter.cpp
rivendell_filter_LDADD = @LIB_RDLIBS@ @LIBVORBIS@
dist_sas_filter_SOURCES = sas_filter.cpp sas_filter.h
nodist_sas_filter_SOURCES = moc_sas_filter.cpp
sas_filter_LDADD = @LIB_RDLIBS@ @LIBVORBIS@
dist_wings_filter_SOURCES = wings_filter.cpp wings_filter.h
nodist_wings_filter_SOURCES = moc_wings_filter.cpp
wings_filter_LDADD = @LIB_RDLIBS@ @LIBVORBIS@
EXTRA_DIST = export_slax
CLEANFILES = *~\
moc_*
MAINTAINERCLEANFILES = *~\
aclocal.m4\
configure\
Makefile.in\
moc_*\
*.tar.gz

74
importers/export_slax Executable file
View File

@@ -0,0 +1,74 @@
#!/bin/bash
# export_slax
#
# Export the current Rivendell archive as a SLAX module.
#
# (C) Copyright 2006 Fred Gleason <fredg@paravelsystems.com>
#
# $Id: export_slax,v 1.4 2007/02/14 21:48:41 fredg Exp $
# $Date: 2007/02/14 21:48:41 $
#
# 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., 59 Temple Place, Suite 330,
# Boston, MA 02111-1307 USA
#
#
# Check arguments
#
if test -z $1 ; then
echo
echo " export_slax <module-name> [<audio-owner>]"
echo
exit 256
fi
if test -z $2 ; then
AUDIO_OWNER=500
else
AUDIO_OWNER=$2
fi
#
# Clean the build tree
#
BUILD_DIR=/var/tmp/export_slax
rm -rf $BUILD_DIR
#
# Build the package tree
#
mkdir -p $BUILD_DIR/var/lib/mysql/mysql
mkdir -p $BUILD_DIR/var/lib/mysql/Rivendell
chown -R mysql:users $BUILD_DIR/var/lib/mysql
cp -a /var/lib/mysql/mysql $BUILD_DIR/var/lib/mysql/
cp -a /var/lib/mysql/Rivendell $BUILD_DIR/var/lib/mysql/
cp -a /var/snd $BUILD_DIR/var/
chown -R $AUDIO_OWNER:root $BUILD_DIR/var/snd
#
# Generate the package
#
SOURCE_DIR=`pwd`
cd $BUILD_DIR
makepkg --prepend --linkadd y --chown n export_slax.tgz
tgz2mo export_slax.tgz $SOURCE_DIR/$1
cd $SOURCE_DIR
#
# Clean up and exit
#
#rm -r $BUILD_DIR
# End of export_slax

713
importers/nexgen_filter.cpp Normal file
View File

@@ -0,0 +1,713 @@
// nexgen_filter.cpp
//
// A Library import filter for the Prophet NexGen system
//
// (C) Copyright 2012 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: nexgen_filter.cpp,v 1.1.2.8 2013/06/20 20:24:45 cvs Exp $
//
// 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 <stdio.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <errno.h>
#include <qapplication.h>
#include <qstringlist.h>
#include <qfile.h>
#include <qregexp.h>
#include <rddb.h>
#include <rd.h>
#include <rdconfig.h>
#include <rdconf.h>
#include <rdcmd_switch.h>
#include <rdcut.h>
#include <rdwavefile.h>
#include <rdcart.h>
#include <rdcut.h>
#include <rdweb.h>
#include <nexgen_filter.h>
//
// Global Variables
//
RDConfig *rdconfig;
MainObject::MainObject(QObject *parent,const char *name)
: QObject(parent,name)
{
QString group_name;
QString audio_dir;
QString reject_dir="/dev/null";
QStringList xml_files;
bool ok=false;
char tempdir[PATH_MAX];
filter_cart_offset=0;
filter_delete_cuts=false;
filter_normalization_level=0;
filter_verbose=false;
//
// Read Command Options
//
RDCmdSwitch *cmd=
new RDCmdSwitch(qApp->argc(),qApp->argv(),"nexgen_filter",
NEXGEN_FILTER_USAGE);
bool options=true;
for(unsigned i=0;i<cmd->keys();i++) {
if(!options) {
xml_files.push_back(cmd->key(i));
}
else {
if(cmd->key(i)=="--verbose") {
filter_verbose=true;
cmd->setProcessed(i,true);
}
if(cmd->key(i)=="--group") {
group_name=cmd->value(i);
cmd->setProcessed(i,true);
}
if(cmd->key(i)=="--audio-dir") {
audio_dir=cmd->value(i);
cmd->setProcessed(i,true);
}
if(cmd->key(i)=="--reject-dir") {
reject_dir=cmd->value(i);
cmd->setProcessed(i,true);
}
if(cmd->key(i)=="--cart-offset") {
filter_cart_offset=cmd->value(i).toInt(&ok);
if(!ok) {
fprintf(stderr,"nexgen_filter: --cart-offset must be an integer\n");
exit(256);
}
cmd->setProcessed(i,true);
}
if(cmd->key(i)=="--delete-cuts") {
filter_delete_cuts=true;
cmd->setProcessed(i,true);
}
if(cmd->key(i)=="--normalization-level") {
filter_normalization_level=cmd->value(i).toInt(&ok);
if(!ok) {
fprintf(stderr,"nexgen_filter: --cart-offset must be an integer\n");
exit(256);
}
if(filter_normalization_level>0) {
fprintf(stderr,
"nexgen_filter: positive --normalization-level is invalid\n");
exit(256);
}
cmd->setProcessed(i,true);
}
if(!cmd->processed(i)) {
options=false;
xml_files.push_back(cmd->key(i));
}
}
}
delete cmd;
//
// Open Config
//
rdconfig=new RDConfig(RD_CONF_FILE);
rdconfig->load();
//
// Open Database
//
filter_db=QSqlDatabase::addDatabase(rdconfig->mysqlDriver());
if(!filter_db) {
fprintf(stderr,"nexgen_filter: can't open mySQL database\n");
exit(1);
}
filter_db->setDatabaseName(rdconfig->mysqlDbname());
filter_db->setUserName(rdconfig->mysqlUsername());
filter_db->setPassword(rdconfig->mysqlPassword());
filter_db->setHostName(rdconfig->mysqlHostname());
if(!filter_db->open()) {
fprintf(stderr,"nexgen_filter: unable to connect to mySQL Server\n");
filter_db->removeDatabase(rdconfig->mysqlDbname());
exit(1);
}
//
// RIPCD Connection
//
filter_ripc=new RDRipc("");
filter_ripc->connectHost("localhost",RIPCD_TCP_PORT,rdconfig->password());
//
// Station Configuration
//
filter_rdstation=new RDStation(rdconfig->stationName());
//
// Validate Arguments
//
if(group_name.isEmpty()) {
fprintf(stderr,"nexgen_filter: missing group name\n");
exit(256);
}
filter_group=new RDGroup(group_name);
if(!filter_group->exists()) {
fprintf(stderr,"nexgen_filter: group \"%s\" does not exist\n",
(const char *)group_name);
exit(256);
}
filter_audio_dir=new QDir(audio_dir);
if(!audio_dir.isEmpty()) {
if(!filter_audio_dir->exists()) {
fprintf(stderr,"nexgen_filter: audio directory \"%s\" does not exist\n",
(const char *)audio_dir);
exit(256);
}
if(!filter_audio_dir->isReadable()) {
fprintf(stderr,"nexgen_filter: audio directory \"%s\" is not readable\n",
(const char *)audio_dir);
exit(256);
}
}
//
// Configure Reject Directory
//
if(reject_dir=="/dev/null") {
filter_reject_dir=NULL;
}
else {
filter_reject_dir=new QDir(reject_dir);
if(!filter_reject_dir->exists()) {
fprintf(stderr,"nexgen_filter: reject directory \"%s\" does not exist\n",
(const char *)reject_dir);
exit(256);
}
}
//
// Create Temp Directory
//
strncpy(tempdir,RDTempDir()+"/nexgen_filterXXXXXX",PATH_MAX);
filter_temp_dir=new QDir(mkdtemp(tempdir));
filter_temp_audiofile=filter_temp_dir->canonicalPath()+"/audio.dat";
//
// Main Loop
//
for(unsigned i=0;i<xml_files.size();i++) {
if(IsXmlFile(xml_files[i])) {
if(audio_dir.isEmpty()) {
fprintf(stderr,"unable to process \"%s\" [no --audio-dir specified]\n",
(const char *)xml_files[i]);
}
else {
ProcessXmlFile(xml_files[i]);
}
}
else {
ProcessArchive(xml_files[i]);
}
}
//
// Clean Up
//
rmdir(filter_temp_dir->canonicalPath());
exit(0);
}
void MainObject::ProcessArchive(const QString &filename)
{
int fd_in=-1;
int fd_out=-1;
char tempdir[PATH_MAX];
char *data=NULL;
QString dir;
char header[105];
uint32_t len;
QString xmlfile;
QString wavfile;
QStringList files;
struct stat stat;
blksize_t blksize=1024;
ssize_t n=0;
//
// Allocate Default Buffer
//
data=(char *)malloc(1024);
//
// Create temporary directory
//
snprintf(tempdir,PATH_MAX,"%s/XXXXXX",(const char *)RDTempDir());
if(mkdtemp(tempdir)==NULL) {
return;
}
dir=tempdir;
//
// Open Archive
//
if((fd_in=open(filename,O_RDONLY))<0) {
return;
}
//
// Write Out File Components
//
while((read(fd_in,header,104)==104)&&(strncmp(header,"FR:",3)==0)) {
files.push_back(dir+"/"+RDGetBasePart(QString(header+3).replace("\\","/")));
if(files.back().right(4).lower()==".xml") {
xmlfile=files.back();
}
if(files.back().right(4).lower()==".wav") {
wavfile=files.back();
}
len=((0xFF&header[103])<<24)+((0xFF&header[102])<<16)+
((0xFF&header[101])<<8)+(0xFF&header[100]);
if((fd_out=open(files.back(),O_CREAT|O_WRONLY|O_TRUNC,S_IRUSR|S_IWUSR))<0) {
fprintf(stderr,"unable to write temporary file \"%s\" [%s].\n",
(const char *)files.back(),strerror(errno));
return;
}
if(fstat(fd_out,&stat)==0) {
blksize=stat.st_blksize;
data=(char *)realloc(data,blksize);
}
for(uint32_t i=blksize;i<len;i+=blksize) {
n=read(fd_in,data,blksize);
write(fd_out,data,n);
}
n=read(fd_in,data,len%blksize);
write(fd_out,data,n);
close(fd_out);
}
close(fd_in);
//
// Run Import
//
if((!xmlfile.isEmpty())&&(!wavfile.isEmpty())) {
ProcessXmlFile(xmlfile,wavfile,filename);
}
//
// Clean Up
//
for(unsigned i=0;i<files.size();i++) {
unlink(files[i]);
}
rmdir(tempdir);
free(data);
}
void MainObject::ProcessXmlFile(const QString &xml,const QString &wavname,
const QString &arcname)
{
RDCart *cart=NULL;
RDCut *cut=NULL;
RDWaveData data;
QString filename;
int cartnum;
QString sql;
RDSqlQuery *q;
QString delete_cuts_switch="";
//
// Read Metadata
//
if(!OpenXmlFile(xml,&data,&cartnum,&filename)) {
fprintf(stderr,"unable to parse XML file \"%s\"\n",(const char *)xml);
WriteReject(xml);
return;
}
if(!wavname.isEmpty()) {
filename=wavname;
}
//
// Sanity Checks
//
if((cartnum<1)||(cartnum>999999)) {
fprintf(stderr,"calculated cart number [%d] is invalid\n",cartnum);
WriteReject(xml);
return;
}
if(filter_group->enforceCartRange()) {
if((cartnum<(int)filter_group->defaultLowCart())||
(cartnum>(int)filter_group->defaultHighCart())) {
fprintf(stderr,
"calculated cart number [%d] is invalid for group \"%s\"\n",
cartnum,(const char *)filter_group->name());
WriteReject(xml);
return;
}
}
//
// Prepare Audio
//
if(!PreprocessAudio(filename)) {
WriteReject(xml);
return;
}
//
// Import Audio
//
Print(QString().sprintf("Importing cart %06d",cartnum));
if(!data.title().isEmpty()) {
Print(QString().sprintf(" [%s",(const char *)data.title()));
if(!data.artist().isEmpty()) {
Print(QString().sprintf("/%s",(const char *)data.artist()));
}
Print(QString().sprintf("]"));
}
if(arcname.isEmpty()) {
Print(QString().sprintf(" from %s ...",(const char *)filename));
}
else {
Print(QString().sprintf(" from %s ...",(const char *)arcname));
}
if(filter_delete_cuts) {
delete_cuts_switch="--delete-cuts ";
}
if(system(QString().sprintf("rdimport --autotrim-level=0 --normalization-level=%d --to-cart=%d ",
filter_normalization_level,cartnum)+
+delete_cuts_switch+filter_group->name()+" "+
filter_temp_audiofile)!=0) {
Print(QString().sprintf(" aborted.\n"));
fprintf(stderr,"import of \"%s\" failed\n",(const char *)filename);
WriteReject(xml);
return;
}
Print(QString().sprintf(" done.\n"));
unlink(filter_temp_audiofile);
//
// Apply Metadata
//
cart=new RDCart(cartnum);
cart->setMetadata(&data);
delete cart;
sql=
QString().sprintf("select CUT_NAME from CUTS where CART_NUMBER=%d",cartnum)+
" order by ORIGIN_DATETIME desc";
q=new RDSqlQuery(sql);
if(q->first()) {
cut=new RDCut(q->value(0).toString());
cut->setMetadata(&data);
delete cut;
}
delete q;
}
bool MainObject::OpenXmlFile(const QString &xml,RDWaveData *data,
int *cartnum,QString *filename)
{
FILE *f=NULL;
char line[1024];
int crossfade=-1;
int fadeup_start=-1;
int fadeup_len=-1;
if((f=fopen(xml,"r"))==NULL) {
return false;
}
if(fgets(line,1024,f)==NULL) {
fclose(f);
return false;
}
if(!QString(line).contains("XMLDAT")) {
fclose(f);
return false;
}
while(fgets(line,1024,f)!=NULL) {
ProcessXmlLine(line,data,cartnum,filename,&crossfade,&fadeup_start,
&fadeup_len);
}
if((fadeup_start>=0)&&(fadeup_len>=0)) { // Calculate Start Marker
data->setStartPos(fadeup_start);
data->setEndPos(data->endPos()+fadeup_start);
data->setFadeUpPos(fadeup_start+fadeup_len);
}
if((crossfade!=-1)&&(data->endPos()>0)) { // Calculate Segue
data->setSegueStartPos(data->endPos()-crossfade);
data->setSegueEndPos(data->endPos());
}
fclose(f);
return true;
}
void MainObject::ProcessXmlLine(const QString &line,RDWaveData *data,
int *cartnum,QString *filename,
int *crossfade,int *fadeup_start,
int *fadeup_len)
{
QString tag=
line.mid(line.find("<")+1,line.find(">")-line.find("<")-1).lower();
QString value=line.mid(line.find(">")+1,line.findRev("<")-line.find(">")-1);
// printf("%s: %s\n",(const char *)tag,(const char *)value);
if(tag=="file_name") {
*filename=filter_audio_dir->canonicalPath()+"/"+
value.right(value.length()-value.findRev('\\')-1);
}
if(tag=="cart") {
*cartnum=value.toUInt()+filter_cart_offset;
data->setMetadataFound(true);
}
if(tag=="title") {
data->setTitle(RDXmlUnescape(value));
data->setMetadataFound(true);
}
if(tag=="artist") {
data->setArtist(RDXmlUnescape(value));
data->setMetadataFound(true);
}
if(tag=="album") {
data->setAlbum(RDXmlUnescape(value));
data->setMetadataFound(true);
}
if(tag=="label") {
data->setLabel(RDXmlUnescape(value));
data->setMetadataFound(true);
}
if(tag=="composer") {
data->setComposer(RDXmlUnescape(value));
data->setMetadataFound(true);
}
if(tag=="licensor") {
data->setLicensingOrganization(RDXmlUnescape(value));
data->setMetadataFound(true);
}
if(tag=="user_define") {
data->setUserDefined(RDXmlUnescape(value));
data->setMetadataFound(true);
}
if(tag=="isrc") {
data->setIsrc(value.replace("-",""));
data->setMetadataFound(true);
}
if(tag=="modified_time") {
QDateTime dt=GetDateTime(value);
data->setOriginationDate(dt.date());
data->setOriginationTime(dt.time());
data->setMetadataFound(true);
}
if(tag=="start_time") {
QDateTime dt=GetDateTime(value);
data->setStartDate(dt.date());
data->setStartTime(dt.time());
data->setMetadataFound(true);
}
if(tag=="end_time") {
QDateTime dt=GetDateTime(value);
data->setEndDate(dt.date());
data->setEndTime(dt.time());
data->setMetadataFound(true);
}
if(tag=="intro_start") {
data->setStartPos(value.toInt());
data->setMetadataFound(true);
}
if(tag=="intro_3") {
if(value.toInt()>0) {
data->setIntroStartPos(0);
data->setIntroEndPos(value.toInt());
}
}
if(tag=="hookstart") {
if(value.toInt()>0) {
data->setHookStartPos(value.toInt());
}
}
if(tag=="hookend") {
if(value.toInt()>0) {
data->setHookEndPos(value.toInt());
}
}
/*
if(tag=="length") {
data->setEndPos(value.toInt());
data->setMetadataFound(true);
}
*/
if(tag=="runtime") {
data->setEndPos(value.toInt());
data->setMetadataFound(true);
}
if(tag=="isci_code") {
data->setIsci(value);
data->setMetadataFound(true);
}
//
// Used for calculating segue markers later
//
if(tag=="cross_fade") {
*crossfade=value.toInt();
}
if(tag=="fade_up_start") {
*fadeup_start=value.toInt();
}
if(tag=="fade_up_length") {
*fadeup_len=value.toInt();
}
}
bool MainObject::PreprocessAudio(QString filename)
{
int fd=-1;
char c;
if((fd=open(filename,O_RDONLY))<0) {
filename=SwapCase(filename);
if((fd=open(filename,O_RDONLY))<0) {
fprintf(stderr,"unable to open audio file \"%s\"\n",
(const char *)filename);
return false;
}
}
lseek(fd,20,SEEK_SET);
if(read(fd,&c,1)!=1) {
close(fd);
fprintf(stderr,"truncated audio file \"%s\"\n",(const char *)filename);
return false;
}
close(fd);
if(c==80) { // MPEG Audio
if(system(QString("madplay -Q -o wave:")+filter_temp_audiofile+" "+filename)!=0) {
fprintf(stderr,"MPEG converter error with file \"%s\"\n",
(const char *)filename);
return false;
}
}
else { // PCM Audio
if(symlink(filename,filter_temp_audiofile)!=0) {
fprintf(stderr,"unable to create symlink \"%s\"\n",
(const char *)filter_temp_audiofile);
return false;
}
}
return true;
}
void MainObject::WriteReject(const QString &filename)
{
if(filter_reject_dir!=NULL) {
if(QFile::exists(filename)) {
if(!RDCopy(filename,filter_reject_dir->canonicalPath()+"/"+
RDGetBasePart(filename))) {
fprintf(stderr,"Unable to write to \"%s\"\n",
(const char *)filter_reject_dir->path());
}
}
}
}
QDateTime MainObject::GetDateTime(const QString &str) const
{
QStringList fields;
QStringList dates;
QStringList times;
QDateTime ret;
fields=fields.split(" ",str);
if(fields.size()==2) {
dates=dates.split("/",fields[0]);
if(dates.size()==3) {
times=times.split(":",fields[1]);
if(times.size()==3) {
ret=
QDateTime(QDate(dates[2].toInt(),dates[0].toInt(),dates[1].toInt()),
QTime(times[0].toInt(),times[1].toInt(),times[2].toInt()));
}
}
}
return ret;
}
QString MainObject::SwapCase(const QString &str) const
{
QStringList parts=parts.split(".",str);
if(parts[parts.size()-1].contains(QRegExp("*[a-z]*",true,true))>0) {
parts[parts.size()-1]=parts[parts.size()-1].upper();
}
else {
parts[parts.size()-1]=parts[parts.size()-1].lower();
}
return parts.join(".");
}
bool MainObject::IsXmlFile(const QString &filename)
{
int fd=-1;
char data[10];
if((fd=open(filename,O_RDONLY))<0) {
return false;
}
if(read(fd,data,8)!=8) {
close(fd);
return false;
}
close(fd);
data[8]=0;
return strncmp(data,"<XMLDAT>",8)==0;
}
void MainObject::Print(const QString &msg) const
{
if(filter_verbose) {
printf("%s",(const char *)msg);
fflush(stdout);
}
}
int main(int argc,char *argv[])
{
QApplication a(argc,argv,false);
new MainObject(NULL,"main");
return a.exec();
}

77
importers/nexgen_filter.h Normal file
View File

@@ -0,0 +1,77 @@
// nexgen_filter.h
//
// A Library import filter for the Prophet NexGen system
//
// (C) Copyright 2012 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: nexgen_filter.h,v 1.1.2.5 2013/06/20 20:24:45 cvs Exp $
//
// 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 NEXGEN_FILTER_H
#define NEXGEN_FILTER_H
#include <stdio.h>
#include <qobject.h>
#include <qapplication.h>
#include <qsqldatabase.h>
#include <qdatetime.h>
#include <qdir.h>
#include <rdstation.h>
#include <rdripc.h>
#include <rdgroup.h>
#include <rdwavedata.h>
#define NEXGEN_FILTER_USAGE "[options] <xml-file>|<pkt-file> [...]\n\nImport audio from a Prophet NexGen system, using metadata contained in\none or more XML files. Options are:\n\n--group=<group-name>\n The Rivendell group to use. This option is mandatory and has no default.\n\n--audio-dir=<path>\n The full path to the directory containing the audio files. This option\n is ignored when importing PKT files, but mandatory for importing\n using XML data. It has no default.\n\n--reject-dir=<path>\n The full path to the directory in which to place copies of XML files\n which were unable to be processed. Default is '/dev/null'.\n\n--cart-offset=<offset>\n Apply integer <offset> to the NexGen cart number before importing.\n Default is '0'.\n\n--delete-cuts\n If the destination cart already exists, delete any existing cuts\n within it before importing.\n\n--normalization-level=<level>\n The level to use for normalizing the audio, in dBFS. Specifying '0'\n will turn off normalization. Default is '0'.\n\n--verbose\n Print status messages as files are processed.\n\n<xml-file> [..]\n Filespec for XML file(s) containing import metadata.\n\n"
class MainObject : public QObject
{
Q_OBJECT
public:
MainObject(QObject *parent=0,const char *name=0);
private:
void ProcessArchive(const QString &filename);
void ProcessXmlFile(const QString &xml,const QString &wavname="",
const QString &arcname="");
bool OpenXmlFile(const QString &xml,RDWaveData *data,int *cartnum,
QString *filename);
void ProcessXmlLine(const QString &line,RDWaveData *data,int *cartnum,
QString *filename,int *crossfade,int *fadeup_start,
int *fadeup_len);
bool PreprocessAudio(QString filename);
void WriteReject(const QString &filename);
QDateTime GetDateTime(const QString &str) const;
QString SwapCase(const QString &str) const;
bool IsXmlFile(const QString &filename);
void Print(const QString &msg) const;
RDGroup *filter_group;
QDir *filter_audio_dir;
QDir *filter_reject_dir;
QDir *filter_temp_dir;
QString filter_temp_audiofile;
int filter_cart_offset;
bool filter_delete_cuts;
int filter_normalization_level;
RDStation *filter_rdstation;
RDRipc *filter_ripc;
QSqlDatabase *filter_db;
bool filter_verbose;
};
#endif

219
importers/panel_copy.cpp Normal file
View File

@@ -0,0 +1,219 @@
// panel_copy.cpp
//
// An RDCatch event copier.
//
// (C) Copyright 2002-2005 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: panel_copy.cpp,v 1.7 2010/07/29 19:32:32 cvs Exp $
// $Date: 2010/07/29 19:32:32 $
//
// 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 <stdio.h>
#include <unistd.h>
#include <qapplication.h>
#include <rddb.h>
#include <rd.h>
#include <dbversion.h>
#include <panel_copy.h>
#include <rdcmd_switch.h>
MainObject::MainObject(QObject *parent,const char *name)
: QObject(parent,name)
{
bool found=false;
QString src_hostname;
QString dest_hostname;
QString src_station;
QString dest_station;
QString sql;
RDSqlQuery *q;
RDSqlQuery *q1;
//
// Read Command Options
//
RDCmdSwitch *cmd=
new RDCmdSwitch(qApp->argc(),qApp->argv(),"panel_copy",
PANEL_COPY_USAGE);
delete cmd;
rd_config=new RDConfig(RD_CONF_FILE);
rd_config->load();
//
// Read Switches
//
for(int i=1;i<qApp->argc();i+=2) {
found=false;
if(QString(qApp->argv()[i])=="-h") { // Source mySQL Hostname
if((i+1)==qApp->argc()) {
fprintf(stderr,"panel_copy: invalid argument\n");
exit(256);
}
src_hostname=qApp->argv()[i+1];
found=true;
}
if(QString(qApp->argv()[i])=="-H") { // Source mySQL Hostname
if((i+1)==qApp->argc()) {
fprintf(stderr,"panel_copy: invalid argument\n");
exit(256);
}
dest_hostname=qApp->argv()[i+1];
found=true;
}
if(!found) {
fprintf(stderr,"panel_copy: invalid argument\n");
exit(256);
}
}
if(src_hostname.isEmpty()) {
fprintf(stderr,"panel_copy: invalid source mySQL hostname\n");
exit(256);
}
if(dest_hostname.isEmpty()) {
fprintf(stderr,"panel_copy: invalid destination mySQL hostname\n");
exit(256);
}
if(src_hostname==dest_hostname) {
fprintf(stderr,"panel_copy: cannot copy a database onto itself\n");
exit(256);
}
//
// Open Databases
//
src_db=QSqlDatabase::addDatabase("QMYSQL3","SRCDB");
if(!src_db) {
fprintf(stderr,"panel_copy: can't open source mySQL database\n");
exit(1);
}
src_db->setDatabaseName(rd_config->mysqlDbname());
src_db->setUserName(rd_config->mysqlUsername());
src_db->setPassword(rd_config->mysqlPassword());
src_db->setHostName(src_hostname);
if(!src_db->open()) {
fprintf(stderr,"panel_copy: unable to connect to source mySQL server\n");
src_db->removeDatabase(rd_config->mysqlDbname());
exit(256);
}
dest_db=QSqlDatabase::addDatabase("QMYSQL3","DESTDB");
if(!dest_db) {
fprintf(stderr,"panel_copy: can't open destination mySQL database\n");
exit(1);
}
dest_db->setDatabaseName(rd_config->mysqlDbname());
dest_db->setUserName(rd_config->mysqlUsername());
dest_db->setPassword(rd_config->mysqlPassword());
dest_db->setHostName(dest_hostname);
if(!dest_db->open()) {
fprintf(stderr,
"panel_copy: unable to connect to destination mySQL server\n");
dest_db->removeDatabase(rd_config->mysqlDbname());
exit(256);
}
//
// Check Database Versions
//
sql="select DB from VERSION";
q=new RDSqlQuery(sql,src_db);
if(!q->first()) {
fprintf(stderr,
"panel_copy: unable to read source database version\n");
exit(256);
}
if(q->value(0).toInt()!=RD_VERSION_DATABASE) {
fprintf(stderr,"panel_copy: source database version mismatch\n");
exit(256);
}
delete q;
q=new RDSqlQuery(sql,dest_db);
if(!q->first()) {
fprintf(stderr,
"panel_copy: unable to read destination database version\n");
exit(256);
}
if(q->value(0).toInt()!=RD_VERSION_DATABASE) {
fprintf(stderr,"panel_copy: destination database version mismatch\n");
exit(256);
}
delete q;
//
// Confirmation Prompt
//
printf("\n");
printf("****** WARNING ******\n");
printf(" This operation will OVERWRITE ALL SOUNDPANEL BUTTON ASSIGNMENTS on the destination database!");
printf(" Press RETURN to continue, or CNTL-C to abort.");
printf("\n");
while(getchar()!=10);
printf("Copying button assignments...");
fflush(stdout);
//
// Delete current destination entries
//
sql="delete from PANELS";
q=new RDSqlQuery(sql,dest_db);
delete q;
//
// Copy Entries
//
sql="select TYPE,OWNER,PANEL_NO,ROW_NO,COLUMN_NO,LABEL,CART,DEFAULT_COLOR\
from PANELS";
q=new RDSqlQuery(sql,src_db);
while(q->next()) {
sql=QString().sprintf("insert into PANELS set \
TYPE=%d,\
OWNER=\"%s\",\
PANEL_NO=%d,\
ROW_NO=%d,\
COLUMN_NO=%d,\
LABEL=\"%s\",\
CART=%d,\
DEFAULT_COLOR=\"%s\"",
q->value(0).toInt(),
(const char *)q->value(1).toString(),
q->value(2).toInt(),
q->value(3).toInt(),
q->value(4).toInt(),
(const char *)q->value(5).toString(),
q->value(6).toInt(),
(const char *)q->value(7).toString());
q1=new RDSqlQuery(sql,dest_db);
delete q1;
}
delete q;
printf("done.\n");
exit(0);
}
int main(int argc,char *argv[])
{
QApplication a(argc,argv,false);
new MainObject(NULL,"main");
return a.exec();
}

48
importers/panel_copy.h Normal file
View File

@@ -0,0 +1,48 @@
// panel_copy.h
//
// A utility for copying SoundPanel assignments between databases.
//
// (C) Copyright 2002-2005 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: panel_copy.h,v 1.5 2010/07/29 19:32:32 cvs Exp $
// $Date: 2010/07/29 19:32:32 $
//
// 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 PANEL_COPY_H
#define PANEL_COPY_H
#include <qobject.h>
#include <qapplication.h>
#include <qsqldatabase.h>
#include <rdconfig.h>
#define PANEL_COPY_USAGE "-h <src-mysql-host> -H <dest-mysql-host>\n"
class MainObject : public QObject
{
Q_OBJECT
public:
MainObject(QObject *parent=0,const char *name=0);
private:
QSqlDatabase *src_db;
QSqlDatabase *dest_db;
RDConfig *rd_config;
};
#endif

335
importers/rdcatch_copy.cpp Normal file
View File

@@ -0,0 +1,335 @@
// rdcatch_copy.cpp
//
// An RDCatch event copier.
//
// (C) Copyright 2002-2005 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: rdcatch_copy.cpp,v 1.8 2010/07/29 19:32:32 cvs Exp $
// $Date: 2010/07/29 19:32:32 $
//
// 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 <stdio.h>
#include <unistd.h>
#include <qapplication.h>
#include <rd.h>
#include <dbversion.h>
#include <rdcatch_copy.h>
#include <rdcmd_switch.h>
#include <rddb.h>
MainObject::MainObject(QObject *parent,const char *name)
: QObject(parent,name)
{
bool found=false;
QString src_hostname;
QString dest_hostname;
QString src_station;
QString dest_station;
QString sql;
RDSqlQuery *q;
RDSqlQuery *q1;
//
// Read Command Options
//
RDCmdSwitch *cmd=
new RDCmdSwitch(qApp->argc(),qApp->argv(),"rdcatch_copy",
RDCATCH_COPY_USAGE);
delete cmd;
rd_config=new RDConfig(RD_CONF_FILE);
rd_config->load();
//
// Read Switches
//
for(int i=1;i<qApp->argc();i+=2) {
found=false;
if(QString(qApp->argv()[i])=="-h") { // Source mySQL Hostname
if((i+1)==qApp->argc()) {
fprintf(stderr,"rdcatch_copy: invalid argument\n");
exit(256);
}
src_hostname=qApp->argv()[i+1];
found=true;
}
if(QString(qApp->argv()[i])=="-s") { // Source Rivendell Host
if((i+1)==qApp->argc()) {
fprintf(stderr,"rdcatch_copy: invalid argument\n");
exit(256);
}
src_station=qApp->argv()[i+1];
found=true;
}
if(QString(qApp->argv()[i])=="-H") { // Source mySQL Hostname
if((i+1)==qApp->argc()) {
fprintf(stderr,"rdcatch_copy: invalid argument\n");
exit(256);
}
dest_hostname=qApp->argv()[i+1];
found=true;
}
if(QString(qApp->argv()[i])=="-S") { // Source Rivendell Host
if((i+1)==qApp->argc()) {
fprintf(stderr,"rdcatch_copy: invalid argument\n");
exit(256);
}
dest_station=qApp->argv()[i+1];
found=true;
}
if(!found) {
fprintf(stderr,"rdcatch_copy: invalid argument\n");
exit(256);
}
}
if(src_hostname.isEmpty()) {
fprintf(stderr,"rdcatch_copy: invalid source mySQL hostname\n");
exit(256);
}
if(src_station.isEmpty()) {
fprintf(stderr,"rdcatch_copy: invalid source Rivendell host\n");
exit(256);
}
if(dest_hostname.isEmpty()) {
fprintf(stderr,"rdcatch_copy: invalid destination mySQL hostname\n");
exit(256);
}
if(dest_station.isEmpty()) {
fprintf(stderr,"rdcatch_copy: invalid destination Rivendell host\n");
exit(256);
}
//
// Open Databases
//
src_db=QSqlDatabase::addDatabase("QMYSQL3");
if(!src_db) {
fprintf(stderr,"rdcatch_copy: can't open source mySQL database\n");
exit(1);
}
src_db->setDatabaseName(rd_config->mysqlDbname());
src_db->setUserName(rd_config->mysqlUsername());
src_db->setPassword(rd_config->mysqlPassword());
src_db->setHostName(src_hostname);
if(!src_db->open()) {
fprintf(stderr,"rdcatch_copy: unable to connect to source mySQL server\n");
src_db->removeDatabase(rd_config->mysqlDbname());
exit(256);
}
if(src_hostname==dest_hostname) {
if(src_station==dest_station) {
fprintf(stderr,"rdcatch_copy: cannot copy a host configuration onto itself\n");
exit(256);
}
else {
dest_db=src_db;
}
}
else {
dest_db=QSqlDatabase::addDatabase("QMYSQL3");
if(!dest_db) {
fprintf(stderr,"rdcatch_copy: can't open destination mySQL database\n");
exit(1);
}
dest_db->setDatabaseName(rd_config->mysqlDbname());
dest_db->setUserName(rd_config->mysqlUsername());
dest_db->setPassword(rd_config->mysqlPassword());
dest_db->setHostName(dest_hostname);
if(!dest_db->open()) {
fprintf(stderr,
"rdcatch_copy: unable to connect to destination mySQL server\n");
dest_db->removeDatabase(rd_config->mysqlDbname());
exit(256);
}
}
//
// Check Database Versions
//
sql="select DB from VERSION";
q=new RDSqlQuery(sql,src_db);
if(!q->first()) {
fprintf(stderr,
"rdcatch_copy: unable to read source database version\n");
exit(256);
}
if(q->value(0).toInt()!=RD_VERSION_DATABASE) {
fprintf(stderr,"rdcatch_copy: source database version mismatch\n");
exit(256);
}
delete q;
q=new RDSqlQuery(sql,dest_db);
if(!q->first()) {
fprintf(stderr,
"rdcatch_copy: unable to read destination database version\n");
exit(256);
}
if(q->value(0).toInt()!=RD_VERSION_DATABASE) {
fprintf(stderr,"rdcatch_copy: destination database version mismatch\n");
exit(256);
}
delete q;
//
// Check Rivendell Hosts
//
sql=QString().sprintf("select NAME from STATIONS where NAME=\"%s\"",
(const char *)src_station);
q=new RDSqlQuery(sql,src_db);
if(!q->first()) {
fprintf(stderr,
"rdcatch_copy: source Rivendell host doesn't exist\n");
exit(256);
}
delete q;
sql=QString().sprintf("select NAME from STATIONS where NAME=\"%s\"",
(const char *)dest_station);
q=new RDSqlQuery(sql,dest_db);
if(!q->first()) {
fprintf(stderr,
"rdcatch_copy: destination Rivendell host doesn't exist\n");
exit(256);
}
delete q;
//
// Confirmation Prompt
//
printf("\n");
printf("****** WARNING ******\n");
printf(" This operation will OVERWRITE ALL RDCATCH EVENTS on the destination Host!");
printf(" Press RETURN to continue, or CNTL-C to abort.");
printf("\n");
while(getchar()!=10);
printf("Copying events...");
fflush(stdout);
//
// Delete current destination entries
//
sql=QString().sprintf("delete from RECORDINGS where STATION_NAME\"%s\"",
(const char *)dest_station);
q=new RDSqlQuery(sql,dest_db);
delete q;
//
// Copy Entries
//
sql=QString().sprintf("select IS_ACTIVE,TYPE,CHANNEL,CUT_NAME,SUN,MON,TUE,\
WED,THU,FRI,SAT,DESCRIPTION,START_TYPE,START_TIME,\
START_LENGTH,START_MATRIX,START_LINE,START_OFFSET,\
END_TYPE,END_TIME,END_LENGTH,END_MATRIX,END_LINE,\
LENGTH,TRIM_THRESHOLD,NORMALIZE_LEVEL,\
STARTDATE_OFFSET,ENDDATE_OFFSET,FORMAT,CHANNELS,\
SAMPRATE,BITRATE,QUALITY,MACRO_CART,SWITCH_INPUT,\
SWITCH_OUTPUT,EXIT_CODE,ONE_SHOT,URL,URL_USERNAME,\
URL_PASSWORD from RECORDINGS\
where STATION_NAME=\"%s\"",
(const char *)src_station);
q=new RDSqlQuery(sql,src_db);
while(q->next()) {
sql=QString().sprintf("insert into RECORDINGS set IS_ACTIVE=\"%s\",\
TYPE=%d,CHANNEL=%u,CUT_NAME=\"%s\",SUN=\"%s\",\
MON=\"%s\",TUE=\"%s\",WED=\"%s\",THU=\"%s\",\
FRI=\"%s\",SAT=\"%s\",DESCRIPTION=\"%s\",\
START_TYPE=%d,START_TIME=\"%s\",START_LENGTH=%d,\
START_MATRIX=%d,START_LINE=%d,START_OFFSET=%d,\
END_TYPE=%d,END_TIME=\"%s\",END_LENGTH=%d,\
END_MATRIX=%d,END_LINE=%d,LENGTH=%u,\
TRIM_THRESHOLD=%d,NORMALIZE_LEVEL=%d,\
STARTDATE_OFFSET=%u,ENDDATE_OFFSET=%u,FORMAT=%d,\
CHANNELS=%d,SAMPRATE=%d,BITRATE=%d,QUALITY=%d,\
MACRO_CART=%d,SWITCH_INPUT=%d,SWITCH_OUTPUT=%d,\
EXIT_CODE=%d,ONE_SHOT=\"%s\",URL=\"%s\",\
URL_USERNAME=\"%s\",URL_PASSWORD=\"%s\",\
STATION_NAME=\"%s\"",
(const char *)q->value(0).toString(),
q->value(1).toInt(),q->value(2).toUInt(),
(const char *)q->value(3).toString(),
(const char *)q->value(4).toString(),
(const char *)q->value(5).toString(),
(const char *)q->value(6).toString(),
(const char *)q->value(7).toString(),
(const char *)q->value(8).toString(),
(const char *)q->value(9).toString(),
(const char *)q->value(10).toString(),
(const char *)q->value(11).toString(),
q->value(12).toInt(),
(const char *)q->value(13).toString(),
q->value(14).toInt(),
q->value(15).toInt(),
q->value(16).toInt(),
q->value(17).toInt(),
q->value(18).toInt(),
(const char *)q->value(19).toString(),
q->value(20).toInt(),
q->value(21).toInt(),
q->value(22).toInt(),
q->value(23).toUInt(),
q->value(24).toInt(),
q->value(25).toInt(),
q->value(26).toUInt(),
q->value(27).toUInt(),
q->value(28).toInt(),
q->value(29).toInt(),
q->value(30).toInt(),
q->value(31).toInt(),
q->value(32).toInt(),
q->value(33).toInt(),
q->value(34).toInt(),
q->value(35).toInt(),
q->value(36).toInt(),
(const char *)q->value(37).toString(),
(const char *)q->value(38).toString(),
(const char *)q->value(39).toString(),
(const char *)q->value(40).toString(),
(const char *)dest_station);
q1=new RDSqlQuery(sql,dest_db);
delete q1;
}
delete q;
printf("done.\n");
exit(0);
}
int main(int argc,char *argv[])
{
QApplication a(argc,argv,false);
new MainObject(NULL,"main");
return a.exec();
}

52
importers/rdcatch_copy.h Normal file
View File

@@ -0,0 +1,52 @@
// rdcatch_copy.h
//
// An RDCatch event copier.
//
// (C) Copyright 2002-2005 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: rdcatch_copy.h,v 1.6 2010/07/29 19:32:32 cvs Exp $
// $Date: 2010/07/29 19:32:32 $
//
// 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 RDCATCH_COPY_H
#define RDCATCH_COPY_H
#include <qobject.h>
#include <qapplication.h>
#include <qsqldatabase.h>
#include <rdstation.h>
#include <rdripc.h>
#include <rdcatch_connect.h>
#include <rdstation.h>
#include <rdconfig.h>
#define RDCATCH_COPY_USAGE "-h <src-mysql-host> -s <src-rd-host> -H <dest-mysql-host> -S <dest-rd-host>\n"
class MainObject : public QObject
{
Q_OBJECT
public:
MainObject(QObject *parent=0,const char *name=0);
private:
QSqlDatabase *src_db;
QSqlDatabase *dest_db;
RDConfig *rd_config;
};
#endif

View File

@@ -0,0 +1,497 @@
// rivendell_filter.cpp
//
// A Library import filter for an external Rivendell system
//
// (C) Copyright 2002-2005,2008 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: rivendell_filter.cpp,v 1.3 2010/07/29 19:32:32 cvs Exp $
// $Date: 2010/07/29 19:32:32 $
//
// 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 <stdio.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <qapplication.h>
#include <qdir.h>
#include <rddb.h>
#include <rd.h>
#include <rdconf.h>
#include <rdconfig.h>
#include <rdcmd_switch.h>
#include <rdescape_string.h>
#include <rdcut.h>
#include <rivendell_filter.h>
//
// Global Variables
//
RDConfig *rdconfig;
MainObject::MainObject(QObject *parent,const char *name)
: QObject(parent,name)
{
QString ext_dbname;
QString ext_hostname;
QString ext_username;
QString ext_password;
QString ext_audiodir;
QString default_group;
unsigned start_cartnum=0;
unsigned end_cartnum=0;
QSqlDatabase *filter_db;
QSqlDatabase *ext_db;
bool ok=false;
bool found;
QString start_datetime;
QString end_datetime;
QString start_daypart;
QString end_daypart;
QString owner;
QString group;
QString sql;
QSqlQuery *q;
QSqlQuery *q1;
QSqlQuery *q2;
//
// Read Command Options
//
RDCmdSwitch *cmd=
new RDCmdSwitch(qApp->argc(),qApp->argv(),"rivendell_filter",
RIVENDELL_FILTER_USAGE);
delete cmd;
rdconfig=new RDConfig(RD_CONF_FILE);
rdconfig->load();
//
// Open Local Database
//
filter_db=QSqlDatabase::addDatabase(rdconfig->mysqlDriver(),"LOCAL_DB");
if(!filter_db) {
fprintf(stderr,"rivendell_filter: can't open local mySQL database\n");
exit(1);
}
filter_db->setDatabaseName(rdconfig->mysqlDbname());
filter_db->setUserName(rdconfig->mysqlUsername());
filter_db->setPassword(rdconfig->mysqlPassword());
filter_db->setHostName(rdconfig->mysqlHostname());
if(!filter_db->open()) {
fprintf(stderr,
"rivendell_filter: unable to connect to local mySQL Server\n");
filter_db->removeDatabase(rdconfig->mysqlDbname());
exit(1);
}
//
// Read Arguments
//
for(int i=1;i<(qApp->argc()-1);i+=2) {
found=false;
if(!strcmp("-h",qApp->argv()[i])) {
ext_hostname=qApp->argv()[i+1];
found=true;
}
if(!strcmp("-u",qApp->argv()[i])) {
ext_username=qApp->argv()[i+1];
found=true;
}
if(!strcmp("-p",qApp->argv()[i])) {
ext_password=qApp->argv()[i+1];
found=true;
}
if(!strcmp("-A",qApp->argv()[i])) {
ext_audiodir=qApp->argv()[i+1];
found=true;
}
if(!strcmp("-g",qApp->argv()[i])) {
default_group=qApp->argv()[i+1];
found=true;
}
if(!strcmp("-s",qApp->argv()[i])) {
start_cartnum=QString(qApp->argv()[i+1]).toUInt(&ok);
if(!ok) {
fprintf(stderr,"\nrivendell_filter: invalid group number\n");
exit(256);
}
found=true;
}
if(!strcmp("-e",qApp->argv()[i])) {
end_cartnum=QString(qApp->argv()[i+1]).toUInt(&ok);
if(!ok) {
fprintf(stderr,"\nrivendell_filter: invalid group number\n");
exit(256);
}
found=true;
}
if(!found) {
fprintf(stderr,"\nrivendell_filter %s\n",RIVENDELL_FILTER_USAGE);
exit(1);
}
}
if((start_cartnum==0)||(start_cartnum>999999)) {
fprintf(stderr,"\nrivendell_filter: invalid start cart value\n");
exit(256);
}
if((end_cartnum==0)||(end_cartnum>999999)) {
fprintf(stderr,"\nrivendell_filter: invalid end cart value\n");
exit(256);
}
if(start_cartnum>end_cartnum) {
fprintf(stderr,"\nrivendell_filter: invalid cart values\n");
exit(256);
}
if(ext_audiodir.isEmpty()) {
fprintf(stderr,"rivendell_filter: invalid source audio directory\n");
exit(256);
}
QDir dir=QDir(ext_audiodir);
if(!dir.exists()) {
fprintf(stderr,"rivendell_filter: invalid source audio directory\n");
exit(256);
}
if(!dir.isReadable()) {
fprintf(stderr,
"rivendell_filter: source audio directory is not readable\n");
exit(256);
}
if(ext_audiodir.right(1)!="/") {
ext_audiodir+="/";
}
//
// Open Remote Database
//
ext_db=QSqlDatabase::addDatabase(rdconfig->mysqlDriver(),"REMOTE_DB");
if(!ext_db) {
fprintf(stderr,"rivendell_filter: can't open remote mySQL database\n");
exit(1);
}
ext_db->setDatabaseName(rdconfig->mysqlDbname());
ext_db->setUserName(ext_username);
ext_db->setPassword(ext_password);
ext_db->setHostName(ext_hostname);
if(!ext_db->open()) {
fprintf(stderr,
"rivendell_filter: unable to connect to remote mySQL Server\n");
ext_db->removeDatabase(rdconfig->mysqlDbname());
exit(1);
}
//
// Verify that default group exists
//
sql=QString().sprintf("select NAME from GROUPS where NAME=\"%s\"",
(const char *)default_group);
q=new QSqlQuery(sql,filter_db);
if(!q->next()) {
fprintf(stderr,"rivendell_filter: default group does not exist\n");
exit(256);
}
delete q;
//
// Transfer Loop
//
sql=QString().sprintf("select NUMBER,TYPE,GROUP_NAME,TITLE,ARTIST,ALBUM,\
YEAR,ISRC,LABEL,CLIENT,AGENCY,PUBLISHER,COMPOSER,\
USER_DEFINED,USAGE_CODE,FORCED_LENGTH,AVERAGE_LENGTH,\
LENGTH_DEVIATION,AVERAGE_SEGUE_LENGTH,\
AVERAGE_HOOK_LENGTH,CUT_QUANTITY,LAST_CUT_PLAYED,\
PLAY_ORDER,VALIDITY,\
ENFORCE_LENGTH,PRESERVE_PITCH,ASYNCRONOUS,\
OWNER,MACROS,SCHED_CODES from CART \
where (NUMBER>=%u)&&(NUMBER<=%u)",
start_cartnum,end_cartnum);
q=new QSqlQuery(sql,ext_db);
while(q->next()) {
printf("Transferring cart %06u [%s]...",q->value(0).toUInt(),
(const char *)q->value(3).toString());
fflush(stdout);
//
// Validate Group
//
sql=QString().sprintf("select NAME from GROUPS where NAME=\"%s\"",
(const char *)RDEscapeString(q->value(2).toString()));
q1=new QSqlQuery(sql,filter_db);
if(q1->first()) {
group=q->value(2).toString();
}
else {
group=default_group;
}
delete q1;
//
// Purge old entries
//
sql=QString().sprintf("select CUT_NAME from CUTS where CART_NUMBER=%u",
q->value(0).toUInt());
q1=new QSqlQuery(sql,filter_db);
while(q1->next()) {
unlink(RDCut::pathName(q1->value(0).toString()));
}
delete q1;
sql=QString().sprintf("delete from CUTS where CART_NUMBER=%u",
q->value(0).toUInt());
q1=new QSqlQuery(sql,filter_db);
delete q1;
sql=QString().sprintf("delete from CART where NUMBER=%u",
q->value(0).toUInt());
q1=new QSqlQuery(sql,filter_db);
delete q1;
//
// Create new entries
//
if(q->value(27).isNull()) {
owner="null";
}
else {
owner=QString().sprintf("\"%s\"",
(const char *)RDEscapeString(q->value(27).toString()));
}
sql=QString().sprintf("insert into CART set NUMBER=%u,\
TYPE=%u,\
GROUP_NAME=\"%s\",\
TITLE=\"%s\",\
ARTIST=\"%s\",\
ALBUM=\"%s\",\
YEAR=\"%s\",\
ISRC=\"%s\",\
LABEL=\"%s\",\
CLIENT=\"%s\",\
AGENCY=\"%s\",\
PUBLISHER=\"%s\",\
COMPOSER=\"%s\",\
USER_DEFINED=\"%s\",\
USAGE_CODE=\"%s\",\
FORCED_LENGTH=%u,\
AVERAGE_LENGTH=%u,\
LENGTH_DEVIATION=%u,\
AVERAGE_SEGUE_LENGTH=%u,\
AVERAGE_HOOK_LENGTH=%u,\
CUT_QUANTITY=%u,\
LAST_CUT_PLAYED=%u,\
PLAY_ORDER=%u,\
VALIDITY=%u,\
ENFORCE_LENGTH=\"%s\",\
PRESERVE_PITCH=\"%s\",\
ASYNCRONOUS=\"%s\",\
OWNER=%s,\
MACROS=\"%s\",\
SCHED_CODES=\"%s\"",
q->value(0).toUInt(),
q->value(1).toUInt(),
(const char *)RDEscapeString(group),
(const char *)RDEscapeString(q->value(3).toString()),
(const char *)RDEscapeString(q->value(4).toString()),
(const char *)RDEscapeString(q->value(5).toString()),
(const char *)q->value(6).toDate().
toString("yyyy-MM-dd"),
(const char *)RDEscapeString(q->value(7).toString()),
(const char *)RDEscapeString(q->value(8).toString()),
(const char *)RDEscapeString(q->value(9).toString()),
(const char *)RDEscapeString(q->value(10).toString()),
(const char *)RDEscapeString(q->value(11).toString()),
(const char *)RDEscapeString(q->value(12).toString()),
(const char *)RDEscapeString(q->value(13).toString()),
(const char *)RDEscapeString(q->value(14).toString()),
q->value(15).toUInt(),
q->value(16).toUInt(),
q->value(17).toUInt(),
q->value(18).toUInt(),
q->value(19).toUInt(),
q->value(20).toUInt(),
q->value(21).toUInt(),
q->value(22).toUInt(),
q->value(23).toUInt(),
(const char *)RDEscapeString(q->value(24).toString()),
(const char *)RDEscapeString(q->value(25).toString()),
(const char *)RDEscapeString(q->value(26).toString()),
(const char *)owner,
(const char *)RDEscapeString(q->value(28).toString()),
(const char *)RDEscapeString(q->value(29).
toString()));
q1=new QSqlQuery(sql,filter_db);
delete q1;
sql=QString().sprintf("select CUT_NAME,EVERGREEN,DESCRIPTION,OUTCUE,ISRC,\
LENGTH,ORIGIN_DATETIME,START_DATETIME,END_DATETIME,\
SUN,MON,TUE,WED,THU,FRI,SAT,START_DAYPART,\
END_DAYPART,ORIGIN_NAME,WEIGHT,VALIDITY,\
CODING_FORMAT,SAMPLE_RATE,BIT_RATE,CHANNELS,\
PLAY_GAIN,START_POINT,END_POINT,FADEUP_POINT,\
FADEDOWN_POINT,SEGUE_START_POINT,SEGUE_END_POINT,\
SEGUE_GAIN,HOOK_START_POINT,HOOK_END_POINT,\
TALK_START_POINT,TALK_END_POINT from CUTS \
where CART_NUMBER=%u",q->value(0).toUInt());
q1=new QSqlQuery(sql,ext_db);
while(q1->next()) {
if(q1->value(7).isNull()) {
start_datetime="null";
}
else {
start_datetime=QString().sprintf("\"%s\"",
(const char *)q1->value(7).
toDateTime().toString("yyyy-MM-dd hh:mm:ss"));
}
if(q1->value(8).isNull()) {
end_datetime="null";
}
else {
end_datetime=QString().sprintf("\"%s\"",
(const char *)q1->value(8).
toDateTime().toString("yyyy-MM-dd hh:mm:ss"));
}
if(q1->value(16).isNull()) {
start_daypart="null";
}
else {
start_daypart=QString().sprintf("\"%s\"",
(const char *)q1->value(16).
toTime().toString("hh:mm:ss"));
}
if(q1->value(17).isNull()) {
end_daypart="null";
}
else {
end_daypart=QString().sprintf("\"%s\"",
(const char *)q1->value(17).
toTime().toString("hh:mm:ss"));
}
sql=QString().sprintf("insert into CUTS set CART_NUMBER=%u,\
CUT_NAME=\"%s\",\
EVERGREEN=\"%s\",\
DESCRIPTION=\"%s\",\
OUTCUE=\"%s\",\
ISRC=\"%s\",\
LENGTH=%u,\
ORIGIN_DATETIME=\"%s\",\
START_DATETIME=%s,\
END_DATETIME=%s,\
SUN=\"%s\",\
MON=\"%s\",\
TUE=\"%s\",\
WED=\"%s\",\
THU=\"%s\",\
FRI=\"%s\",\
SAT=\"%s\",\
START_DAYPART=%s,\
END_DAYPART=%s,\
ORIGIN_NAME=\"%s\",\
WEIGHT=%u,\
VALIDITY=%u,\
CODING_FORMAT=%u,\
SAMPLE_RATE=%u,\
BIT_RATE=%u,\
CHANNELS=%u,\
PLAY_GAIN=%d,\
START_POINT=%d,\
END_POINT=%d,\
FADEUP_POINT=%d,\
FADEDOWN_POINT=%d,\
SEGUE_START_POINT=%d,\
SEGUE_END_POINT=%d,\
SEGUE_GAIN=%d,\
HOOK_START_POINT=%d,\
HOOK_END_POINT=%d,\
TALK_START_POINT=%d,\
TALK_END_POINT=%d",
q->value(0).toUInt(),
(const char *)RDEscapeString(q1->value(0).
toString()),
(const char *)RDEscapeString(q1->value(1).
toString()),
(const char *)RDEscapeString(q1->value(2).
toString()),
(const char *)RDEscapeString(q1->value(3).
toString()),
(const char *)RDEscapeString(q1->value(4).
toString()),
q1->value(5).toUInt(),
(const char *)RDEscapeString(q1->value(6).
toString()),
(const char *)start_datetime,
(const char *)end_datetime,
(const char *)RDEscapeString(q1->value(9).
toString()),
(const char *)RDEscapeString(q1->value(10).
toString()),
(const char *)RDEscapeString(q1->value(11).
toString()),
(const char *)RDEscapeString(q1->value(12).
toString()),
(const char *)RDEscapeString(q1->value(13).
toString()),
(const char *)RDEscapeString(q1->value(14).
toString()),
(const char *)RDEscapeString(q1->value(15).
toString()),
(const char *)start_daypart,
(const char *)end_daypart,
(const char *)RDEscapeString(q1->value(18).
toString()),
q1->value(19).toUInt(),
q1->value(20).toUInt(),
q1->value(21).toUInt(),
q1->value(22).toUInt(),
q1->value(23).toUInt(),
q1->value(24).toUInt(),
q1->value(25).toInt(),
q1->value(26).toInt(),
q1->value(27).toInt(),
q1->value(28).toInt(),
q1->value(29).toInt(),
q1->value(30).toInt(),
q1->value(31).toInt(),
q1->value(32).toInt(),
q1->value(33).toInt(),
q1->value(34).toInt(),
q1->value(35).toInt(),
q1->value(36).toInt());
q2=new QSqlQuery(sql,filter_db);
delete q2;
ok=RDCopy(QString().sprintf("%s%s.%s",(const char *)ext_audiodir,
(const char *)q1->value(0).toString(),
RD_AUDIO_EXTENSION),
RDCut::pathName(q1->value(0).toString()));
if(!ok) {
printf("[WARNING -- NO AUDIO FOUND]...");
fflush(stdout);
}
}
delete q1;
printf("done.\n");
}
delete q;
exit(0);
}
int main(int argc,char *argv[])
{
QApplication a(argc,argv,false);
new MainObject(NULL,"main");
return a.exec();
}

View File

@@ -0,0 +1,43 @@
// rivendell_filter.h
//
// A Library import filter for an external Rivendell system
//
// (C) Copyright 2002-2005, 2008 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: rivendell_filter.h,v 1.3 2010/07/29 19:32:32 cvs Exp $
// $Date: 2010/07/29 19:32:32 $
//
// 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 RIVENDELL_FILTER_H
#define RIVENDELL_FILTER_H
#include <stdio.h>
#include <qobject.h>
#include <qapplication.h>
#include <qsqldatabase.h>
#define RIVENDELL_FILTER_USAGE " -h <hostname> -u <username> -p <password> -A <audio-dir> -g <default-group> -s <start-cartnum> -e <end-cartnum>"
class MainObject : public QObject
{
Q_OBJECT
public:
MainObject(QObject *parent=0,const char *name=0);
};
#endif // RIVENDELL_FILTER_H

283
importers/sas_filter.cpp Normal file
View File

@@ -0,0 +1,283 @@
// sas_filter.cpp
//
// An RDCatch event import filter for the SAS64000
//
// (C) Copyright 2002-2004 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: sas_filter.cpp,v 1.11 2011/06/21 22:20:43 cvs Exp $
// $Date: 2011/06/21 22:20:43 $
//
// 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 free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.//
// 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 <stdio.h>
#include <unistd.h>
#include <qapplication.h>
#include <rddb.h>
#include <rd.h>
#include <rdcmd_switch.h>
#include <dbversion.h>
#include <sas_filter.h>
//
// Global Variables
//
MainObject::MainObject(QObject *parent,const char *name)
: QObject(parent,name)
{
bool skip_db_check=false;
unsigned schema=0;
//
// Read Command Options
//
RDCmdSwitch *cmd=
new RDCmdSwitch(qApp->argc(),qApp->argv(),"sas_filter",SAS_FILTER_USAGE);
for(unsigned i=0;i<cmd->keys();i++) {
if(cmd->key(i)=="--skip-db-check") {
skip_db_check=true;
}
}
delete cmd;
rd_config=new RDConfig(RD_CONF_FILE);
rd_config->load();
filter_switch_count=0;
filter_macro_count=0;
//
// Open Database
//
QString err(tr("sas_filter: "));
filter_db=RDInitDb(&schema,&err);
if(!filter_db) {
fprintf(stderr,"%s\n",err.ascii());
exit(1);
}
if((schema!=RD_VERSION_DATABASE)&&(!skip_db_check)) {
fprintf(stderr,
"sas_filter: database version mismatch, should be %u, is %u\n",
RD_VERSION_DATABASE,schema);
exit(256);
}
//
// RIPCD Connection
//
filter_ripc=new RDRipc("");
filter_ripc->connectHost("localhost",RIPCD_TCP_PORT,rd_config->password());
//
// Station Configuration
//
filter_rdstation=new RDStation(rd_config->stationName());
//
// RDCatchd Connection
//
filter_connect=new RDCatchConnect(0,this,"filter_connect");
filter_connect->connectHost("localhost",RDCATCHD_TCP_PORT,
rd_config->password());
//
// Read Switches
//
if((qApp->argc()==2)&&(!strcmp(qApp->argv()[1],"-d"))) { // Delete List
DeleteList();
filter_connect->reset();
exit(0);
}
if((qApp->argc()==3)&&(!strcmp(qApp->argv()[1],"-i"))) { // Insert List
InsertList();
filter_connect->reset();
exit(0);
}
fprintf(stderr,"\nsas_filter %s\n",SAS_FILTER_USAGE);
exit(1);
}
void MainObject::InsertList()
{
char line[256];
int count=0;
FILE *fh=fopen(qApp->argv()[2],"r");
if(fh==NULL) {
perror("sas_filter");
exit(1);
}
printf("Importing events from %s...",qApp->argv()[2]);
fflush(0);
while(fgets(line,256,fh)!=NULL) {
if(strlen(line)==79) {
InjectLine(line);
count++;
}
}
printf("done.\n");
fclose(fh);
printf("Imported %d switch events, %d macro events, %d total.\n",
filter_switch_count,filter_macro_count,
filter_switch_count+filter_macro_count);
}
void MainObject::DeleteList()
{
QString sql="delete from RECORDINGS";
RDSqlQuery *q=new RDSqlQuery(sql);
delete q;
filter_connect->reset();
printf("RDCatch events list deleted!\n");
}
void MainObject::InjectLine(char *line)
{
QString temp;
int input=0;
int output=0;
int gpo=0;
//
// Initialize the SQL clause
//
QString base_sql=QString().sprintf("insert into RECORDINGS set\
STATION_NAME=\"%s\",CHANNEL=%d,",
(const char *)rd_config->sasStation(),
rd_config->sasMatrix());
//
// Day of the week fields
//
if(line[0]=='X') {
base_sql+="MON=\"Y\",";
}
if(line[1]=='X') {
base_sql+="TUE=\"Y\",";
}
if(line[2]=='X') {
base_sql+="WED=\"Y\",";
}
if(line[3]=='X') {
base_sql+="THU=\"Y\",";
}
if(line[4]=='X') {
base_sql+="FRI=\"Y\",";
}
if(line[5]=='X') {
base_sql+="SAT=\"Y\",";
}
if(line[6]=='X') {
base_sql+="SUN=\"Y\",";
}
//
// Time
//
line[17]=0;
base_sql+=QString().sprintf("START_TIME=\"%s\",",line+9);
//
// Title
//
line[60]=0;
temp=QString(line+19).stripWhiteSpace();
base_sql+=QString().sprintf("DESCRIPTION=\"%s\",",(const char *)temp);
//
// Active Flag
//
if(line[77]=='I') {
base_sql+="IS_ACTIVE=\"N\",";
}
//
// Output
//
line[65]=0;
sscanf(line+62,"%d",&output);
//
// Input
//
line[70]=0;
sscanf(line+67,"%d",&input);
//
// GPO
//
line[75]=0;
sscanf(line+73,"%d",&gpo);
if((input>0)&&(output>0)) {
InjectSwitchEvent(base_sql,input,output);
}
if(gpo>0) {
InjectCartEvent(base_sql,gpo);
}
}
void MainObject::InjectSwitchEvent(QString sql,int input,int output)
{
//
// Event Type
//
sql+="TYPE=2,";
//
// Input and Output
//
sql+=QString().sprintf("SWITCH_INPUT=%d,SWITCH_OUTPUT=%d",input,output);
RDSqlQuery *q=new RDSqlQuery(sql);
delete q;
filter_switch_count++;
}
void MainObject::InjectCartEvent(QString sql,int gpo)
{
//
// Event Type
//
sql+="TYPE=1,";
//
// Macro Cart
//
sql+=QString().sprintf("MACRO_CART=%d",gpo+rd_config->sasBaseCart());
filter_macro_count++;
RDSqlQuery *q=new RDSqlQuery(sql);
delete q;
// printf("SQL: %s\n",(const char *)sql);
}
int main(int argc,char *argv[])
{
QApplication a(argc,argv,false);
new MainObject(NULL,"main");
return a.exec();
}

61
importers/sas_filter.h Normal file
View File

@@ -0,0 +1,61 @@
// sas_filter.h
//
// An RDCatch event import filter for the SAS64000
//
// (C) Copyright 2002-2004 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: sas_filter.h,v 1.7 2010/07/29 19:32:32 cvs Exp $
// $Date: 2010/07/29 19:32:32 $
//
// 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 SAS_FILTER_H
#define SAS_FILTER_H
#include <qobject.h>
#include <qapplication.h>
#include <qsqldatabase.h>
#include <rdstation.h>
#include <rdripc.h>
#include <rdcatch_connect.h>
#include <rdstation.h>
#include <rdconfig.h>
#define SAS_FILTER_USAGE "-d|-i <insert-list>\n"
class MainObject : public QObject
{
Q_OBJECT
public:
MainObject(QObject *parent=0,const char *name=0);
private:
void InsertList();
void DeleteList();
void InjectLine(char *line);
void InjectSwitchEvent(QString sql,int input,int output);
void InjectCartEvent(QString sql,int gpo);
RDStation *filter_rdstation;
RDRipc *filter_ripc;
RDCatchConnect *filter_connect;
QSqlDatabase *filter_db;
int filter_switch_count;
int filter_macro_count;
RDConfig *rd_config;
};
#endif

329
importers/wings_filter.cpp Normal file
View File

@@ -0,0 +1,329 @@
// wings_filter.cpp
//
// A Library import filter for the Airforce Wings system
//
// (C) Copyright 2002-2004 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: wings_filter.cpp,v 1.13 2010/07/29 19:32:33 cvs Exp $
// $Date: 2010/07/29 19:32:33 $
//
// 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 <stdio.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <qapplication.h>
#include <rddb.h>
#include <rd.h>
#include <rdconfig.h>
#include <rdcmd_switch.h>
#include <rdcut.h>
#include <wings_filter.h>
//
// Global Variables
//
RDConfig *rdconfig;
MainObject::MainObject(QObject *parent,const char *name)
: QObject(parent,name)
{
//
// Read Command Options
//
RDCmdSwitch *cmd=
new RDCmdSwitch(qApp->argc(),qApp->argv(),"wings_filter",
WINGS_FILTER_USAGE);
delete cmd;
WingsRecord wr;
QString audioname;
bool found;
QString dbname;
QString audiodir;
QString audio_extension=WINGS_DEFAULT_AUDIO_EXT;
QString groupname;
RDWaveFile *wavefile=NULL;
rdconfig=new RDConfig(RD_CONF_FILE);
rdconfig->load();
//
// Open Database
//
filter_db=QSqlDatabase::addDatabase(rdconfig->mysqlDriver());
if(!filter_db) {
fprintf(stderr,"wings_filter: can't open mySQL database\n");
exit(1);
}
filter_db->setDatabaseName(rdconfig->mysqlDbname());
filter_db->setUserName(rdconfig->mysqlUsername());
filter_db->setPassword(rdconfig->mysqlPassword());
filter_db->setHostName(rdconfig->mysqlHostname());
if(!filter_db->open()) {
fprintf(stderr,"wings_filter: unable to connect to mySQL Server\n");
filter_db->removeDatabase(rdconfig->mysqlDbname());
exit(1);
}
//
// RIPCD Connection
//
filter_ripc=new RDRipc("");
filter_ripc->connectHost("localhost",RIPCD_TCP_PORT,rdconfig->password());
//
// Station Configuration
//
filter_rdstation=new RDStation(rdconfig->stationName());
//
// Read Arguments
//
for(int i=1;i<(qApp->argc()-1);i+=2) {
found=false;
if(!strcmp("-d",qApp->argv()[i])) {
dbname=qApp->argv()[i+1];
found=true;
}
if(!strcmp("-A",qApp->argv()[i])) {
audiodir=qApp->argv()[i+1];
found=true;
}
if(!strcmp("-g",qApp->argv()[i])) {
groupname=qApp->argv()[i+1];
found=true;
}
if(!strcmp("-e",qApp->argv()[i])) {
audio_extension=qApp->argv()[i+1];
found=true;
}
if(!found) {
fprintf(stderr,"\nwings_filter %s\n",WINGS_FILTER_USAGE);
exit(1);
}
}
FILE *file=fopen((const char *)dbname,"r");
if(file==NULL) {
perror("wings_filter");
exit(1);
}
RDGroup *default_group=new RDGroup(groupname);
if(!default_group->exists()) {
fprintf(stderr,"wings_filter: no such default group\n");
delete default_group;
exit(256);
}
while(ReadLine(file,&wr)) {
strcpy(wr.extension,audio_extension);
audioname=QString().sprintf("%s/%s.%s",(const char *)audiodir,
wr.filename,(const char *)audio_extension);
wavefile=new RDWaveFile(audioname);
if(!wavefile->openWave()) {
fprintf(stderr,"Unable to open %s, skipping...\n",
(const char *)audioname);
}
else {
if(wavefile->type()!=RDWaveFile::Atx) {
fprintf(stderr,"ATX header in %s appears corrupt, skipping...\n",
(const char *)audioname);
}
else {
RDGroup *group=new RDGroup(wr.group);
if(group->exists()) {
ImportCut(group,&wr,wavefile);
}
else {
ImportCut(default_group,&wr,wavefile);
}
delete group;
}
wavefile->closeWave();
}
delete wavefile;
}
delete default_group;
fclose(file);
exit(0);
}
bool MainObject::ImportCut(RDGroup *group,struct WingsRecord *rec,
RDWaveFile *wavefile)
{
unsigned cartnum=0;
QString sql;
RDSqlQuery *q;
int format=0;
RDWaveFile *destfile;
int n;
char buffer[WINGS_XFER_BUFFER_SIZE];
if((cartnum=group->nextFreeCart())==0) {
fprintf(stderr,"No more available carts in group %s, skipping %s...\n",
rec->group,rec->filename);
delete group;
return false;
}
destfile=new RDWaveFile(RDCut::pathName(QString().sprintf
("%06u_001",cartnum)));
switch(wavefile->getFormatTag()) {
case WAVE_FORMAT_PCM:
format=0;
destfile->setBextChunk(true);
destfile->setFormatTag(WAVE_FORMAT_PCM);
break;
case WAVE_FORMAT_MPEG:
if(wavefile->getHeadLayer()==2) {
format=1;
destfile->setFormatTag(WAVE_FORMAT_MPEG);
destfile->setHeadLayer(2);
destfile->setHeadBitRate(wavefile->getHeadBitRate());
destfile->setHeadMode(wavefile->getHeadMode());
destfile->setMextChunk(true);
destfile->setMextHomogenous(true);
destfile->setMextAncillaryLength(3);
destfile->setMextLeftEnergyPresent(true);
if(wavefile->getChannels()>1) {
destfile->setMextRightEnergyPresent(true);
}
}
else {
return false;
}
break;
default:
return false;
break;
}
destfile->setSamplesPerSec(wavefile->getSamplesPerSec());
destfile->setBitsPerSample(wavefile->getBitsPerSample());
destfile->setChannels(wavefile->getChannels());
destfile->setBextChunk(true);
destfile->setBextDescription(rec->title);
if(!destfile->createWave()) {
fprintf(stderr,"wings_filter: unable to write to audio directory\n");
exit(256);
}
while((n=wavefile->readWave(buffer,WINGS_XFER_BUFFER_SIZE))>0) {
destfile->writeWave(buffer,n);
}
destfile->closeWave();
printf("Importing %s - %s to cart %u, group %s\n",
rec->filename,rec->title,cartnum,(const char *)group->name());
sql=QString().sprintf("insert into CART set NUMBER=%u,GROUP_NAME=\"%s\",\
TITLE=\"%s\",ARTIST=\"%s\",ALBUM=\"%s\",\
CUT_QUANTITY=1,TYPE=%d,FORCED_LENGTH=%u,\
AVERAGE_LENGTH=%u,USER_DEFINED=\"%s.%s\"",
cartnum,(const char *)group->name(),
rec->title,rec->artist,rec->album,
RDCart::Audio,wavefile->getExtTimeLength(),
wavefile->getExtTimeLength(),
rec->filename,rec->extension);
q=new RDSqlQuery(sql);
delete q;
sql=QString().sprintf("insert into CUTS set CUT_NAME=\"%06u_001\",\
CART_NUMBER=%u,DESCRIPTION=\"%s\",\
ORIGIN_DATETIME=\"%s\",ORIGIN_NAME=\"%s\",\
CODING_FORMAT=%d,SAMPLE_RATE=%u,CHANNELS=%d,\
BIT_RATE=%d,LENGTH=%u,START_POINT=0,\
END_POINT=%d",
cartnum,cartnum,(const char *)rec->title,
(const char *)QDateTime::currentDateTime().
toString("yyyy-MM-dd hh:mm:ss"),
(const char *)rdconfig->stationName(),format,
wavefile->getSamplesPerSec(),
wavefile->getChannels(),wavefile->getHeadBitRate(),
wavefile->getExtTimeLength(),
wavefile->getExtTimeLength());
q=new RDSqlQuery(sql);
delete q;
return true;
}
bool MainObject::ReadLine(FILE *fp,struct WingsRecord *rec)
{
char buffer[WINGS_RECORD_LENGTH+1];
memset(rec,0,sizeof(struct WingsRecord));
if(fgets(buffer,WINGS_RECORD_LENGTH+1,fp)==NULL) {
return false;
}
if(strlen(buffer)<WINGS_RECORD_LENGTH) {
return false;
}
buffer[8]=0; // Fielname
strcpy(rec->filename,buffer);
TrimSpaces(rec->filename);
rec->group[0]=buffer[9]; // Group
rec->group[1]=0;
buffer[17]=0; // Length
sscanf(buffer+14,"%d",&rec->length);
rec->length*=1000;
buffer[47]=0; // Title
strcpy(rec->title,buffer+24);
TrimSpaces(rec->title);
buffer[77]=0; // Artist
strcpy(rec->artist,buffer+55);
TrimSpaces(rec->artist);
buffer[105]=0;
strcpy(rec->album,buffer+78);
TrimSpaces(rec->album);
return true;
}
void MainObject::TrimSpaces(char *str)
{
for(int i=strlen(str)-1;i>=0;i--) {
if(isspace(str[i])) {
str[i]=0;
}
else {
i=-1;
}
}
}
int main(int argc,char *argv[])
{
QApplication a(argc,argv,false);
new MainObject(NULL,"main");
return a.exec();
}

71
importers/wings_filter.h Normal file
View File

@@ -0,0 +1,71 @@
// wings_filter.h
//
// A Library import filter for the Crown Wings system
//
// (C) Copyright 2002-2005 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: wings_filter.h,v 1.9 2010/07/29 19:32:33 cvs Exp $
// $Date: 2010/07/29 19:32:33 $
//
// 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 WINGS_FILTER_H
#define WINGS_FILTER_H
#include <stdio.h>
#include <qobject.h>
#include <qapplication.h>
#include <qsqldatabase.h>
#include <rdwavefile.h>
#include <rdstation.h>
#include <rdripc.h>
#include <rdcatch_connect.h>
#include <rdcae.h>
#include <rdgroup.h>
#define WINGS_RECORD_LENGTH 613
#define WINGS_FILTER_USAGE "-g <default-group> -d <db-file> -A <audio-dir> [-e <audio-ext>]\n"
#define WINGS_DEFAULT_AUDIO_EXT "ATX"
#define WINGS_XFER_BUFFER_SIZE 4096
struct WingsRecord {
char filename[9];
char extension[4];
char title[32];
char artist[32];
char album[32];
char group[2];
unsigned length;
};
class MainObject : public QObject
{
Q_OBJECT
public:
MainObject(QObject *parent=0,const char *name=0);
private:
bool ImportCut(RDGroup *group,struct WingsRecord *rec,RDWaveFile *wavefile);
bool ReadLine(FILE *fp,struct WingsRecord *rec);
void TrimSpaces(char *str);
RDStation *filter_rdstation;
RDRipc *filter_ripc;
QSqlDatabase *filter_db;
};
#endif