From 42d3bb430a54ebc58d3f1deecea54f5a3e2e5e5f Mon Sep 17 00:00:00 2001
From: Fred Gleason <fredg@paravelsystems.com>
Date: Sat, 25 Oct 2014 17:39:57 -0400
Subject: [PATCH] 2014-10-25 Fred Gleason <fredg@paravelsystems.com> 	*
 Implemented '--set-marker-end-*=' and '--set-marker-start-*=' 	options for
 rdimport(1) in 'utils/rdimport/markerset.cpp',, 
 'utils/rdimport/markerset.h', 'utils/rdimport/rdimport.cpp' and 
 'utils/rdimport/rdimport.h'.

---
 ChangeLog                    |   5 ++
 docs/man/rdimport.1          | 170 ++++++++++++++++++++---------------
 utils/rdimport/Makefile.am   |   3 +-
 utils/rdimport/markerset.cpp | 143 +++++++++++++++++++++++++++++
 utils/rdimport/markerset.h   |  50 +++++++++++
 utils/rdimport/rdimport.cpp  |  37 +++++++-
 utils/rdimport/rdimport.h    |   6 ++
 7 files changed, 342 insertions(+), 72 deletions(-)
 create mode 100644 utils/rdimport/markerset.cpp
 create mode 100644 utils/rdimport/markerset.h

diff --git a/ChangeLog b/ChangeLog
index a07f9c9d..d1f0f84b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -14577,3 +14577,8 @@
 	* Implemented post export commands in 'lib/rdreport.cpp'.
 2014-10-25 Fred Gleason <fredg@paravelsystems.com>
 	* Created an rdimport(1) man page in 'docs/man/rdimport.1'.
+2014-10-25 Fred Gleason <fredg@paravelsystems.com>
+	* Implemented '--set-marker-end-*=' and '--set-marker-start-*='
+	options for rdimport(1) in 'utils/rdimport/markerset.cpp',,
+	'utils/rdimport/markerset.h', 'utils/rdimport/rdimport.cpp' and
+	'utils/rdimport/rdimport.h'.
diff --git a/docs/man/rdimport.1 b/docs/man/rdimport.1
index 3104fe58..f15b5b98 100644
--- a/docs/man/rdimport.1
+++ b/docs/man/rdimport.1
@@ -16,71 +16,58 @@ list of filespecs to be read from standard input.
 
 .SH OPTIONS
 .TP
-.B --verbose
-Print progress messages during processing.
-.TP
-.B --help
-Print a short usage message and exit.
-.TP
-.B --version
-Output version information and exit.
-.TP
-.B --log-mode
-Prepend date/time information to each line of printed status (implies
-the '--verbose' option).
-.TP
-.B --normalization-level=<\fIlevel\fP>
-Specify the level to use for peak normalizing the audio, in dBFS.
-Specifying '0' will turn off normalization.
+.B --add-scheduler-code=<\fIstr\fP>
+Add Scheduler Code <\fIstr\fP> to the target cart.  The specified
+code must exist in RDAdmin->SchedulerCodes.  This option may be
+specified multiple times.
 .TP
 .B --autotrim-level=<level>
 Specify the threshold level to use for autotrimming the audio, in dBFS.
 Specifying '0' will turn off autotrimming.
 .TP
-.B --single-cart
-If more than one file is imported, place them within multiple cuts within a
-single cart, rather than creating separate carts for each file.
-.TP
-.B --segue-level=<\fIlevel\fP>
-Specify the threshold level to use for setting the segue markers, in dBFS.
-Default action is not to create segue markers.
-.TP
-.B --segue-length=<\fIlength\fP>
-Length of the added segue in msecs.  See \fB--segue-level\fP above.
-.TP
-.B --to-cart=<\fIcartnum\fP>
-Specify the cart to import the audio into, rather than using the next
-available cart number for the group.  If the cart does not exist, it will
-be created.  Each file will be imported into a separate new cut within the
-cart.  Use of this option implies the \fB--single-cart\fP option as well,
-and is mutually exclusive with the \fB--use-cartchunk-cutid\fP option.
-.TP
-.B --use-cartchunk-cutid
-Import the audio into the cart specified by the CartChunk CutID parameter
-associated with the file.  If the cart does not exist, it will be
-created.  Use of this option is mutually exclusive with the \fB--to-cart\fP
-option.
-.TP
-.B --title-from-cartchunk-cutid
-Set the cart title from CartChunk CutID.
-.TP
 .B --cart-number-offset=<\fIoffset\fP>
 Add <\fIoffset\fP> to the cart number as determined from metadata pattern
 or --use-cartchunk-cutid.
 .TP
-.B --delete-source
-Delete each source file after successful import.  Use with caution!
+.B --create-enddate-offset=<\fIdays\fP>
+If the imported file does not reference an end date, create with
+end date offset by <\fIdays\fP> days relative to the current date.
+Cannot be less than the value the value for \fB--create-startdate-offset\fP
+(default = 0).
+.TP
+.B --create-startdate-offset=<\fIdays\fP>
+If the imported file does not reference a start date, create with 
+startdate offset by <\fIdays\fP> days relative to the current date.
+Cannot be greater than the value for \fB--create-enddate-offset\fP
+(default = 0).
 .TP
 .B --delete-cuts
 Delete all cuts within the destination cart before importing.  Use
 with caution!
 .TP
+.B --delete-source
+Delete each source file after successful import.  Use with caution!
+.TP
 .B --drop-box
 Operate in DropBox mode, causing \fIrdimport(1)\fP to run continuously,
 periodically scanning for files matching the specified <\fIfilespec\fP>,
 importing and then deleting them when found.  WARNING:  use of this option
 also implies the \fB--delete-source\fP option!
 .TP
+.B --enddate-offset=<days>
+If the imported file references an end date, offset the value by <\fIdays\fP>
+days.
+.TP
+.B --fix-broken-formats
+Attempt to work around malformed audio input data.
+.TP
+.B --help
+Print a short usage message and exit.
+.TP
+.B --log-mode
+Prepend date/time information to each line of printed status (implies
+the '--verbose' option).
+.TP
 .B --metadata-pattern=<\fIpattern\fP>
 Attempt to read metadata parameters from the source filename, using
 the pattern <\fIpattern\fP>.  Patterns consist of a sequence of wildcards and
@@ -154,41 +141,84 @@ when processing a filename of 'My Song_My Artist_TEMP_123456.mp3',
 would extract 'My Song' as the title and 'My Artist' as the artist,
 while importing it into cart 123456 in the TEMP group.
 .TP
-.B --startdate-offset=<\fIdays\fP>
-If the imported file references a start date, offset the value by <\fIdays\fP>
-days.
+.B --normalization-level=<\fIlevel\fP>
+Specify the level to use for peak normalizing the audio, in dBFS.
+Specifying '0' will turn off normalization.
 .TP
-.B --enddate-offset=<days>
-If the imported file references an end date, offset the value by <\fIdays\fP>
-days.
+.B --segue-length=<\fIlength\fP>
+Length of the added segue in msecs.  See \fB--segue-level\fP below.
 .TP
-.B --create-startdate-offset=<\fIdays\fP>
-If the imported file does not reference a start date, create with 
-startdate offset by <\fIdays\fP> days relative to the current date.
-Cannot be greater than the value for \fB--create-enddate-offset\fP
-(default = 0).
-.TP
-.B --create-enddate-offset=<\fIdays\fP>
-If the imported file does not reference an end date, create with
-end date offset by <\fIdays\fP> days relative to the current date.
-Cannot be less than the value the value for \fB--create-startdate-offset\fP
-(default = 0).
+.B --segue-level=<\fIlevel\fP>
+Specify the threshold level to use for setting the segue markers, in dBFS.
+Default action is not to create segue markers.
 .TP
 .B --set-daypart-times=<\fIstart-time\fP>,<\fIend-time\fP>
 Set the start and end daypart times, in the format HHMMSS.
 .TP
-.B --fix-broken-formats
-Attempt to work around malformed audio input data.
+.B --set-marker-end-<\fImarker\fP>=<\fIoffset\fP>
+Set an end marker to a given offset value.  The <\fIoffset\fP> parameter is
+specified in milliseconds.  If positive, it is taken to indicate a marker
+position relative to the absolute beginning of the audio cut, while if
+negative, it is taken to indicate a marker position relative to the absolute
+end of the audio cut.
+
+The following <\fImarker\fP> types are recognized:
+.RS
 .TP
-.B --add-scheduler-code=<\fIstr\fP>
-Add Scheduler Code <\fIstr\fP> to the target cart.  The specified
-code must exist in RDAdmin->SchedulerCodes.  This option may be
-specified multiple times.
+.B cut
+The Cut markers.
+.TP
+.B hook
+The Hook markers.
+.TP
+.B segue
+The Segue markers
+.TP
+.B talk
+The Talk markers.
+.RE
+.RE
+
+.TP
+.B --set-marker-start-<\fImarker\fP>=<\fIoffset\fP>
+Set a start marker to a given offset value.  See the discussion of the
+\fB--set-marker-end-<marker>\fP option above for a description of the
+<\fImarker\fP> and <\fIoffset\fP> parameters.
 .TP
 .B --set-user-defined=<\fIstr\fP>
 Set the User Defined field for the target cart to <\fIstr\fP>.  This will
 override any value that might otherwise be set --e.g. by using the
 \fB--metadata-pattern\fP option.
+.TP
+.B --single-cart
+If more than one file is imported, place them within multiple cuts within a
+single cart, rather than creating separate carts for each file.
+.TP
+.B --startdate-offset=<\fIdays\fP>
+If the imported file references a start date, offset the value by <\fIdays\fP>
+days.
+.TP
+.B --title-from-cartchunk-cutid
+Set the cart title from CartChunk CutID.
+.TP
+.B --to-cart=<\fIcartnum\fP>
+Specify the cart to import the audio into, rather than using the next
+available cart number for the group.  If the cart does not exist, it will
+be created.  Each file will be imported into a separate new cut within the
+cart.  Use of this option implies the \fB--single-cart\fP option as well,
+and is mutually exclusive with the \fB--use-cartchunk-cutid\fP option.
+.TP
+.B --use-cartchunk-cutid
+Import the audio into the cart specified by the CartChunk CutID parameter
+associated with the file.  If the cart does not exist, it will be
+created.  Use of this option is mutually exclusive with the \fB--to-cart\fP
+option.
+.TP
+.B --verbose
+Print progress messages during processing.
+.TP
+.B --version
+Output version information and exit.
 
 .SH NOTES
 It may be necessary to enclose individual <\fIfilespec\fP> clauses in quotes
@@ -197,8 +227,8 @@ indicator that this is necessary is the failure of \fBrdimport(1)\fP to process
 newly added files when running in DropBox mode.
 
 .SH BUGS
-It could be argued that RMS rather peak normalization would be more appropriate
-for use with the \fB--normalization-level\fP option.
+It could be argued that RMS rather than peak normalization would be more
+appropriate for use with the \fB--normalization-level\fP option.
 
 .SH AUTHOR
 Fred Gleason <fredg@paravelsystems.com>
diff --git a/utils/rdimport/Makefile.am b/utils/rdimport/Makefile.am
index ed39bde9..6c86bb0d 100644
--- a/utils/rdimport/Makefile.am
+++ b/utils/rdimport/Makefile.am
@@ -31,7 +31,8 @@ moc_%.cpp:	%.h
 
 bin_PROGRAMS = rdimport
 
-dist_rdimport_SOURCES = rdimport.cpp rdimport.h
+dist_rdimport_SOURCES = markerset.cpp markerset.h\
+                        rdimport.cpp rdimport.h
 
 nodist_rdimport_SOURCES = moc_rdimport.cpp
 
diff --git a/utils/rdimport/markerset.cpp b/utils/rdimport/markerset.cpp
new file mode 100644
index 00000000..b578f08e
--- /dev/null
+++ b/utils/rdimport/markerset.cpp
@@ -0,0 +1,143 @@
+// markerset.cpp
+//
+// Abstract a set of marker parameters.
+//
+//   (C) Copyright 2014 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 <stdio.h>
+#include <stdlib.h>
+
+#include "markerset.h"
+
+MarkerSet::MarkerSet()
+{
+  marker_start_valid=false;
+  marker_start_value=0;
+  marker_end_valid=false;
+  marker_end_value=0;
+  marker_audio_length=0;
+}
+
+
+bool MarkerSet::hasStartValue() const
+{
+  return marker_start_valid;
+}
+
+
+int MarkerSet::startValue(int lo_limit,int hi_limit) const
+{
+  return LimitCheck(marker_start_value,lo_limit,hi_limit);
+}
+
+
+bool MarkerSet::hasEndValue() const
+{
+  return marker_end_valid;
+}
+
+
+int MarkerSet::endValue(int lo_limit,int hi_limit) const
+{
+  return LimitCheck(marker_end_value,lo_limit,hi_limit);
+}
+
+
+void MarkerSet::load(RDCmdSwitch *cmd,const QString &marker)
+{
+  QString start_key="--set-marker-start-"+marker;
+  QString end_key="--set-marker-end-"+marker;
+  marker_marker=marker;
+  for(unsigned i=0;i<cmd->keys();i++) {
+    if(cmd->key(i)==start_key) {
+      marker_start_value=cmd->value(i).toInt(&marker_start_valid);
+      if(!marker_start_valid) {
+	fprintf(stderr,"rdimport: invalid argment to %s\n",
+		(const char *)start_key);
+	exit(255);
+      }
+      cmd->setProcessed(i,true);
+    }
+    if(cmd->key(i)==end_key) {
+      marker_end_value=cmd->value(i).toInt(&marker_end_valid);
+      if(!marker_end_valid) {
+	fprintf(stderr,"rdimport: invalid argment to %s\n",
+		(const char *)end_key);
+	exit(255);
+      }
+      cmd->setProcessed(i,true);
+    }
+  }
+  if(marker_end_valid&&(!marker_start_valid)) {
+    marker_start_value=0;
+    marker_start_valid=true;
+  }
+}
+
+
+void MarkerSet::setAudioLength(int msecs)
+{
+  if(marker_start_valid&&(!marker_end_valid)) {
+    marker_end_value=msecs;
+    marker_end_valid=true;
+  }
+  marker_audio_length=msecs;
+}
+
+
+void MarkerSet::dump()
+{
+  if(marker_start_valid) {
+    printf(" Marker Start %s: ",(const char *)marker_marker);
+    printf("%d mS\n",marker_start_value);
+  }
+  if(marker_end_valid) {
+  printf(" Marker End %s: ",(const char *)marker_marker);
+    printf("%d mS\n",marker_end_value);
+  }
+}
+
+
+int MarkerSet::LimitCheck(int value,int lo_limit,int hi_limit) const
+{
+  if(lo_limit!=-1) {
+    if(value<lo_limit) {
+      return lo_limit;
+    }
+  }
+  if(hi_limit!=-1) {
+    if(value>hi_limit) {
+      return hi_limit;
+    }
+  }
+  return value;
+}
+
+
+int MarkerSet::FrontReference(int value) const
+{
+  if(value>=0) {
+    if(value>marker_audio_length) {
+      return marker_audio_length;
+    }
+    return value;
+  }
+  if((marker_audio_length+value)<0) {
+    return 0;
+  }
+  return marker_audio_length+value;
+}
diff --git a/utils/rdimport/markerset.h b/utils/rdimport/markerset.h
new file mode 100644
index 00000000..63449301
--- /dev/null
+++ b/utils/rdimport/markerset.h
@@ -0,0 +1,50 @@
+// markerset.h
+//
+// Abstract a set of marker parameters.
+//
+//   (C) Copyright 2014 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 MARKERSET_H
+#define MARKERSET_H
+
+#include <rdcmd_switch.h>
+
+class MarkerSet
+{
+ public:
+  MarkerSet();
+  bool hasStartValue() const;
+  int startValue(int lo_limit=-1,int hi_limit=-1) const;
+  bool hasEndValue() const;
+  int endValue(int lo_limit=-1,int hi_limit=-1) const;
+  void load(RDCmdSwitch *cmd,const QString &marker);
+  void setAudioLength(int msecs);
+  void dump();
+
+ private:
+  int LimitCheck(int value,int lo_limit,int hi_limit) const;
+  int FrontReference(int value) const;
+  QString marker_marker;
+  bool marker_start_valid;
+  int marker_start_value;
+  bool marker_end_valid;
+  int marker_end_value;
+  int marker_audio_length;
+};
+
+
+#endif  // MARKERSET_H
diff --git a/utils/rdimport/rdimport.cpp b/utils/rdimport/rdimport.cpp
index 5b457cf2..c1945416 100644
--- a/utils/rdimport/rdimport.cpp
+++ b/utils/rdimport/rdimport.cpp
@@ -246,6 +246,14 @@ MainObject::MainObject(QObject *parent,const char *name)
       import_create_dates=true;
     }
   }
+  import_cut_markers=new MarkerSet();
+  import_cut_markers->load(import_cmd,"cut");
+  import_talk_markers=new MarkerSet();
+  import_talk_markers->load(import_cmd,"talk");
+  import_hook_markers=new MarkerSet();
+  import_hook_markers->load(import_cmd,"hook");
+  import_segue_markers=new MarkerSet();
+  import_segue_markers->load(import_cmd,"segue");
 
   //
   // Read Configuration
@@ -508,6 +516,10 @@ MainObject::MainObject(QObject *parent,const char *name)
     if(import_persistent_dropbox_id>=0) {
       printf(" Persistent DropBox ID = %d\n",import_persistent_dropbox_id);
     }
+    import_cut_markers->dump();
+    import_talk_markers->dump();
+    import_hook_markers->dump();
+    import_segue_markers->dump();
     printf(" Files to process:\n");
     for(unsigned i=import_file_key;i<import_cmd->keys();i++) {
       printf("   \"%s\"\n",(const char *)import_cmd->key(i));
@@ -785,7 +797,6 @@ MainObject::Result MainObject::ImportFile(const QString &filename,
       return MainObject::FileBad;
     }
   }
-
   if(!import_metadata_pattern.isEmpty()) {
     QString groupname=effective_group->name();
     found_cart=RunPattern(import_metadata_pattern,RDGetBasePart(filename),
@@ -1006,6 +1017,30 @@ MainObject::Result MainObject::ImportFile(const QString &filename,
     cut->setStartDaypart(import_dayparts[0],true);
     cut->setEndDaypart(import_dayparts[1],true);
   }
+  import_cut_markers->setAudioLength(wavefile->getExtTimeLength());
+  if(import_cut_markers->hasStartValue()) {
+    cut->setStartPoint(import_cut_markers->startValue());
+    cut->setEndPoint(import_cut_markers->endValue());
+    cut->setLength(cut->endPoint()-cut->startPoint());
+    cart->updateLength();
+  }
+  int lo=cut->startPoint();
+  int hi=cut->endPoint();
+  import_talk_markers->setAudioLength(wavefile->getExtTimeLength());
+  if(import_talk_markers->hasStartValue()) {
+    cut->setTalkStartPoint(import_talk_markers->startValue(lo,hi));
+    cut->setTalkEndPoint(import_talk_markers->endValue(lo,hi));
+  }
+  import_hook_markers->setAudioLength(wavefile->getExtTimeLength());
+  if(import_hook_markers->hasStartValue()) {
+    cut->setHookStartPoint(import_hook_markers->startValue(lo,hi));
+    cut->setHookEndPoint(import_hook_markers->endValue(lo,hi));
+  }
+  import_segue_markers->setAudioLength(wavefile->getExtTimeLength());
+  if(import_segue_markers->hasStartValue()) {
+    cut->setSegueStartPoint(import_segue_markers->startValue(lo,hi));
+    cut->setSegueEndPoint(import_segue_markers->endValue(lo,hi));
+  }
   delete settings;
   delete conv;
   delete cut;
diff --git a/utils/rdimport/rdimport.h b/utils/rdimport/rdimport.h
index fb5022ba..fb3c9d13 100644
--- a/utils/rdimport/rdimport.h
+++ b/utils/rdimport/rdimport.h
@@ -44,6 +44,8 @@
 #include <rdsystem.h>
 #include <rdstation.h>
 
+#include "markerset.h"
+
 #define RDIMPORT_TEMP_BASENAME "rdimp"
 #define RDIMPORT_STDIN_BUFFER_LENGTH 1024
 #define RDIMPORT_DROPBOX_SCAN_INTERVAL 5
@@ -127,6 +129,10 @@ class MainObject : public QObject
   QString import_temp_fix_filename;
   RDSystem *import_system;
   RDStation *import_station;
+  MarkerSet *import_cut_markers;
+  MarkerSet *import_talk_markers;
+  MarkerSet *import_hook_markers;
+  MarkerSet *import_segue_markers;
 };