diff --git a/ChangeLog b/ChangeLog index b1d0638c..c1e7ba62 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14497,3 +14497,199 @@ 2014-09-20 Alban Peignier * Merged patch from albanpeignier to use RDCart::selectCut() in RDSimplePlayer [GitHub issue #000025]. +2014-09-24 Fred Gleason + * Removed redundant line assignments in 'rdlogmanager/edit_clock.cpp'. + * Applied a patch from albanpeignier that adds a 'Clone' button + to the 'Edit Clock' dialog in 'rdlogmanager/edit_clock.cpp' and + 'rdlogmanager/edit_clock.h' [GitHub pull request #000030]. +2014-09-24 Fred Gleason + * Applied a patch from albanpeignier for RDLogEdit that appends + a new cart to a log if 'Add' is touched with no log line highlighted + [GitHub pull request #000031. +2014-09-24 Fred Gleason + * Added code in 'rdlogedit/edit_log.cpp' to append a cart to the + log when the 'End of Log' marker is double-clicked. +2014-09-24 Fred Gleason + * Applied a patch from smowton that fixed a clashing id problem + when auto-refreshing logs in RDAirPlay [GitHub pull request #000028]. +2014-10-07 Fred Gleason + * Added a 'GPIO_EVENTS' table to the database. + * Incremented the database version to 240. + * Implemented GPIO event logging in 'ripcd/local_macros.cpp' and + 'ripcd/ripcd.h'. + * Added an 'Events Log' area to RDGpiMon(1) in + 'utils/rdgpimon/rdgpimon.cpp' and 'utils/rdgpimon/rdgpimon.h'. + * Added code in rdmaint(1) to purge logged GPIO events in + 'utils/rdmaint/rdmaint.cpp' and 'utils/rdmaint/rdmaint.h'. +2014-10-07 Fred Gleason + * Added a 'Report' button to RDGpiMon(1) in + 'utils/rdgpimon/rdgpimon.cpp' and 'utils/rdgpimon/rdgpimon.h'. +2014-10-08 Fred Gleason + * Added code in 'utils/rdimport/rdimport.cpp' to ensure that + imports do not end up with an empty cut description field. +2014-10-08 Fred Gleason + * Applied a patch from albanpeignier that adds a second scheduler + code for music events. + * Added an 'EVENTS.HAVE_CODE2' field to the database. + * Incremented the database version to 241. +2014-10-08 Fred Gleason + * Applied a patch from albanpeignier that fixed a random/null + end point with FLAC imports [GitHub pull request #000034]. +2014-10-09 Fred Gleason + * Implemented the 'RDXPORT_COMMAND_AUDIOSTORE' web API call in + 'web/rdxport/audiostore.cpp', 'web/rdxport/rdxport.cpp' and + 'web/rdxport/rdxport.h'. + * Added an 'RDAudioStore' class in 'lib/rdaudiostore.cpp' and + 'lib/rdaudiostore.h'. + * Modified the Desk Gauge widget in 'rdlibrary/disk_gauge.cpp' + and 'rdlibrary/disk_gauge.h' to use the 'RDAudioStore' class + [fixes GitHub issue #000035]. +2014-10-10 Fred Gleason + * Corrected an error in 'rdlibrary/disk_gauge.cpp' that generated + incorrect free time values. +2014-10-10 Fred Gleason + * Tweaked sensitivity for initiating drags on Sound Panel buttons + in '/lib/rdpanel_button.cpp' [GitHub issue #000032]. +2014-10-10 Fred Gleason + * Adjusted display of Talk Time in button widget to allow for display + of lengths greater than :59 [GitHub issue #000018]. +2014-10-16 Fred Gleason + * Added support for 'HPI_ADAPTER_MODE_9OSTREAM', + 'HPI_ADAPTER_MODE_MONO' and 'HPI_ADAPTER_MODE_LOWLATENCY' modes + in 'utils/rdhpiinfo/change_mode.cpp' and + 'utils/rdhpiinfo/rdhpiinfo.cpp'. + * Implemented proper labeling for 'HPI_ADAPTER_MODE_16OSTREAM' mode + with ASI6x85 adapters. +2014-10-23 Fred Gleason + * Fixed a bug in the 'Edit Audio' dialog in 'lib/rdedit_audio.cpp' + that caused loss of precision when loading the Cut Gain control + [GitHub issue #000037]. +2014-10-24 Fred Gleason + * Added 'REPORTS.POST_EXPORT_CMD' and 'REPORTS.WIN_POST_EXPORT_CMD' + fields to the database. + * Incremented the database version to 242. + * Added 'RDReport::postExportCommand()' and + 'RDReport::setPostExportCommand()' methods in 'lib/rdreport.cpp' and + 'lib/rdreport.h'. + * Added 'Linux Post Export Cmd' and 'Windows Post Export Cmd' controls + to the 'Edit Report' dialog in 'rdadmin/edit_report.cpp' and + 'rdadmin/edit_report.h'. + * Implemented post export commands in 'lib/rdreport.cpp'. +2014-10-25 Fred Gleason + * Created an rdimport(1) man page in 'docs/man/rdimport.1'. +2014-10-25 Fred Gleason + * 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'. +2014-10-25 Fred Gleason + * Implemented '--set-marker-fadedown=' and '--set-marker-fadeup*=' + options for rdimport(1) in 'utils/rdimport/markerset.cpp',, + 'utils/rdimport/markerset.h', 'utils/rdimport/rdimport.cpp' and + 'utils/rdimport/rdimport.h'. +2014-10-25 Fred Gleason + * Added fade markers to the 'MarkerSet::dump()' method in + 'utils/rdimport/markerset.cpp'. +2014-10-25 Fred Gleason + * Implemented '--set-string-*=' options for rdimport(1) in + 'utils/rdimport/rdimport.cpp' and 'utils/rdimport/rdimport.h'. +2014-10-26 Fred Gleason + * Implemented '--set-string-description' and '--set-string-outcue' + options for rdimport(1) in 'utils/rdimport/rdimport.cpp' and + 'utils/rdimport/rdimport.h'. +2014-10-26 Fred Gleason + * Implemented '--set-datetimes' option for rdimport(1) in + 'utils/rdimport/rdimport.cpp' and 'utils/rdimport/rdimport.h'. +2014-10-26 Fred Gleason + * Incremented the package version to 2.9.3int00. +2014-10-27 Fred Gleason + * Fixed a regression in 'lib/rdreport.cpp' that caused RDLogManager + events to be omitted from reports even when the + 'Export Event Types - All' checkbox was selected in combination with + 'Traffic Log' or 'Music Log' checkboxes. [Fixes GitHub issue + #000021]. +2014-10-27 Fred Gleason + * Incremented the package version to 2.9.3int01. +2014-10-28 Fred Gleason + * Updated 'NEWS'. + * Incremented the package version to 2.10.0. +2014-10-30 Fred Gleason + * Fixed a regression in 'lib/rdsimpleplayer.cpp' that caused play + start position to be set incorrectly. +2014-10-30 Fred Gleason + * Added a 'DSP Utilization' readout for rdhpiinfo(8) in + 'utils/rdhpiinfo/rdhpiinfo.cpp' and 'utils/rdhpiinfo/rdhpiinfo.h'. + * Added a 'Profile Details' dialog for rdhpiinfo(8) in + 'utils/rdhpiinfo/virtdetails.cpp' and 'utils/rdhpiinfo/virtdetails.h'. +2014-11-01 Fred Gleason + * Changed policy in 'rdlogedit/edit_log.cpp' so that pasted events + retain external data attributes. +2014-11-01 Fred Gleason + * Incremented the package version to 2.10.0int00. + * Modified 'rdlogedit/edit_log.cpp' so as to retain external data + attributes only when pasting from a 'cut' operation. +2014-11-02 Fred Gleason + * Added an 'EXT DATA' column to the Edit Log dialog on rdlogedit(1) + in 'rdlogedit/edit_log.cpp'. +2014-11-02 Fred Gleason + * Incremented the package version to 2.10.0int01. +2014-11-03 Fred Gleason + * Added a 'usermode-gtk' dependency for RHEL 7 in 'configure.ac'. +2014-11-04 Fred Gleason + * Removed debugging printf from 'utils/rdhpiinfo/rdhpiinfo.cpp'. +2014-11-04 Fred Gleason + * Updated 'NEWS'. + * Incremented the package version to 2.10.1. +2014-11-04 Fred Gleason + * Fixed a bug in 'rdlogedit/drop_listview.cpp' that caused a + segfault when dropping a cart on the log list. +2014-11-06 Fred Gleason + * Incremented the package version to 2.10.1int00. +2014-11-10 Fred Gleason + * Fixed a bug in 'rdlogedit/edit_log.cpp' that allowed GUID data + in the clipboard to be transferred between logs. +2014-11-21 Fred Gleason + * Added a '--clear-datetimes' option to rdimport(1) in + 'utils/rdimport/rdimport.cpp' and 'utils/rdimport/rdimport.h'. +2014-11-21 Fred Gleason + * Added a '--clear-daypart-times' option to rdimport(1) in + 'utils/rdimport/rdimport.cpp' and 'utils/rdimport/rdimport.h'. +2014-11-24 Fred Gleason + * Added support for the ASI5211 in 'rdhpi/rdhpisoundcard.cpp'. +2014-11-24 Fred Gleason + * Fixed a bug in 'rdhpi/rdsoundcard.cpp' that caused AES3-only output + ports to fail to be detected under HPI. +2014-11-24 Fred Gleason + * Fixed a regression in 'rdairplay/log_traffic.cpp' that broke + when writing ELR data to a service with a space in its name. +2014-11-24 Fred Gleason + * Fixed a bug in 'lib/rdsound_panel.cpp that caused action mode colors + be cleared prematurely [GitHub issue #000038]. +2014-11-24 Fred Gleason + * Incremented the package version to 2.10.1int01. +2014-11-25 Fred Gleason + * Updated 'NEWS'. + * Incremented the package version to 2.10.2. +2014-11-30 Fred Gleason + * Fixed missing 'EVENTS.HAVE_CODE2' field in the DB creation code + in 'rdadmin/createdb.cpp'. +2014-12-01 Fred Gleason + * Adjust value of 'STAGE1BUFSIZE' to '16384' in + 'lib/rdaudioconvert.cpp'. +2014-12-01 Fred Gleason + * Fixed a bug in 'utils/rdimport/rdimport.cpp' that failed to + apply automatic segues correctly when the audio store was not + locally accessible. + * Fixed a bug in 'utils/rdimport/rdimport.cpp' that caused the + value of the '--segue-level' options to be wrong by a factor of + 100. + * Refactored the 'RDCut::autoSegue()' method to fetch trim data + via 'RDTrimAudio'. + * Added language in the rdimport(1) man page to resolve ambiguity + regarding how the --segue-level location is dteremined when + normalization is specified. +2014-12-08 Fred Gleason + * Added an RLM for Live 365 in 'rlm/rlm_live365.c'. +2014-12-08 Fred Gleason + * Fixed a bug in 'rlm/rlm_live365.c' where the 'album' field was + not escaped correctly. diff --git a/NEWS b/NEWS index 71087900..82eaae6f 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,80 @@ The NEWS file for the Rivendell package. +------------------------------------------------------------------------------- +v2.10.2 -- 11/26/2014 + +Changes: + RDImport Enhancements. Added '--clear-datetimes' and + '--clear-daypart-times' options to rdimport(1). + + ELR Data. Added a column to allow ELR data to be seen when editing + logs in RDLogEdit. + + HPI Fixes. Fixed a bug that caused ASI cards with only AES3 ports + to fail to detect those ports. + + Various other bug fixes. See the ChangeLog for details. + +Database Update: + This version of Rivendell uses database schema version 242, and will + automatically upgrade any earlier versions. To see the current schema + version prior to upgrade, see RDAdmin->SystemInfo. + + As always, be sure to run RDAdmin immediately after upgrading to allow + any necessary changes to the database schema to be applied. +------------------------------------------------------------------------------- +v2.10.1 -- 11/4/2014 + +Changes: + RDHpiInfo Enhancements. Added DSP utilization and profiling data + readouts for AudioScience audio adapters to rdhpiinfo(8). + + RDLogEdit Enhancements. Added an 'EXT DATA' column to the Edit Log + screen in rdlogedit(1) to allow visibility of ELR GUID data when + making edits. + + Various other bug fixes. See the ChangeLog for details. + +Database Update: + This version of Rivendell uses database schema version 242, and will + automatically upgrade any earlier versions. To see the current schema + version prior to upgrade, see RDAdmin->SystemInfo. + + As always, be sure to run RDAdmin immediately after upgrading to allow + any necessary changes to the database schema to be applied. +------------------------------------------------------------------------------- +v2.10.0 -- 10/28/2014 + +Changes: + Updated Translation. A new French translation has applied, courtesy + of the good folks at Tryphon [http://www.tryphon.eu/]. + + Log Tools Enhancements. Added various UI enhancements in RDLogManager + and RDLogEdit. + + GPIO Logging. Added an event viewer in RDGpiMon to allow GPIO events + to be logged and viewed. + + Music Scheduler Enhancements. Added the ability to utilize a second + Scheduler Code in music events in RDLogManager. + + Report Generation Enhancements. Added the ability to specify a + post-export script when generating reports (analogous to pre-import + scripts for log imports). + + RDImport Enhancements. Added -set-marker-start-*=', + '--set-marker-end-*=', '--set-marker-fadeup*=' '--set-marker-fadedown*=', + '--set-string-*=' and '--set-datetimes' options for rdimport(1). + + Various other bug fixes. See the ChangeLog for details. + +Database Update: + This version of Rivendell uses database schema version 242, and will + automatically upgrade any earlier versions. To see the current schema + version prior to upgrade, see RDAdmin->SystemInfo. + + As always, be sure to run RDAdmin immediately after upgrading to allow + any necessary changes to the database schema to be applied. ------------------------------------------------------------------------------- v2.9.3 -- 9/18/2014 diff --git a/PACKAGE_VERSION b/PACKAGE_VERSION index eafef0d4..d332044b 100644 --- a/PACKAGE_VERSION +++ b/PACKAGE_VERSION @@ -1 +1 @@ -2.9.3 \ No newline at end of file +2.10.2 \ No newline at end of file diff --git a/conf/rlm_live365.conf b/conf/rlm_live365.conf new file mode 100644 index 00000000..328c3b9c --- /dev/null +++ b/conf/rlm_live365.conf @@ -0,0 +1,67 @@ +; rlm_live365.conf +; +; This is the sample configuration file for the 'rlm_live365' module for +; Rivendell, which can be used to update the metadata on an Shoutcast 1.x +; server using Now & Next data. +; +; To enable this module, add it to the 'Loadable Modules' list in +; RDAdmin->ManageHosts->RDAirPlay->ConfigureNow&Next. The 'Argument' +; field should point to the location of this file. +; +; This module requires the curl(1) network transfer tool, included with most +; Linux distros. It is also available at http://curl.haxx.se/. + + +; Section Header +; +; One section per Live365 station is configured, starting with +; 'Station1' and working up consecutively +[Station1] + + +; MemberName +; +; The member name of the Live365 station to which to send updates. +MemberName=my_station + + +; Password +; +; The password of the Live365 station to which to send updates. +Password=changeme + + +; Metadata String. The metadata fields to be sent each time RDAirPlay changes +; play state, including any wildcards as placeholders for metadata values. +; +; The list of available wildcards can be found in the 'metadata_wildcards.txt' +; file in the Rivendell documentation directory. +; +TitleString=%t +ArtistString=%a +AlbumString=%l + + +; Log Selection +; +; Set the status for each log to 'Yes', 'No' or 'Onair' to indicate whether +; state changes on that log should be output to this station. If set +; to 'Onair', then output will be generated only if RDAirPlays OnAir flag +; is active. +MasterLog=Yes +Aux1Log=Yes +Aux2Log=Yes + + +; Additional Live365 stations can be configured by adding new +; sections... +; +;[Station2] +;MemberName=your_station +;Password=changeme +;TitleString=%t +;ArtistString=%a +;AlbumString=%l +;MasterLog=No +;Aux1Log=Yes +;Aux2Log=No diff --git a/configure.ac b/configure.ac index 5c20fb9c..3f8f0344 100644 --- a/configure.ac +++ b/configure.ac @@ -120,17 +120,19 @@ else AC_SUBST(APACHE_PKG,"httpd") AC_SUBST(APACHE_CONFIG_DIR,"/etc/httpd/conf.d") AC_SUBST(CONSOLEHELPER_RDALSACONFIG,"/usr/bin/rdalsaconfig-root") - AC_SUBST(USERMODE_PKG,"usermode") if test $ar_distro_major -ge 7 ; then + AC_SUBST(USERMODE_PKG,"usermode usermode-gtk") AC_SUBST(QT3_MYSQL_PKG,"qt3-MySQL") AC_SUBST(QT3_DEVEL_PKG,"qt3-devel") AC_SUBST(MYSQL_PKG,"mariadb") else if test $ar_distro_major -ge 6 ; then + AC_SUBST(USERMODE_PKG,"usermode") AC_SUBST(QT3_MYSQL_PKG,"qt-MySQL") AC_SUBST(QT3_DEVEL_PKG,"qt3-devel") AC_SUBST(MYSQL_PKG,"mysqld") else + AC_SUBST(USERMODE_PKG,"usermode") AC_SUBST(QT3_MYSQL_PKG,"qt-MySQL") AC_SUBST(QT3_DEVEL_PKG,"qt-devel") AC_SUBST(MYSQL_PKG,"mysqld") @@ -464,8 +466,9 @@ AC_CONFIG_FILES([rivendell.spec \ web/tests/Makefile \ conf/Makefile \ docs/Makefile \ - docs/tables/Makefile \ docs/examples/Makefile \ + docs/man/Makefile \ + docs/tables/Makefile \ debian/Makefile \ debian/patches/Makefile \ xdg/Makefile \ diff --git a/docs/Makefile.am b/docs/Makefile.am index e972a198..5f569dd3 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -4,9 +4,6 @@ ## ## (C) Copyright 2002-2006 Fred Gleason ## -## $Id: Makefile.am,v 1.21.6.5 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. @@ -23,6 +20,7 @@ ## Use automake to process this into a Makefile.in SUBDIRS = examples\ + man\ tables EXTRA_DIST = ALSA.txt\ diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am new file mode 100644 index 00000000..64034b26 --- /dev/null +++ b/docs/man/Makefile.am @@ -0,0 +1,28 @@ +## automake.am +## +## docs/man Automake.am Rivendell +## +## by Fred Gleason +## +## 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 + +man_MANS = rdimport.1 +EXTRA_DIST = $(man_MANS) + +CLEANFILES = *~ +DISTCLEANFILES = moc_* +MAINTAINERCLEANFILES = *~\ + Makefile.in diff --git a/docs/man/rdimport.1 b/docs/man/rdimport.1 new file mode 100644 index 00000000..f89790bf --- /dev/null +++ b/docs/man/rdimport.1 @@ -0,0 +1,365 @@ +.TH rdimport 1 "October 2014" Linux "Rivendell Radio Automation System" +.SH NAME +rdimport \- Audio importation tool for the Rivendell Radio Automation System + +.SH SYNOPSIS +rdimport [OPTIONS] []* + +.SH DESCRIPTION +\fBRdimport\fP is a command-line tool for importing one or more audio files +into the Rivendell Radio Automation System. By default, a new cart will be +created for each file imported, although this behavior can be modified by +use of the appropriate options (see the \fB--single-cart\fP and +\fB--to-cart\fP options, below). A <\fIfilespec\fP> of '-' will cause the +list of filespecs to be read from standard input. + + +.SH OPTIONS +.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. + +.TP +.B --autotrim-level= +Specify the threshold level to use for autotrimming the audio, in dBFS. +Specifying '0' will turn off autotrimming. + +.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 --clear-datetimes +Do not set the cut start and end datetimes, even if such are found in +the file's import metadata. Mutually exclusive with the \fB--set-datetimes\fP +option. + +.TP +.B --clear-daypart-times +Do not set the cut start and end daypart times, even if such are found in +the file's import metadata. Mutually exclusive with the +\fB--set-daypart-times\fP option. + +.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). + +.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= +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 +regular characters to indicate boundaries between metadata fields. + +The available wildcards are: +.RS +.TP +%a +Artist +.TP +%b +Record Label +.TP +%c +Client +.TP +%e +Agency +.TP +%g +Rivendell Group (overrides the <\fIgroup-name\fP> parameter) +.TP +%i +Cut Description +.TP +%l +Album +.TP +%m +Composer +.TP +%n +Rivendell Cart Number +.TP +%o +Cut Outcue +.TP +%p +Publisher +.TP +%r +Conductor +.TP +%s +Song ID +.TP +%t +Title +.TP +%u +User Defined +.TP +%y +Release Year (four digit numeric) +.TP +%% +A literal '%' +.RE +.RE + +Detection of either the Rivendell Group [%g] or Rivendell Cart [%n] +will cause RDImport to attempt to import the file to the specified Group +and/or Cart, overriding whatever values were specified elsewhere on the +command line. If the \fB--set-user-defined\fP option has been used, +then the value specified there will be used instead of %u. + +Boundaries between metadata fields are indicated by placing regular +characters between macros. For example, the pattern '%t_%a_%g_%n.', +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 --normalization-level=<\fIlevel\fP> +Specify the level to use for peak normalizing the audio, in dBFS. +Specifying '0' will turn off normalization. + +.TP +.B --segue-length=<\fIlength\fP> +Length of the added segue in msecs. See \fB--segue-level\fP below. + +.TP +.B --segue-level=<\fIlevel\fP> +Specify the threshold level to use for setting the segue markers, in dBFS, +as measured after any specified normalization has been applied. Default +action is not to create segue markers. + +.TP +.B --set-datetimes=<\fIstart-datetime\fP>,<\fIend-datetime\fP> +Set the cut start and end datetimes, in the format YYYYMMDD-HHMMSS. Mutually +exclusive with \fB--clear-datetimes\fP. + +.TP +.B --set-daypart-times=<\fIstart-time\fP>,<\fIend-time\fP> +Set the cut start and end daypart times, in the format HHMMSS. Mutually +exclusive with \fB--clear-daypart-times\fP. + +.TP +.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 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-fadedown=<\fIoffset\fP> +Set the FadeDown marker to a given offset value. See the discussion of the +\fB--set-marker-end-\fP option above for a description of the +<\fIoffset\fP> parameter. + +.TP +.B --set-marker-fadeup=<\fIoffset\fP> +Set the FadeUp marker to a given offset value. See the discussion of the +\fB--set-marker-end-\fP option above for a description of the +<\fIoffset\fP> parameter. + +.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-\fP option above for a description of the +<\fImarker\fP> and <\fIoffset\fP> parameters. + +.TP +.B --set-string-<\fIfield\fP>=<\fIstring\fP> +Set the cart label field <\fIfield\fP> to <\fIstring\fP>. This will override +any other values --e.g. from \fB--metadata-pattern\fP. Values recognized +for <\fIfield\fP> are: +.RS +.TP +.B agency +Agency Name + +.TP +.B album +Album Name + +.TP +.B artist +Artist Name + +.TP +.B bpm +Beats per Minute (integer numeric) + +.TP +.B client +Client Name + +.TP +.B composer +Music Composer Name + +.TP +.B conductor +Conductor Name + +.TP +.B description +Cut Description + +.TP +.B label +Record Label Name (rights holder) + +.TP +.B outcue +Cut Outcue + +.TP +.B publisher +Music Publisher (rights holder) + +.TP +.B song-id +Song ID + +.TP +.B title +Title + +.TP +.B user-defined +Miscelaneous Information + +.TP +.B year +Year Released (four digit numeric) +.RE +.RE + +.TP +.B --set-user-defined=<\fIstr\fP> +Deprecated. Use the \fB--set-string-user-defined\fP option instead. + +.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 +in order to protect wildcard characters from expansion by the shell. A typical +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 than peak normalization would be more +appropriate for use with the \fB--normalization-level\fP option. + +.SH AUTHOR +Fred Gleason +.SH "SEE ALSO" +.BR http://www.cartchunk.org/ + + + + + + + diff --git a/docs/tables/Makefile.am b/docs/tables/Makefile.am index 0e79576f..72e61260 100644 --- a/docs/tables/Makefile.am +++ b/docs/tables/Makefile.am @@ -41,6 +41,7 @@ EXTRA_DIST = audio_perms.txt\ encoders.txt\ extended_panel_names.txt\ feed_perms.txt\ + gpio_events.txt\ gpis.txt\ gpos.txt\ groups.txt\ @@ -64,6 +65,7 @@ EXTRA_DIST = audio_perms.txt\ repl_cut_state.txt\ replicator_map.txt\ replicators.txt\ + reports.txt\ services.txt\ sources.txt\ stations.txt\ diff --git a/docs/tables/gpio_events.txt b/docs/tables/gpio_events.txt new file mode 100644 index 00000000..70ba3c64 --- /dev/null +++ b/docs/tables/gpio_events.txt @@ -0,0 +1,14 @@ + GPIO_EVENTS Table Layout for Rivendell + +The GPIO_EVENTS table holds data concerning past GPIO events processed +by the system. + +FIELD NAME TYPE REMARKS +------------------------------------------------------------------ +ID int(10) unsigned Primary key, auto increment +STATION_NAME char(64) From STATIONS.NAME +MATRIX int(10) unsigned From MATRICES.MATRIX +NUMBER int(11) +TYPE int(11) 0 = GPI, 1 = GPO +EDGE int(11) 1 = Rising, 0 = Falling +EVENT_DATETIME datetime diff --git a/docs/tables/reports.txt b/docs/tables/reports.txt new file mode 100644 index 00000000..14c46ca6 --- /dev/null +++ b/docs/tables/reports.txt @@ -0,0 +1,29 @@ + REPORTS Table Layout for Rivendell + +The REPORTS table holds data concerning each report configured on the system. + +FIELD NAME TYPE REMARKS +--------------------------------------------------------------- +ID int(10) unsigned Primary Key +NAME char(64) +DESCRIPTION char(64) +EXPORT_FILTER int(11) +EXPORT_PATH char(255) +POST_EXPORT_CMD text +WIN_EXPORT_PATH char(255) +WIN_POST_EXPORT_CMD text +EXPORT_TFC enum('N','Y') +EXPORT_MUS enum('N','Y') +FORCE_MUS enum('N','Y') +EXPORT_GEN enum('N','Y') +STATION_ID char(16) +CART_DIGITS int(10) unsigned +USE_LEADING_ZEROS enum('N','Y') +LINES_PER_PAGE int(11) +SERVICE_NAME char(64) +STATION_TYPE int(11) +STATION_FORMAT char(64) +FILTER_ONAIR_FLAG enum('N','Y') +FILTER_GROUPS enum('N','Y') +START_TIME time +END_TIME time diff --git a/docs/web_api.odt b/docs/web_api.odt index 8ad687f5..23bf8e21 100644 Binary files a/docs/web_api.odt and b/docs/web_api.odt differ diff --git a/lib/Makefile.am b/lib/Makefile.am index 250e8b2b..e751d5b0 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -73,6 +73,7 @@ dist_librd_la_SOURCES = dbversion.h\ rdaudioinfo.cpp rdaudioinfo.h\ rdaudiosettings_dialog.cpp rdaudiosettings_dialog.h\ rdaudiosettings.cpp rdaudiosettings.h\ + rdaudiostore.cpp rdaudiostore.h\ rdbusybar.cpp rdbusybar.h\ rdbusydialog.cpp rdbusydialog.h\ rdbutton_dialog.cpp rdbutton_dialog.h\ @@ -243,6 +244,7 @@ nodist_librd_la_SOURCES = moc_rdadd_cart.cpp\ moc_rdaudioimport.cpp\ moc_rdaudioinfo.cpp\ moc_rdaudiosettings_dialog.cpp\ + moc_rdaudiostore.cpp\ moc_rdbusybar.cpp\ moc_rdbusydialog.cpp\ moc_rdbutton_dialog.cpp\ diff --git a/lib/dbversion.h b/lib/dbversion.h index 12cb5e9c..f2da5961 100644 --- a/lib/dbversion.h +++ b/lib/dbversion.h @@ -26,7 +26,7 @@ /* * Current Database Version */ -#define RD_VERSION_DATABASE 239 +#define RD_VERSION_DATABASE 242 #endif // DBVERSION_H diff --git a/lib/rdaudioconvert.cpp b/lib/rdaudioconvert.cpp index edd9bbbb..429b5450 100644 --- a/lib/rdaudioconvert.cpp +++ b/lib/rdaudioconvert.cpp @@ -526,7 +526,7 @@ RDAudioConvert::ErrorCode RDAudioConvert::Stage1Vorbis(const QString &dstfile, #endif // HAVE_VORBIS } -#define STAGE1BUFSIZE 2500 +#define STAGE1BUFSIZE 16384 RDAudioConvert::ErrorCode RDAudioConvert::Stage1Mpeg(const QString &dstfile, RDWaveFile *wave) diff --git a/lib/rdaudiostore.cpp b/lib/rdaudiostore.cpp new file mode 100644 index 00000000..d07fbd54 --- /dev/null +++ b/lib/rdaudiostore.cpp @@ -0,0 +1,203 @@ +// rdaudiostore.cpp +// +// Get information about the audio store. +// +// (C) Copyright 2014 Fred Gleason +// +// 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 +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +size_t RDAudioStoreCallback(void *ptr,size_t size,size_t nmemb,void *userdata) +{ + QString *xml=(QString *)userdata; + for(unsigned i=0;i<(size*nmemb);i++) { + *xml+=((const char *)ptr)[i]; + } + return size*nmemb; +} + + +RDAudioStore::RDAudioStore(RDStation *station,RDConfig *config, + QObject *parent,const char *name) + : QObject(parent,name) +{ + conv_station=station; + conv_config=config; + conv_free_bytes=0; + conv_total_bytes=0; +} + + +uint64_t RDAudioStore::freeBytes() const +{ + return conv_free_bytes; +} + + +uint64_t RDAudioStore::totalBytes() const +{ + return conv_total_bytes; +} + + +RDAudioStore::ErrorCode RDAudioStore::runStore(const QString &username, + const QString &password) +{ + long response_code; + CURL *curl=NULL; + char url[1024]; + CURLcode curl_err; + + // + // Generate POST Data + // + QString post=QString().sprintf("COMMAND=%d&LOGIN_NAME=%s&PASSWORD=%s", + RDXPORT_COMMAND_AUDIOSTORE, + (const char *)RDFormPost::urlEncode(username), + (const char *)RDFormPost::urlEncode(password)); + if((curl=curl_easy_init())==NULL) { + return RDAudioStore::ErrorInternal; + } + + // + // Write out URL as a C string before passing to curl_easy_setopt(), + // otherwise some versions of LibCurl will throw a 'bad/illegal format' + // error. + // + strncpy(url,conv_station->webServiceUrl(conv_config),1024); + curl_easy_setopt(curl,CURLOPT_URL,url); + curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,RDAudioStoreCallback); + curl_easy_setopt(curl,CURLOPT_WRITEDATA,&conv_xml); + curl_easy_setopt(curl,CURLOPT_POST,1); + curl_easy_setopt(curl,CURLOPT_POSTFIELDS,(const char *)post); + curl_easy_setopt(curl,CURLOPT_TIMEOUT,RD_CURL_TIMEOUT); + + switch(curl_err=curl_easy_perform(curl)) { + case CURLE_OK: + break; + + case CURLE_UNSUPPORTED_PROTOCOL: + case CURLE_FAILED_INIT: + case CURLE_COULDNT_RESOLVE_PROXY: + case CURLE_PARTIAL_FILE: + case CURLE_HTTP_RETURNED_ERROR: + case CURLE_WRITE_ERROR: + case CURLE_OUT_OF_MEMORY: + case CURLE_OPERATION_TIMEDOUT: + case CURLE_HTTP_POST_ERROR: + curl_easy_cleanup(curl); + fprintf(stderr,"curl error: %d\n",curl_err); + return RDAudioStore::ErrorInternal; + + case CURLE_URL_MALFORMAT: + case CURLE_COULDNT_RESOLVE_HOST: + case CURLE_COULDNT_CONNECT: + case 9: // CURLE_REMOTE_ACCESS_DENIED + curl_easy_cleanup(curl); + return RDAudioStore::ErrorUrlInvalid; + + default: + curl_easy_cleanup(curl); + return RDAudioStore::ErrorService; + } + curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,&response_code); + curl_easy_cleanup(curl); + + switch(response_code) { + case 200: + break; + + case 404: + return RDAudioStore::ErrorNoAudio; + + default: + return RDAudioStore::ErrorService; + } + conv_free_bytes=ParseInt("freeBytes",conv_xml); + conv_total_bytes=ParseInt("totalBytes",conv_xml); + + return RDAudioStore::ErrorOk; +} + + +QString RDAudioStore::errorText(RDAudioStore::ErrorCode err) +{ + QString ret=QString().sprintf("Unknown Error [%u]",err); + + switch(err) { + case RDAudioStore::ErrorOk: + ret=tr("OK"); + break; + + case RDAudioStore::ErrorInternal: + ret=tr("Internal Error"); + break; + + case RDAudioStore::ErrorUrlInvalid: + ret=tr("Invalid URL"); + break; + + case RDAudioStore::ErrorService: + ret=tr("RDXport service returned an error"); + break; + + case RDAudioStore::ErrorInvalidUser: + ret=tr("Invalid user or password"); + break; + + case RDAudioStore::ErrorNoAudio: + ret=tr("Audio does not exist"); + break; + } + return ret; +} + + +uint64_t RDAudioStore::ParseInt(const QString &tag,const QString &xml) +{ + // + // FIXME: This is totally ad-hoc, but should work until we settle on + // a proper XML parser. + // + QStringList list=list.split("\n",xml); + for(unsigned i=0;i=2) { + list2=list2.split(">",list2[1]); + if(list2.size()>=2) { + return list2[1].toLongLong(); + } + } + } + } + return -1; +} diff --git a/lib/rdaudiostore.h b/lib/rdaudiostore.h new file mode 100644 index 00000000..a06ed6bb --- /dev/null +++ b/lib/rdaudiostore.h @@ -0,0 +1,55 @@ +// rdaudiostore.h +// +// Get information about the audio store. +// +// (C) Copyright 2014 Fred Gleason +// +// 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 RDAUDIOSTORE_H +#define RDAUDIOSTORE_H + +#include + +#include + +#include +#include + +class RDAudioStore : public QObject +{ + Q_OBJECT; + public: + enum ErrorCode {ErrorOk=0,ErrorInternal=5,ErrorUrlInvalid=7, + ErrorService=8,ErrorInvalidUser=9,ErrorNoAudio=10}; + RDAudioStore(RDStation *station,RDConfig *config,QObject *parent=0, + const char *name=0); + uint64_t freeBytes() const; + uint64_t totalBytes() const; + RDAudioStore::ErrorCode runStore(const QString &username, + const QString &password); + static QString errorText(RDAudioStore::ErrorCode err); + + private: + uint64_t ParseInt(const QString &tag,const QString &xml); + RDStation *conv_station; + RDConfig *conv_config; + QString conv_xml; + uint64_t conv_free_bytes; + uint64_t conv_total_bytes; +}; + + +#endif // RDAUDIOSTORE_H diff --git a/lib/rdcut.cpp b/lib/rdcut.cpp index d9c29dea..f00a86cc 100644 --- a/lib/rdcut.cpp +++ b/lib/rdcut.cpp @@ -40,6 +40,7 @@ #include #include #include +#include // // Global Classes @@ -1295,11 +1296,12 @@ void RDCut::autoTrim(RDCut::AudioEnd end,int level) } -void RDCut::autoSegue(int level,int length) +void RDCut::autoSegue(int level,int length,RDStation *station,RDUser *user, + RDConfig *config) { #ifndef WIN32 int point; - int start_point; + // int start_point; if(!exists()) { return; @@ -1311,17 +1313,23 @@ void RDCut::autoSegue(int level,int length) return; } if(level<0) { - if((point=wave->endTrim(+REFERENCE_LEVEL-level))>-1) { - start_point=(int)(1000.0*(double)point/(double)wave->getSamplesPerSec()); - setSegueStartPoint(start_point); - if(length>0 && (start_point+length)setCartNumber(cart_number); + trim->setCutNumber(cut_number); + trim->setTrimLevel(level); + if(trim->runTrim(user->name(),user->password())==RDTrimAudio::ErrorOk) { + if((point=trim->endPoint())>=0) { + setSegueStartPoint(trim->endPoint()); + if(length>0 && (trim->endPoint()+length)endPoint()+length); + } + else { + setSegueEndPoint(endPoint()); + } } } + delete trim; + } else { if(length>0) { if((endPoint()-length)>startPoint()){ diff --git a/lib/rdcut.h b/lib/rdcut.h index 95eb23dc..54ce3e1b 100644 --- a/lib/rdcut.h +++ b/lib/rdcut.h @@ -131,7 +131,8 @@ class RDCut bool checkInRecording(const QString &stationname,RDSettings *settings, unsigned msecs) const; void autoTrim(RDCut::AudioEnd end,int level); - void autoSegue(int level,int length); + void autoSegue(int level,int length,RDStation *station,RDUser *user, + RDConfig *config); void reset() const; void connect(QObject *receiver,const char *member) const; void disconnect(QObject *receiver,const char *member) const; diff --git a/lib/rdedit_audio.cpp b/lib/rdedit_audio.cpp index 7f70d9aa..528ee3cb 100644 --- a/lib/rdedit_audio.cpp +++ b/lib/rdedit_audio.cpp @@ -892,8 +892,6 @@ RDEditAudio::RDEditAudio(RDCart *cart,QString cut_name,RDCae *cae,RDUser *user, edit_cursors[RDEditAudio::HookEnd]=-1; } edit_gain_control->setValue(edit_cut->playGain()); - edit_gain_edit->setText(QString().sprintf("%4.1f dB", - (double)edit_gain_control->value()/100.0)); edit_trim_box->setValue(trim_level/100); if(edit_cut->segueGain()==0) { edit_overlap_box->setChecked(true); @@ -2232,7 +2230,7 @@ bool RDEditAudio::SaveMarkers() // // Save Settings // - edit_cut->setPlayGain(10*edit_gain_control->value()); + // edit_cut->setPlayGain(10*edit_gain_control->value()); edit_cut->setStartPoint((int)((double)(edit_cursors[RDEditAudio::Start])* 1152000.0/ (double)edit_sample_rate)); diff --git a/lib/rdevent.cpp b/lib/rdevent.cpp index 0ba217b1..2933b49e 100644 --- a/lib/rdevent.cpp +++ b/lib/rdevent.cpp @@ -408,6 +408,17 @@ void RDEvent::setHaveCode(QString str) SetRow("HAVE_CODE",str,true); } +QString RDEvent::HaveCode2() +{ + bool ok; + return GetStringValue("HAVE_CODE2",&ok); +} + + +void RDEvent::setHaveCode2(QString str) +{ + SetRow("HAVE_CODE2",str,true); +} unsigned RDEvent::titleSep() { diff --git a/lib/rdevent.h b/lib/rdevent.h index e8251f87..6d4171e6 100644 --- a/lib/rdevent.h +++ b/lib/rdevent.h @@ -73,6 +73,8 @@ class RDEvent void setSchedGroup(QString str); QString HaveCode(); void setHaveCode(QString str); + QString HaveCode2(); + void setHaveCode2(QString str); unsigned titleSep(); void setTitleSep(unsigned titlesep); static QString preimportTableName(const QString event_name); diff --git a/lib/rdevent_line.cpp b/lib/rdevent_line.cpp index 40ddae7c..2842b304 100644 --- a/lib/rdevent_line.cpp +++ b/lib/rdevent_line.cpp @@ -244,6 +244,16 @@ void RDEventLine::setHaveCode(QString str) event_have_code=str; } +QString RDEventLine::HaveCode2() const +{ + return event_have_code2; +} + + +void RDEventLine::setHaveCode2(QString str) +{ + event_have_code2=str; +} unsigned RDEventLine::titleSep() const { @@ -317,6 +327,7 @@ void RDEventLine::clear() event_autofill_slop=-1; event_sched_group=""; event_have_code=""; + event_have_code2=""; event_title_sep=100; event_nested_event=""; } @@ -328,7 +339,7 @@ bool RDEventLine::load() GRACE_TIME,POST_POINT,USE_AUTOFILL,\ USE_TIMESCALE,IMPORT_SOURCE,START_SLOP,\ END_SLOP,FIRST_TRANS_TYPE,DEFAULT_TRANS_TYPE,\ - COLOR,AUTOFILL_SLOP,NESTED_EVENT,SCHED_GROUP,TITLE_SEP,HAVE_CODE \ + COLOR,AUTOFILL_SLOP,NESTED_EVENT,SCHED_GROUP,TITLE_SEP,HAVE_CODE,HAVE_CODE2 \ from EVENTS where NAME=\"%s\"", (const char *)event_name); RDSqlQuery *q=new RDSqlQuery(sql); @@ -361,7 +372,8 @@ bool RDEventLine::load() event_sched_group=q->value(15).toString(); event_title_sep=q->value(16).toUInt(); event_have_code=q->value(17).toString(); - + event_have_code2=q->value(18).toString(); + delete q; event_preimport_log->load(); event_postimport_log->load(); @@ -383,7 +395,7 @@ bool RDEventLine::save() END_SLOP=%d,FIRST_TRANS_TYPE=%d,\ DEFAULT_TRANS_TYPE=%d,COLOR=\"%s\"\ AUTOFILL_SLOP=%d,NESTED_EVENT=\"%s\",\ - SCHED_GROUP=\"%s\",TITLE_SEP=%d,HAVE_CODE=\"%s\" \ + SCHED_GROUP=\"%s\",TITLE_SEP=%d,HAVE_CODE=\"%s\",HAVE_CODE2=\"%s\" \ where NAME=\"%s\"", (const char *)RDEscapeString(event_properties), event_preposition,event_time_type, @@ -400,6 +412,7 @@ bool RDEventLine::save() (const char *)RDEscapeString(event_sched_group), event_title_sep, (const char*)event_have_code, + (const char*)event_have_code2, (const char *)RDEscapeString(event_name)); } else { @@ -696,8 +709,25 @@ bool RDEventLine::generateLog(QString logname,const QString &svcname, *errors+=QString().sprintf("%s Rule broken: Must have code %s\n",(const char *)time.toString("hh:mm:ss"),(const char*)event_have_code); schedCL->restore(); } - - // Scheduler Codes + + // Must have second scheduler code + if(event_have_code2!="") + { + schedCL->save(); + for(counter=0;countergetNumberOfItems();counter++) + { + if(!schedCL->itemHasCode(counter,event_have_code2)) + { + schedCL->removeItem(counter); + counter--; + } + } + if(schedCL->getNumberOfItems()==0) + *errors+=QString().sprintf("%s Rule broken: Must have second code %s\n",(const char *)time.toString("hh:mm:ss"),(const char*)event_have_code2); + schedCL->restore(); + } + + // Scheduler Codes sql=QString().sprintf("select CODE,MAX_ROW,MIN_WAIT,NOT_AFTER, OR_AFTER,OR_AFTER_II from %s_RULES",(const char *)clockname); q=new RDSqlQuery(sql); while (q->next()) diff --git a/lib/rdevent_line.h b/lib/rdevent_line.h index b34e783b..d61bce02 100644 --- a/lib/rdevent_line.h +++ b/lib/rdevent_line.h @@ -70,6 +70,8 @@ class RDEventLine void setSchedGroup(QString str); QString HaveCode() const; void setHaveCode(QString str); + QString HaveCode2() const; + void setHaveCode2(QString str); unsigned titleSep() const; void setTitleSep(unsigned titlesep); RDLogEvent *preimportCarts(); @@ -112,6 +114,7 @@ class RDEventLine QString event_nested_event; QString event_sched_group; QString event_have_code; + QString event_have_code2; unsigned event_title_sep; }; diff --git a/lib/rdlabel.h b/lib/rdlabel.h index fa5d86f2..6d09937d 100644 --- a/lib/rdlabel.h +++ b/lib/rdlabel.h @@ -38,7 +38,7 @@ class RDLabel : public QLabel Q_OBJECT public: - RDLabel(QWidget *parent,const char *name,WFlags f=0); + RDLabel(QWidget *parent=0,const char *name=0,WFlags f=0); RDLabel(const QString &text,QWidget *parent,const char *name,WFlags f=0); RDLabel(QWidget *buddy,const QString &text,QWidget *parent,const char *name, WFlags f=0); diff --git a/lib/rdlog_event.cpp b/lib/rdlog_event.cpp index d02b6cd0..6b368afd 100644 --- a/lib/rdlog_event.cpp +++ b/lib/rdlog_event.cpp @@ -626,20 +626,22 @@ void RDLogEvent::setLogLine(int line,RDLogLine *ll) } -RDLogLine *RDLogEvent::loglineById(int id) const +RDLogLine *RDLogEvent::loglineById(int id, bool ignore_holdovers) const { - for(int i=0;iid()==id) { - return log_line[i]; - } - } - return NULL; + int line = lineById(id, ignore_holdovers); + if(line == -1) + return NULL; + else + return log_line[line]; } -int RDLogEvent::lineById(int id) const +int RDLogEvent::lineById(int id, bool ignore_holdovers) const { for(int i=0;iisHoldover()) { + continue; + } if(log_line[i]->id()==id) { return i; } diff --git a/lib/rdlog_event.h b/lib/rdlog_event.h index c44ac061..46ae3f52 100644 --- a/lib/rdlog_event.h +++ b/lib/rdlog_event.h @@ -61,8 +61,8 @@ class RDLogEvent QTime blockStartTime(int line); RDLogLine *logLine(int line) const; void setLogLine(int line,RDLogLine *ll); - RDLogLine *loglineById(int id) const; - int lineById(int id) const; + RDLogLine *loglineById(int id, bool ignore_holdovers=false) const; + int lineById(int id, bool ignore_holdovers=false) const; int lineByStartHour(int hour,RDLogLine::StartTimeType type) const; int lineByStartHour(int hour) const; int nextTimeStart(QTime after); diff --git a/lib/rdlog_line.cpp b/lib/rdlog_line.cpp index 4972d136..e0de1876 100644 --- a/lib/rdlog_line.cpp +++ b/lib/rdlog_line.cpp @@ -174,6 +174,7 @@ void RDLogLine::clear() log_link_id=-1; log_link_embedded=false; log_start_source=RDLogLine::StartUnknown; + is_holdover = false; } @@ -2093,3 +2094,13 @@ QString RDLogLine::sourceText(RDLogLine::Source src) } return QObject::tr("Unknown"); } + +bool RDLogLine::isHoldover() const +{ + return is_holdover; +} + +void RDLogLine::setHoldover(bool b) +{ + is_holdover = b; +} diff --git a/lib/rdlog_line.h b/lib/rdlog_line.h index 037fccfe..4855fc8f 100644 --- a/lib/rdlog_line.h +++ b/lib/rdlog_line.h @@ -265,6 +265,8 @@ class RDLogLine static QString typeText(RDLogLine::Type type); static QString timeTypeText(RDLogLine::TimeType type); static QString sourceText(RDLogLine::Source src); + bool isHoldover() const; + void setHoldover(bool); private: int log_id; @@ -368,6 +370,7 @@ class RDLogLine int log_link_end_slop; int log_link_id; bool log_link_embedded; + bool is_holdover; }; diff --git a/lib/rdpanel_button.cpp b/lib/rdpanel_button.cpp index 92c08c02..559d8623 100644 --- a/lib/rdpanel_button.cpp +++ b/lib/rdpanel_button.cpp @@ -357,7 +357,7 @@ void RDPanelButton::keyReleaseEvent(QKeyEvent *e) void RDPanelButton::mousePressEvent(QMouseEvent *e) { - button_move_count=3; + button_move_count=10; QPushButton::mousePressEvent(e); } diff --git a/lib/rdreport.cpp b/lib/rdreport.cpp index 603d4f73..13a6c022 100644 --- a/lib/rdreport.cpp +++ b/lib/rdreport.cpp @@ -20,6 +20,8 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // +#include + #include #include @@ -87,14 +89,27 @@ void RDReport::setFilter(ExportFilter filter) const QString RDReport::exportPath(ExportOs ostype) const { - return RDGetSqlValue("REPORTS","NAME",report_name,OsFieldName(ostype)). - toString(); + return RDGetSqlValue("REPORTS","NAME",report_name, + OsFieldName(ostype)+"EXPORT_PATH").toString(); } void RDReport::setExportPath(ExportOs ostype,const QString &path) const { - SetRow(OsFieldName(ostype),path); + SetRow(OsFieldName(ostype)+"EXPORT_PATH",path); +} + + +QString RDReport::postExportCommand(ExportOs ostype) const +{ + return RDGetSqlValue("REPORTS","NAME",report_name, + OsFieldName(ostype)+"POST_EXPORT_CMD").toString(); +} + + +void RDReport::setPostExportCommand(ExportOs ostype,const QString &cmd) const +{ + SetRow(OsFieldName(ostype)+"POST_EXPORT_CMD",cmd); } @@ -415,15 +430,20 @@ bool RDReport::generateReport(const QDate &startdate,const QDate &enddate, // // Generate Mixdown Table // + // Create Table + // QString mixname="MIXDOWN"+station->name(); sql=QString("drop table `")+mixname+"_SRT`"; - // sql=QString().sprintf("drop table `%s_SRT`",(const char *)mixname); QSqlQuery *p; p=new QSqlQuery(sql); delete p; sql=RDCreateReconciliationTableSql(mixname+"_SRT"); q=new RDSqlQuery(sql); delete q; + + // + // Iterate Selected Services + // sql=QString().sprintf("select SERVICE_NAME from REPORT_SERVICES \ where REPORT_NAME=\"%s\"", (const char *)name()); @@ -433,19 +453,30 @@ bool RDReport::generateReport(const QDate &startdate,const QDate &enddate, if(svc->exists()) { rec_name=q->value(0).toString(); rec_name.replace(" ","_"); + + // + // Generate Type Filters + // force_sql=""; - if(exportTypeForced(RDReport::Traffic)) { - force_sql+=QString().sprintf("(`%s_SRT`.EVENT_SOURCE=%d)||", + if(!exportTypeEnabled(RDReport::Generic)) { + if(exportTypeForced(RDReport::Traffic)|| + exportTypeEnabled(RDReport::Traffic)) { + force_sql+=QString().sprintf("(`%s_SRT`.EVENT_SOURCE=%d)||", (const char *)rec_name, RDLogLine::Traffic); - } - if(exportTypeForced(RDReport::Music)) { - force_sql+=QString().sprintf("(`%s_SRT`.EVENT_SOURCE=%d)||", + } + if(exportTypeForced(RDReport::Music)|| + exportTypeEnabled(RDReport::Music)) { + force_sql+=QString().sprintf("(`%s_SRT`.EVENT_SOURCE=%d)||", (const char *)rec_name, RDLogLine::Music); + } + force_sql=force_sql.left(force_sql.length()-2); } - force_sql=force_sql.left(force_sql.length()-2); + // + // Selected Fields + // sql=QString().sprintf("select LENGTH,LOG_ID,CART_NUMBER,STATION_NAME,\ EVENT_DATETIME,EVENT_TYPE,EXT_START_TIME,\ EXT_LENGTH,EXT_DATA,EXT_EVENT_ID,EXT_ANNC_TYPE,\ @@ -475,9 +506,17 @@ bool RDReport::generateReport(const QDate &startdate,const QDate &enddate, (const char *)rec_name, (const char *)rec_name, (const char *)rec_name); + + // + // OnAir Flag Filter + // if(filterOnairFlag()) { sql+="(ONAIR_FLAG=\"Y\")&&"; } + + // + // Group Filter + // sql+="("; if(!group_sql.isEmpty()) { sql+=QString("(")+group_sql+")&&"; @@ -485,6 +524,10 @@ bool RDReport::generateReport(const QDate &startdate,const QDate &enddate, if(!force_sql.isEmpty()) { sql+=QString("(")+force_sql+")&&"; } + + // + // Daypart Filter + // if(daypart_sql.isEmpty()) { sql+=QString("(EVENT_DATETIME>=\"")+startdate.toString("yyyy-MM-dd")+ " 00:00:00\")&&"+ @@ -549,69 +592,72 @@ bool RDReport::generateReport(const QDate &startdate,const QDate &enddate, bool ret=false; switch(filter()) { - case RDReport::CbsiDeltaFlex: - ret=ExportDeltaflex(startdate,enddate,mixname); - break; + case RDReport::CbsiDeltaFlex: + ret=ExportDeltaflex(startdate,enddate,mixname); + break; - case RDReport::TextLog: - ret=ExportTextLog(startdate,enddate,mixname); - break; + case RDReport::TextLog: + ret=ExportTextLog(startdate,enddate,mixname); + break; - case RDReport::BmiEmr: - ret=ExportBmiEmr(startdate,enddate,mixname); - break; + case RDReport::BmiEmr: + ret=ExportBmiEmr(startdate,enddate,mixname); + break; - case RDReport::NaturalLog: - case RDReport::Technical: - ret=ExportTechnical(startdate,enddate,mixname); - break; + case RDReport::NaturalLog: + case RDReport::Technical: + ret=ExportTechnical(startdate,enddate,mixname); + break; - case RDReport::SoundExchange: - ret=ExportSoundEx(startdate,enddate,mixname); - break; + case RDReport::SoundExchange: + ret=ExportSoundEx(startdate,enddate,mixname); + break; - case RDReport::NprSoundExchange: - ret=ExportNprSoundEx(startdate,enddate,mixname); - break; + case RDReport::NprSoundExchange: + ret=ExportNprSoundEx(startdate,enddate,mixname); + break; - case RDReport::RadioTraffic: - ret=ExportRadioTraffic(startdate,enddate,mixname); - break; + case RDReport::RadioTraffic: + ret=ExportRadioTraffic(startdate,enddate,mixname); + break; - case RDReport::VisualTraffic: - ret=ExportDeltaflex(startdate,enddate,mixname); - break; + case RDReport::VisualTraffic: + ret=ExportDeltaflex(startdate,enddate,mixname); + break; - case RDReport::CounterPoint: - case RDReport::WideOrbit: - ret=ExportRadioTraffic(startdate,enddate,mixname); - break; + case RDReport::CounterPoint: + case RDReport::WideOrbit: + ret=ExportRadioTraffic(startdate,enddate,mixname); + break; - case RDReport::Music1: - ret=ExportRadioTraffic(startdate,enddate,mixname); - break; + case RDReport::Music1: + ret=ExportRadioTraffic(startdate,enddate,mixname); + break; - case RDReport::MusicClassical: - ret=ExportMusicClassical(startdate,enddate,mixname); - break; + case RDReport::MusicClassical: + ret=ExportMusicClassical(startdate,enddate,mixname); + break; - case RDReport::MusicPlayout: - ret=ExportMusicPlayout(startdate,enddate,mixname); - break; + case RDReport::MusicPlayout: + ret=ExportMusicPlayout(startdate,enddate,mixname); + break; - case RDReport::MusicSummary: - ret=ExportMusicSummary(startdate,enddate,mixname); - break; + case RDReport::MusicSummary: + ret=ExportMusicSummary(startdate,enddate,mixname); + break; - default: - return false; - break; + default: + return false; + break; } #ifdef WIN32 *out_path=RDDateDecode(exportPath(RDReport::Windows),startdate); + QString post_cmd=RDDateDecode(postExportCommand(RDReport::Windows),startdate); #else *out_path=RDDateDecode(exportPath(RDReport::Linux),startdate); + QString post_cmd=RDDateDecode(postExportCommand(RDReport::Linux),startdate); #endif + system(post_cmd); // printf("MIXDOWN TABLE: %s_SRT\n",(const char *)mixname); sql=QString().sprintf("drop table `%s_SRT`",(const char *)mixname); q=new RDSqlQuery(sql); @@ -866,10 +912,10 @@ QString RDReport::OsFieldName(ExportOs os) const { switch(os) { case RDReport::Linux: - return QString("EXPORT_PATH"); + return QString(""); case RDReport::Windows: - return QString("WIN_EXPORT_PATH"); + return QString("WIN_"); } return QString(); } diff --git a/lib/rdreport.h b/lib/rdreport.h index e569f08b..d9996f98 100644 --- a/lib/rdreport.h +++ b/lib/rdreport.h @@ -51,6 +51,8 @@ class RDReport void setFilter(ExportFilter filter) const; QString exportPath(ExportOs ostype) const; void setExportPath(ExportOs ostype,const QString &path) const; + QString postExportCommand(ExportOs ostype) const; + void setPostExportCommand(ExportOs ostype,const QString &cmd) const; bool exportTypeEnabled(ExportType type) const; void setExportTypeEnabled(ExportType type,bool state) const; bool exportTypeForced(ExportType type) const; diff --git a/lib/rdsimpleplayer.cpp b/lib/rdsimpleplayer.cpp index 2decad64..a7edd87c 100644 --- a/lib/rdsimpleplayer.cpp +++ b/lib/rdsimpleplayer.cpp @@ -135,7 +135,7 @@ void RDSimplePlayer::play(int start_pos) play_cae->setOutputVolume(play_card,play_stream,i,RD_MUTE_DEPTH); } play_cae->setOutputVolume(play_card,play_stream,play_port,0+play_cut_gain); - play_cae->positionPlay(play_handles.back(),q->value(1).toUInt()+start_pos); + play_cae->positionPlay(play_handles.back(),q->value(0).toUInt()+start_pos); play_cae->play(play_handles.back(), q->value(1).toUInt()-(q->value(0).toUInt()+start_pos), RD_TIMESCALE_DIVISOR,false); diff --git a/lib/rdsound_panel.cpp b/lib/rdsound_panel.cpp index a74bdb36..d3ba9f95 100644 --- a/lib/rdsound_panel.cpp +++ b/lib/rdsound_panel.cpp @@ -886,7 +886,9 @@ void RDSoundPanel::onairFlagChangedData(bool state) void RDSoundPanel::scanPanelData() { - LoadPanel(panel_type,panel_number); + if(panel_action_mode==RDAirPlayConf::Normal) { + LoadPanel(panel_type,panel_number); + } } diff --git a/lib/rdwavefile.cpp b/lib/rdwavefile.cpp index 5c2408de..f825f0fb 100644 --- a/lib/rdwavefile.cpp +++ b/lib/rdwavefile.cpp @@ -3866,6 +3866,8 @@ bool RDWaveFile::GetFlacStreamInfo() bits_per_sample=sinfo.data.stream_info.bits_per_sample; sample_length=sinfo.data.stream_info.total_samples; channels=sinfo.data.stream_info.channels; + ext_time_length=(unsigned)(1000.0*(double)sample_length/(double)samples_per_sec); + time_length=ext_time_length/1000; return true; #else return false; diff --git a/lib/rdxport_interface.h b/lib/rdxport_interface.h index c2b66d31..0b2e75d9 100644 --- a/lib/rdxport_interface.h +++ b/lib/rdxport_interface.h @@ -43,5 +43,7 @@ #define RDXPORT_COMMAND_LISTLOGS 20 #define RDXPORT_COMMAND_LISTSERVICES 21 #define RDXPORT_COMMAND_LISTLOG 22 +#define RDXPORT_COMMAND_AUDIOSTORE 23 + #endif // RDXPORT_INTERFACE_H diff --git a/rdadmin/createdb.cpp b/rdadmin/createdb.cpp index dfd31f89..592c1545 100644 --- a/rdadmin/createdb.cpp +++ b/rdadmin/createdb.cpp @@ -1493,6 +1493,7 @@ bool CreateDb(QString name,QString pwd) SCHED_GROUP VARCHAR(10),\ TITLE_SEP INT(10) UNSIGNED,\ HAVE_CODE VARCHAR(10),\ + HAVE_CODE2 VARCHAR(10),\ HOR_SEP INT(10) UNSIGNED,\ HOR_DIST INT(10) UNSIGNED,\ NESTED_EVENT char(64),\ @@ -1562,7 +1563,9 @@ bool CreateDb(QString name,QString pwd) DESCRIPTION char(64),\ EXPORT_FILTER int,\ EXPORT_PATH char(255),\ + POST_EXPORT_CMD text,\ WIN_EXPORT_PATH char(255),\ + WIN_POST_EXPORT_CMD text,\ EXPORT_TFC enum('N','Y') default 'N',\ FORCE_TFC enum('N','Y') default 'N',\ EXPORT_MUS enum('N','Y') default 'N',\ @@ -2345,16 +2348,32 @@ bool CreateDb(QString name,QString pwd) // // Create DROPBOX_SCHED_CODES table // - sql=QString("create table if not exists DROPBOX_SCHED_CODES(")+ - "ID int auto_increment not null primary key,"+ - "DROPBOX_ID int not null,"+ - "SCHED_CODE char(11) not null," - "index DROPBOX_ID_IDX(DROPBOX_ID),"+ - "index SCHED_CODE_IDX(SCHED_CODE))"; + sql=QString("create table if not exists DROPBOX_SCHED_CODES(")+ + "ID int auto_increment not null primary key,"+ + "DROPBOX_ID int not null,"+ + "SCHED_CODE char(11) not null," + "index DROPBOX_ID_IDX(DROPBOX_ID),"+ + "index SCHED_CODE_IDX(SCHED_CODE))"; if(!RunQuery(sql)) { return false; } - + + // + // Create GPIO_EVENTS table + // + sql=QString("create table if not exists GPIO_EVENTS(")+ + "ID int auto_increment not null primary key,"+ + "STATION_NAME char(64) not null,"+ + "MATRIX int not null,"+ + "NUMBER int not null,"+ + "TYPE int not null,"+ + "EDGE int not null,"+ + "EVENT_DATETIME datetime not null,"+ + "index STATION_NAME_IDX(STATION_NAME,MATRIX,TYPE,EVENT_DATETIME,EDGE))"; + if(!RunQuery(sql)) { + return false; + } + return true; } @@ -8034,8 +8053,41 @@ int UpdateDb(int ver) delete q; } + if(ver<240) { + sql=QString("create table if not exists GPIO_EVENTS(")+ + "ID int auto_increment not null primary key,"+ + "STATION_NAME char(64) not null,"+ + "MATRIX int not null,"+ + "NUMBER int not null,"+ + "TYPE int not null,"+ + "EDGE int not null,"+ + "EVENT_DATETIME datetime not null,"+ + "index STATION_NAME_IDX(STATION_NAME,MATRIX,TYPE,EVENT_DATETIME,EDGE))"; + q=new QSqlQuery(sql); + delete q; + } + + if(ver<241) { + sql=QString("alter table EVENTS add column ")+ + "HAVE_CODE2 VARCHAR(10) after HAVE_CODE"; + q=new QSqlQuery(sql); + delete q; + } + + if(ver<242) { + sql=QString("alter table REPORTS add column ")+ + "POST_EXPORT_CMD text after EXPORT_PATH"; + q=new QSqlQuery(sql); + delete q; + + sql=QString("alter table REPORTS add column ")+ + "WIN_POST_EXPORT_CMD text after WIN_EXPORT_PATH"; + q=new QSqlQuery(sql); + delete q; + } + + - // **** End of version updates **** // diff --git a/rdadmin/edit_report.cpp b/rdadmin/edit_report.cpp index 73808fe9..a4dd5559 100644 --- a/rdadmin/edit_report.cpp +++ b/rdadmin/edit_report.cpp @@ -204,14 +204,36 @@ EditReport::EditReport(QString rptname,QWidget *parent,const char *name) label->setFont(font); label->setAlignment(AlignRight|AlignVCenter|ShowPrefix); + // + // Linux Post Export Command + // + edit_postexport_cmd_edit=new QLineEdit(this); + edit_postexport_cmd_edit->setGeometry(170,178,sizeHint().width()-180,19); + edit_postexport_cmd_edit->setValidator(validator); + label=new QLabel(edit_path_edit,tr("Linux Post Export Cmd:"),this); + label->setGeometry(10,178,155,19); + label->setFont(font); + label->setAlignment(AlignRight|AlignVCenter|ShowPrefix); + // // Windows Export Path // edit_winpath_edit=new QLineEdit(this); - edit_winpath_edit->setGeometry(170,178,sizeHint().width()-180,19); + edit_winpath_edit->setGeometry(170,199,sizeHint().width()-180,19); edit_winpath_edit->setMaxLength(255); label=new QLabel(edit_winpath_edit,tr("Windows Export Path:"),this); - label->setGeometry(10,178,155,19); + label->setGeometry(10,199,155,19); + label->setFont(font); + label->setAlignment(AlignRight|AlignVCenter|ShowPrefix); + + // + // Windows Post Export Command + // + edit_winpostexport_cmd_edit=new QLineEdit(this); + edit_winpostexport_cmd_edit->setGeometry(170,219,sizeHint().width()-180,19); + edit_winpostexport_cmd_edit->setValidator(validator); + label=new QLabel(edit_path_edit,tr("Windows Post Export Cmd:"),this); + label->setGeometry(10,219,155,19); label->setFont(font); label->setAlignment(AlignRight|AlignVCenter|ShowPrefix); @@ -219,28 +241,28 @@ EditReport::EditReport(QString rptname,QWidget *parent,const char *name) // Type Selectors // label=new QLabel(tr("Export Event Types:"),this); - label->setGeometry(10,199,155,19); + label->setGeometry(10,240,155,19); label->setFont(font); label->setAlignment(AlignRight|AlignVCenter|ShowPrefix); edit_traffic_box=new QCheckBox(this); - edit_traffic_box->setGeometry(170,200,15,15); + edit_traffic_box->setGeometry(170,242,15,15); edit_traffic_label=new QLabel(tr("Traffic"),this); - edit_traffic_label->setGeometry(187,199,80,19); + edit_traffic_label->setGeometry(187,241,80,19); edit_traffic_label->setFont(check_font); edit_traffic_label->setAlignment(AlignLeft|AlignVCenter|ShowPrefix); edit_music_box=new QCheckBox(this); - edit_music_box->setGeometry(270,201,15,15); + edit_music_box->setGeometry(270,243,15,15); edit_music_label=new QLabel(tr("Music"),this); - edit_music_label->setGeometry(287,199,80,19); + edit_music_label->setGeometry(287,241,80,19); edit_music_label->setFont(check_font); edit_music_label->setAlignment(AlignLeft|AlignVCenter|ShowPrefix); edit_generic_box=new QCheckBox(this); - edit_generic_box->setGeometry(370,201,15,15); + edit_generic_box->setGeometry(370,243,15,15); label=new QLabel(tr("All"),this); - label->setGeometry(387,199,80,19); + label->setGeometry(387,241,80,19); label->setFont(check_font); label->setAlignment(AlignLeft|AlignVCenter|ShowPrefix); connect(edit_generic_box,SIGNAL(toggled(bool)), @@ -250,21 +272,21 @@ EditReport::EditReport(QString rptname,QWidget *parent,const char *name) // Force Event Source Selectors // label=new QLabel(tr("Export Events From:"),this); - label->setGeometry(10,220,155,19); + label->setGeometry(10,262,155,19); label->setFont(font); label->setAlignment(AlignRight|AlignVCenter|ShowPrefix); edit_forcetraffic_box=new QCheckBox(this); - edit_forcetraffic_box->setGeometry(170,222,15,15); + edit_forcetraffic_box->setGeometry(170,264,15,15); label=new QLabel(tr("Traffic Log"),this); - label->setGeometry(187,220,80,19); + label->setGeometry(187,262,80,19); label->setFont(check_font); label->setAlignment(AlignLeft|AlignVCenter|ShowPrefix); edit_forcemusic_box=new QCheckBox(this); - edit_forcemusic_box->setGeometry(270,222,15,15); + edit_forcemusic_box->setGeometry(270,264,15,15); label=new QLabel(tr("Music Log"),this); - label->setGeometry(287,220,80,19); + label->setGeometry(287,262,80,19); label->setFont(check_font); label->setAlignment(AlignLeft|AlignVCenter|ShowPrefix); @@ -272,11 +294,11 @@ EditReport::EditReport(QString rptname,QWidget *parent,const char *name) // Include Only On Air Events // edit_onairflag_box=new QComboBox(this); - edit_onairflag_box->setGeometry(170,241,60,19); + edit_onairflag_box->setGeometry(170,283,60,19); edit_onairflag_box->insertItem(tr("No")); edit_onairflag_box->insertItem(tr("Yes")); label=new QLabel(edit_onairflag_box,tr("Include Only OnAir Events:"),this); - label->setGeometry(10,241,155,19); + label->setGeometry(10,283,155,19); label->setFont(font); label->setAlignment(AlignRight|AlignVCenter|ShowPrefix); @@ -284,24 +306,24 @@ EditReport::EditReport(QString rptname,QWidget *parent,const char *name) // Daypart Filter // edit_daypart_check=new QCheckBox(this); - edit_daypart_check->setGeometry(60,271,15,15); + edit_daypart_check->setGeometry(60,313,15,15); edit_daypart_label= new QLabel(edit_daypart_check,tr("Filter by Daypart"),this); - edit_daypart_label->setGeometry(edit_daypart_check->geometry().x()+20,271,155,19); + edit_daypart_label->setGeometry(edit_daypart_check->geometry().x()+20,313,155,19); edit_daypart_label->setFont(font); edit_daypart_label->setAlignment(AlignLeft|AlignVCenter|ShowPrefix); edit_starttime_edit=new QTimeEdit(this); - edit_starttime_edit->setGeometry(150,292,80,20); + edit_starttime_edit->setGeometry(150,334,80,20); edit_starttime_label=new QLabel(edit_starttime_edit,tr("Start Time:"),this); - edit_starttime_label->setGeometry(65,292,80,20); + edit_starttime_label->setGeometry(65,334,80,20); edit_starttime_label->setFont(font); edit_starttime_label->setAlignment(AlignRight|AlignVCenter|ShowPrefix); edit_endtime_edit=new QTimeEdit(this); - edit_endtime_edit->setGeometry(335,292,80,20); + edit_endtime_edit->setGeometry(335,334,80,20); edit_endtime_label=new QLabel(edit_endtime_edit,tr("End Time:"),this); - edit_endtime_label->setGeometry(250,292,80,20); + edit_endtime_label->setGeometry(250,334,80,20); edit_endtime_label->setFont(font); edit_endtime_label->setAlignment(AlignRight|AlignVCenter|ShowPrefix); @@ -320,7 +342,7 @@ EditReport::EditReport(QString rptname,QWidget *parent,const char *name) edit_service_sel=new RDListSelector(this); edit_service_sel-> setGeometry((sizeHint().width()-edit_service_sel->sizeHint().width())/2, - 331,edit_service_sel->sizeHint().width(), + 373,edit_service_sel->sizeHint().width(), edit_service_sel->sizeHint().height()); edit_service_sel->sourceSetLabel(tr("Available Services")); edit_service_sel->destSetLabel(tr("Source Services")); @@ -331,7 +353,7 @@ EditReport::EditReport(QString rptname,QWidget *parent,const char *name) edit_station_sel=new RDListSelector(this); edit_station_sel-> setGeometry((sizeHint().width()-edit_station_sel->sizeHint().width())/2, - 445,edit_station_sel->sizeHint().width(), + 477,edit_station_sel->sizeHint().width(), edit_station_sel->sizeHint().height()); edit_station_sel->sourceSetLabel(tr("Available Hosts")); edit_station_sel->destSetLabel(tr("Source Hosts")); @@ -342,15 +364,15 @@ EditReport::EditReport(QString rptname,QWidget *parent,const char *name) edit_group_sel=new RDListSelector(this); edit_group_sel-> setGeometry((sizeHint().width()-edit_group_sel->sizeHint().width())/2, - 576,edit_group_sel->sizeHint().width(), + 593,edit_group_sel->sizeHint().width(), edit_group_sel->sizeHint().height()); edit_group_sel->sourceSetLabel(tr("Available Groups")); edit_group_sel->destSetLabel(tr("Allowed Groups")); edit_group_box=new QCheckBox(this); - edit_group_box->setGeometry(60,552,15,15); + edit_group_box->setGeometry(60,574,15,15); label=new QLabel(edit_group_box,tr("Filter by Groups"),this); - label->setGeometry(edit_group_box->geometry().x()+20,551,155,19); + label->setGeometry(edit_group_box->geometry().x()+20,573,155,19); label->setFont(font); label->setAlignment(AlignLeft|AlignVCenter|ShowPrefix); connect(edit_group_box,SIGNAL(toggled(bool)), @@ -371,8 +393,7 @@ EditReport::EditReport(QString rptname,QWidget *parent,const char *name) // Cancel Button // button=new QPushButton(this); - button->setGeometry(sizeHint().width()-90,sizeHint().height()-60, - 80,50); + button->setGeometry(sizeHint().width()-90,sizeHint().height()-60,80,50); button->setFont(font); button->setText(tr("&Cancel")); connect(button,SIGNAL(clicked()),this,SLOT(cancelData())); @@ -391,7 +412,11 @@ EditReport::EditReport(QString rptname,QWidget *parent,const char *name) edit_stationformat_edit->setText(edit_report->stationFormat()); edit_linesperpage_spin->setValue(edit_report->linesPerPage()); edit_path_edit->setText(edit_report->exportPath(RDReport::Linux)); + edit_postexport_cmd_edit-> + setText(edit_report->postExportCommand(RDReport::Linux)); edit_winpath_edit->setText(edit_report->exportPath(RDReport::Windows)); + edit_winpostexport_cmd_edit-> + setText(edit_report->postExportCommand(RDReport::Windows)); edit_traffic_box-> setChecked(edit_report->exportTypeEnabled(RDReport::Traffic)); edit_music_box-> @@ -482,7 +507,7 @@ EditReport::~EditReport() QSize EditReport::sizeHint() const { - return QSize(500,732); + return QSize(500,749); } @@ -525,7 +550,11 @@ void EditReport::okData() edit_report->setServiceName(edit_servicename_edit->text()); edit_report->setStationFormat(edit_stationformat_edit->text()); edit_report->setExportPath(RDReport::Linux,edit_path_edit->text()); + edit_report-> + setPostExportCommand(RDReport::Linux,edit_postexport_cmd_edit->text()); edit_report->setExportPath(RDReport::Windows,edit_winpath_edit->text()); + edit_report-> + setPostExportCommand(RDReport::Windows,edit_winpostexport_cmd_edit->text()); edit_report-> setExportTypeEnabled(RDReport::Traffic,edit_traffic_box->isChecked()); edit_report-> diff --git a/rdadmin/edit_report.h b/rdadmin/edit_report.h index 677c7ced..9cb998c4 100644 --- a/rdadmin/edit_report.h +++ b/rdadmin/edit_report.h @@ -65,7 +65,9 @@ class EditReport : public QDialog QLineEdit *edit_stationformat_edit; QSpinBox *edit_linesperpage_spin; QLineEdit *edit_path_edit; + QLineEdit *edit_postexport_cmd_edit; QLineEdit *edit_winpath_edit; + QLineEdit *edit_winpostexport_cmd_edit; QLabel *edit_traffic_label; QCheckBox *edit_traffic_box; QLabel *edit_music_label; diff --git a/rdadmin/rdadmin_cs.ts b/rdadmin/rdadmin_cs.ts index 1e215af3..25b28d7f 100644 --- a/rdadmin/rdadmin_cs.ts +++ b/rdadmin/rdadmin_cs.ts @@ -3336,6 +3336,14 @@ pro naplnění databáze zdroji zvuku. End Time: + + Linux Post Export Cmd: + + + + Windows Post Export Cmd: + + EditSettings diff --git a/rdadmin/rdadmin_de.ts b/rdadmin/rdadmin_de.ts index 2f6c5989..6b7532b8 100644 --- a/rdadmin/rdadmin_de.ts +++ b/rdadmin/rdadmin_de.ts @@ -3302,6 +3302,14 @@ in order to populate the audio resources database. End Time: + + Linux Post Export Cmd: + + + + Windows Post Export Cmd: + + EditSettings diff --git a/rdadmin/rdadmin_es.ts b/rdadmin/rdadmin_es.ts index fe882abc..9901761a 100644 --- a/rdadmin/rdadmin_es.ts +++ b/rdadmin/rdadmin_es.ts @@ -3316,6 +3316,14 @@ para generar la base de datos con los recursos de audio disponibles.End Time: + + Linux Post Export Cmd: + + + + Windows Post Export Cmd: + + EditSchedCode diff --git a/rdadmin/rdadmin_fr.ts b/rdadmin/rdadmin_fr.ts index fff77cff..06ec2d69 100644 --- a/rdadmin/rdadmin_fr.ts +++ b/rdadmin/rdadmin_fr.ts @@ -3026,6 +3026,14 @@ in order to populate the audio resources database. End Time: + + Linux Post Export Cmd: + + + + Windows Post Export Cmd: + + EditSettings diff --git a/rdadmin/rdadmin_nb.ts b/rdadmin/rdadmin_nb.ts index 9376b8ff..034c6ca9 100644 --- a/rdadmin/rdadmin_nb.ts +++ b/rdadmin/rdadmin_nb.ts @@ -3301,6 +3301,14 @@ for lydressursar. End Time: + + Linux Post Export Cmd: + + + + Windows Post Export Cmd: + + EditSettings diff --git a/rdadmin/rdadmin_nn.ts b/rdadmin/rdadmin_nn.ts index 9376b8ff..034c6ca9 100644 --- a/rdadmin/rdadmin_nn.ts +++ b/rdadmin/rdadmin_nn.ts @@ -3301,6 +3301,14 @@ for lydressursar. End Time: + + Linux Post Export Cmd: + + + + Windows Post Export Cmd: + + EditSettings diff --git a/rdadmin/rdadmin_pt_BR.ts b/rdadmin/rdadmin_pt_BR.ts index daa8b2b4..7db3fbb2 100644 --- a/rdadmin/rdadmin_pt_BR.ts +++ b/rdadmin/rdadmin_pt_BR.ts @@ -3294,6 +3294,14 @@ Isto para popular os recursos de áudio na Base de Dados. End Time: + + Linux Post Export Cmd: + + + + Windows Post Export Cmd: + + EditSettings diff --git a/rdairplay/log_play.cpp b/rdairplay/log_play.cpp index eeb25369..68e20fdc 100644 --- a/rdairplay/log_play.cpp +++ b/rdairplay/log_play.cpp @@ -503,7 +503,7 @@ void LogPlay::load() if(lines[running-1]<(size()-1)) { remove(lines[running-1]+1,size()-lines[running-1]-1,false); } - for(int i=running-2;i>0;i--) { + for(int i=running-1;i>0;i--) { remove(lines[i-1]+1,lines[i]-lines[i-1]-1,false); } if(lines[0]!=0) { @@ -511,6 +511,12 @@ void LogPlay::load() } } + // Note that events left in the log are holdovers from a previous log. + // Their IDs may clash with those of events in the log we will now load, + // and it may be appropriate to ignore them in that case. + for(int i = 0, ilim = size(); i != ilim; ++i) + logLine(i)->setHoldover(true); + // // Load Events // @@ -588,6 +594,7 @@ bool LogPlay::refresh() int current_id=-1; int lines[TRANSPORT_QUANTITY]; int running; + int first_non_holdover = 0; if(play_macro_running) { play_refresh_pending=true; @@ -633,7 +640,12 @@ bool LogPlay::refresh() for(int i=0;istatus()!=RDLogLine::Scheduled) { - if((s=e->loglineById(d->id()))!=NULL) { + if((!d->isHoldover()) && (s=e->loglineById(d->id()))!=NULL) { + // A holdover event may be finished or active, + // but should not supress the addition of an + // event with the same ID in this log. + // Incrementing its ID here may flag it as an orphan + // to be removed in step 4. s->incrementPass(); } d->incrementPass(); @@ -649,6 +661,15 @@ bool LogPlay::refresh() } } + // Find first non-holdover event, where start-of-log + // new events should be added: + for(int i=0;isize();i++) { + if(logLine(i)->isHoldover()) + ++first_non_holdover; + else + break; + } + // // Pass 3: Add New Events // @@ -656,15 +677,15 @@ bool LogPlay::refresh() s=e->logLine(i); if(s->pass()==0) { if((prev_line=(i-1))<0) { // First Event - insert(0,s,false,true); + insert(first_non_holdover,s,false,true); } else { prev_id=e->logLine(prev_line)->id(); - insert(lineById(prev_id)+1,s,false,true); + insert(lineById(prev_id, /*ignore_holdovers=*/true)+1,s,false,true); } } else { - loglineById(s->id())->incrementPass(); + loglineById(s->id(), /*ignore_holdovers=*/true)->incrementPass(); } } @@ -681,13 +702,16 @@ bool LogPlay::refresh() // // Restore Next Event // - if(current_id!=-1 && e->loglineById(current_id)!=NULL) { //Make Next after currently playing cart - if((next_line=lineById(current_id))>=0) { + if(current_id!=-1 && e->loglineById(current_id)!=NULL) { + // Make Next after currently playing cart + // The next event cannot have been a holdover, + // as holdovers are always either active or finished. + if((next_line=lineById(current_id, /*ignore_holdovers=*/true))>=0) { makeNext(next_line+1,false); } } else { - if((next_line=lineById(next_id))>=0) { + if((next_line=lineById(next_id, /*ignore_holdovers=*/true))>=0) { makeNext(next_line,false); } } diff --git a/rdairplay/log_traffic.cpp b/rdairplay/log_traffic.cpp index 00c7f3be..b9d2cc44 100644 --- a/rdairplay/log_traffic.cpp +++ b/rdairplay/log_traffic.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -46,7 +47,7 @@ void LogTraffic(const QString &svcname,const QString &logname, if((logline==NULL)||(svcname.isEmpty())) { return; } - sql=QString("insert into `")+svcname+"_SRT` set "+ + sql=QString("insert into `")+RDSvc::svcTableName(svcname)+"` set "+ QString().sprintf("LENGTH=%d,",length)+ "LOG_NAME=\""+RDEscapeString(logname.utf8())+"\","+ QString().sprintf("LOG_ID=%d,",logline->id())+ diff --git a/rdairplay/loglinebox.cpp b/rdairplay/loglinebox.cpp index a1b002b1..a75bc155 100644 --- a/rdairplay/loglinebox.cpp +++ b/rdairplay/loglinebox.cpp @@ -134,7 +134,7 @@ LogLineBox::LogLineBox(RDAirPlayConf *conf,QWidget *parent,const char *name) // // Count Up // - line_up_label=new QLabel(this,"line_up_label"); + line_up_label=new QLabel(this); line_up_label->setGeometry(5,65,65,16); line_up_label->setAlignment(AlignLeft|AlignVCenter); line_up_label->setFont(line_font); @@ -143,7 +143,7 @@ LogLineBox::LogLineBox(RDAirPlayConf *conf,QWidget *parent,const char *name) // // Position Slider // - line_position_bar=new QProgressBar(this,"line_position_bar"); + line_position_bar=new QProgressBar(this); line_position_bar->setGeometry(75,66,sizeHint().width()-150,13); line_position_bar->setPercentageVisible(false); line_position_bar->hide(); @@ -151,7 +151,7 @@ LogLineBox::LogLineBox(RDAirPlayConf *conf,QWidget *parent,const char *name) // // Count Down // - line_down_label=new QLabel(this,"line_down_label"); + line_down_label=new QLabel(this); line_down_label->setGeometry(sizeHint().width()-72,65,65,16); line_down_label->setAlignment(AlignLeft|AlignVCenter); line_down_label->setFont(line_font); @@ -160,7 +160,7 @@ LogLineBox::LogLineBox(RDAirPlayConf *conf,QWidget *parent,const char *name) // // Cut Description // - line_description_label=new QLabel(this,"line_description_label"); + line_description_label=new QLabel(this); line_description_label->setGeometry((sizeHint().width()/2),48,(sizeHint().width()/2 -10),16); line_description_label->setFont(line_font); line_description_label->hide(); @@ -168,7 +168,7 @@ LogLineBox::LogLineBox(RDAirPlayConf *conf,QWidget *parent,const char *name) // // Outcue // - line_outcue_label=new QLabel(this,"line_outcue_label"); + line_outcue_label=new QLabel(this); line_outcue_label->setGeometry(5,48, (sizeHint().width()/2 -10),16); line_outcue_label->setFont(outcue_font); line_outcue_label->hide(); @@ -176,21 +176,21 @@ LogLineBox::LogLineBox(RDAirPlayConf *conf,QWidget *parent,const char *name) // // Artist // - line_artist_label=new QLabel(this,"line_artist_label"); + line_artist_label=new QLabel(this); line_artist_label->setGeometry(5,33,sizeHint().width()-10,16); line_artist_label->setFont(line_font); // // Title // - line_title_label=new QLabel(this,"line_title_label"); + line_title_label=new QLabel(this); line_title_label->setGeometry(5,18,sizeHint().width()-10,18); line_title_label->setFont(line_bold_font); // // Marker Comment // - line_comment_label=new RDLabel(this,"line_comment_label"); + line_comment_label=new RDLabel(this); line_comment_label->setGeometry(5,18,sizeHint().width()-10,62); line_comment_label->setFont(line_font); line_comment_label->setAlignment(AlignTop|AlignLeft); @@ -200,35 +200,35 @@ LogLineBox::LogLineBox(RDAirPlayConf *conf,QWidget *parent,const char *name) // // Icon // - line_icon_label=new QLabel(this,"line_icon_label"); + line_icon_label=new QLabel(this); line_icon_label->setGeometry(5,3,45,16); // // Cart // - line_cart_label=new QLabel(this,"line_cart_label"); + line_cart_label=new QLabel(this); line_cart_label->setGeometry(25,3,53,16); line_cart_label->setFont(line_font); // // Cut // - line_cut_label=new QLabel(this,"line_cut_label"); + line_cut_label=new QLabel(this); line_cut_label->setGeometry(80,3,24,16); line_cut_label->setFont(line_font); // // Group // - line_group_label=new QLabel(this,"line_group_label"); + line_group_label=new QLabel(this); line_group_label->setGeometry(107,3,75,16); line_group_label->setFont(line_bold_font); // // Time // - line_time_label=new QLabel(this,"line_time_label"); - line_time_label->setGeometry(185,3,85,16); + line_time_label=new QLabel(this); + line_time_label->setGeometry(185,3,70,16); line_time_label->setFont(line_font); line_time_label->setAlignment(AlignRight); line_time_label->setPalette(line_time_palette); @@ -236,15 +236,15 @@ LogLineBox::LogLineBox(RDAirPlayConf *conf,QWidget *parent,const char *name) // // Talk Time // - line_talktime_label=new QLabel(this,"line_talktime_label"); - line_talktime_label->setGeometry(273,3,21,16); + line_talktime_label=new QLabel(this); + line_talktime_label->setGeometry(257,3,36,16); line_talktime_label->setFont(talk_font); line_talktime_label->setAlignment(AlignRight); // // Length // - line_length_label=new QLabel(this,"line_length_label"); + line_length_label=new QLabel(this); line_length_label->setGeometry(297,3,40,16); line_length_label->setFont(line_font); line_length_label->setAlignment(AlignRight); @@ -252,7 +252,7 @@ LogLineBox::LogLineBox(RDAirPlayConf *conf,QWidget *parent,const char *name) // // Transition Type // - line_trans_label=new QLabel(this,"line_trans_label"); + line_trans_label=new QLabel(this); line_trans_label->setGeometry(sizeHint().width()-53,3,48,16); line_trans_label->setAlignment(AlignRight); line_trans_label->setFont(line_bold_font); @@ -262,7 +262,7 @@ LogLineBox::LogLineBox(RDAirPlayConf *conf,QWidget *parent,const char *name) // // Countdown Timer // - line_countdown_timer=new QTimer(this,"line_countdown_timer"); + line_countdown_timer=new QTimer(this); connect(line_countdown_timer,SIGNAL(timeout()),this,SLOT(countdownData())); setAcceptDrops(true); @@ -844,6 +844,7 @@ void LogLineBox::dropEvent(QDropEvent *e) void LogLineBox::SetColor(QColor color) { setBackgroundColor(color); + // color=Qt::red; line_cart_label->setBackgroundColor(color); line_cut_label->setBackgroundColor(color); line_group_label->setBackgroundColor(color); diff --git a/rdhpi/rdhpiinformation.cpp b/rdhpi/rdhpiinformation.cpp index 43219e9d..89e1bb92 100644 --- a/rdhpi/rdhpiinformation.cpp +++ b/rdhpi/rdhpiinformation.cpp @@ -20,6 +20,8 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // +#include + #include diff --git a/rdhpi/rdhpisoundcard.cpp b/rdhpi/rdhpisoundcard.cpp index 21708542..fe379581 100644 --- a/rdhpi/rdhpisoundcard.cpp +++ b/rdhpi/rdhpisoundcard.cpp @@ -668,6 +668,7 @@ void RDHPISoundCard::HPIProbe() } switch(hpi_adapter_list[i]) { case 0x5111: + case 0x5211: input_mux_type[i]=true; break; @@ -687,10 +688,6 @@ void RDHPISoundCard::HPIProbe() &dummy_type)); hpi_info[i].setSerialNumber(dummy_serial); hpi_info[i].setHpiVersion(dummy_hpi); - /* - hpi_info[i].setHpiMajorVersion(dummy_hpi>>8); - hpi_info[i].setHpiMinorVersion(dummy_hpi&255); - */ hpi_info[i].setDspMajorVersion((dummy_version>>13)&7); hpi_info[i].setDspMinorVersion((dummy_version>>7)&63); hpi_info[i].setPcbVersion((char)(((dummy_version>>3)&7)+'A')); @@ -749,11 +746,16 @@ void RDHPISoundCard::HPIProbe() // str=QString(tr("Output Port")); for(int k=0;k -#include #include +#include #include #include #include +#include DiskGauge::DiskGauge(int samp_rate,int chans,QWidget *parent,const char *name) : QWidget(parent,name) @@ -41,27 +42,29 @@ DiskGauge::DiskGauge(int samp_rate,int chans,QWidget *parent,const char *name) QFont label_font("Helvetica",12,QFont::Bold); label_font.setPixelSize(12); - disk_label=new QLabel("Free:",this,"free_label"); + disk_label=new QLabel("Free:",this); disk_label->setGeometry(0,0,50,sizeHint().height()); disk_label->setFont(label_font); disk_label->setAlignment(AlignRight|AlignVCenter); + disk_label->setDisabled(true); disk_bar=new QProgressBar(this); disk_bar->setPercentageVisible(false); disk_bar->setGeometry(55,0,sizeHint().width()-55,sizeHint().height()); + disk_bar->setDisabled(true); disk_space_label=new QLabel(this); disk_space_label->setFont(label_font); disk_space_label->setAlignment(AlignCenter); + disk_space_label->setDisabled(true); - struct statfs diskstat; - statfs(RDConfiguration()->audioRoot().ascii(),&diskstat); - disk_bar->setTotalSteps(GetMinutes(diskstat.f_blocks,diskstat.f_bsize)); + /* update(); + */ - QTimer *timer=new QTimer(this,"update_timer"); - connect(timer,SIGNAL(timeout()),this,SLOT(update())); - timer->start(DISK_GAUGE_UPDATE_INTERVAL); + disk_timer=new QTimer(this); + connect(disk_timer,SIGNAL(timeout()),this,SLOT(update())); + disk_timer->start(100); } @@ -79,12 +82,26 @@ QSizePolicy DiskGauge::sizePolicy() const void DiskGauge::update() { - struct statfs diskstat; - statfs(RDConfiguration()->audioRoot().ascii() ,&diskstat); - int mins=GetMinutes(diskstat.f_bavail,diskstat.f_bsize); - disk_bar->setProgress(mins); - disk_space_label-> - setText(QString().sprintf("%dh %02dm",mins/60,mins-60*(mins/60))); + if(lib_user==NULL) { + return; + } + RDAudioStore::ErrorCode conv_err; + RDAudioStore *conv=new RDAudioStore(rdstation_conf,lib_config,this); + if((conv_err=conv->runStore(lib_user->name(),lib_user->password()))== + RDAudioStore::ErrorOk) { + uint64_t free_min=GetMinutes(conv->freeBytes()); + uint64_t total_min=GetMinutes(conv->totalBytes()); + disk_bar->setTotalSteps(total_min); + disk_bar->setProgress(free_min); + disk_space_label->setText(QString().sprintf("%luh %02lum",free_min/60, + free_min-60*(free_min/60))); + disk_label->setEnabled(true); + disk_bar->setEnabled(true); + disk_space_label->setEnabled(true); + } + delete conv; + disk_timer->stop(); + disk_timer->start(DISK_GAUGE_UPDATE_INTERVAL,true); } @@ -100,8 +117,20 @@ void DiskGauge::resizeEvent(QResizeEvent *e) } -int DiskGauge::GetMinutes(long blocks,long block_size) +unsigned DiskGauge::GetMinutes(uint64_t bytes) { - return (int)(((double)blocks*(double)block_size)/ - (disk_sample_rate*disk_channels*120.0)); + unsigned ret=0; + + switch(rdlibrary_conf->defaultFormat()) { + case 1: // MPEG Layer 2 + ret=bytes*2/(rdlibrary_conf->defaultChannels()* + rdlibrary_conf->defaultBitrate()*15); + break; + + default: // PCM16 + ret=bytes/(rdlibrary_conf->defaultChannels()*2*lib_system->sampleRate()*60); + break; + } + return ret; } + diff --git a/rdlibrary/disk_gauge.h b/rdlibrary/disk_gauge.h index ee227e77..2cebca2c 100644 --- a/rdlibrary/disk_gauge.h +++ b/rdlibrary/disk_gauge.h @@ -23,8 +23,11 @@ #ifndef DISK_GAUGE_H #define DISK_GAUGE_H +#include + #include #include +#include #include #define DISK_GAUGE_UPDATE_INTERVAL 60000 @@ -44,12 +47,13 @@ class DiskGauge : public QWidget void resizeEvent(QResizeEvent *e); private: - int GetMinutes(long blocks,long block_size); + unsigned GetMinutes(uint64_t bytes); QLabel *disk_label; QProgressBar *disk_bar; QLabel *disk_space_label; double disk_sample_rate; double disk_channels; + QTimer *disk_timer; }; diff --git a/rdlogedit/drop_listview.cpp b/rdlogedit/drop_listview.cpp index d14bb3ee..68f41dcc 100644 --- a/rdlogedit/drop_listview.cpp +++ b/rdlogedit/drop_listview.cpp @@ -49,7 +49,7 @@ void DropListView::dropEvent(QDropEvent *e) if(RDCartDrag::decode(e,&ll)) { RDListViewItem *item=(RDListViewItem *)itemAt(pos); if(item!=NULL) { - line=item->text(13).toInt(); + line=item->text(14).toInt(); } emit cartDropped(line,&ll); } diff --git a/rdlogedit/edit_log.cpp b/rdlogedit/edit_log.cpp index efed57cf..31834e8f 100644 --- a/rdlogedit/edit_log.cpp +++ b/rdlogedit/edit_log.cpp @@ -339,12 +339,14 @@ EditLog::EditLog(QString logname,vector *clipboard, edit_log_list->setColumnAlignment(10,Qt::AlignHCenter); edit_log_list->addColumn(tr("SOURCE")); edit_log_list->setColumnAlignment(11,Qt::AlignHCenter); - edit_log_list->addColumn(tr("LINE ID")); + edit_log_list->addColumn(tr("EXT DATA")); edit_log_list->setColumnAlignment(12,Qt::AlignHCenter); - edit_log_list->addColumn(tr("COUNT")); + edit_log_list->addColumn(tr("LINE ID")); edit_log_list->setColumnAlignment(13,Qt::AlignHCenter); - edit_log_list->setHardSortColumn(13); - edit_log_list->setColumnSortType(13,RDListView::LineSort); + edit_log_list->addColumn(tr("COUNT")); + edit_log_list->setColumnAlignment(14,Qt::AlignHCenter); + edit_log_list->setHardSortColumn(14); + edit_log_list->setColumnSortType(14,RDListView::LineSort); if(editing_allowed) { connect(edit_log_list,SIGNAL(doubleClicked(QListViewItem *)), this,SLOT(doubleClickData(QListViewItem *))); @@ -686,13 +688,12 @@ void EditLog::insertCartButtonData() int id; QListViewItem *item=SingleSelection(); - if(item==NULL) { - return; + if(item==NULL || (line=item->text(14).toInt())<0) { + line=edit_log_event->size(); + id=END_MARKER_ID; + } else { + id=item->text(13).toInt(); } - if((line=item->text(13).toInt())<0) { - line=0; - } - id=item->text(12).toInt(); edit_log_event->insert(line,1); edit_log_event->logLine(line)->setTransType(edit_default_trans); edit_log_event->logLine(line)->setFadeupGain(-3000); @@ -732,8 +733,8 @@ void EditLog::insertMarkerButtonData() if(item==NULL) { return; } - line=item->text(13).toInt(); - id=item->text(12).toInt(); + line=item->text(14).toInt(); + id=item->text(13).toInt(); AddMeta *meta=new AddMeta(this,"add_meta_dialog"); switch((RDLogLine::Type)meta->exec()) { case RDLogLine::Marker: @@ -819,7 +820,12 @@ void EditLog::selectionChangedData() void EditLog::doubleClickData(QListViewItem *item) { - editButtonData(); + if(item->text(13).toInt()==END_MARKER_ID) { + insertCartButtonData(); + } + else { + editButtonData(); + } } @@ -834,8 +840,8 @@ void EditLog::editButtonData() if(item==NULL) { return; } - int id=item->text(12).toInt(); - int line=item->text(13).toInt(); + int id=item->text(13).toInt(); + int line=item->text(14).toInt(); if(id==END_MARKER_ID) { return; } @@ -848,7 +854,7 @@ void EditLog::editButtonData() &edit_group_list,edit_log_event,line, this,"edit_logline"); if(edit_cart->exec()>=0) { - edit_log_event->refresh(item->text(13).toInt()); + edit_log_event->refresh(item->text(14).toInt()); edit_changed=true; } delete edit_cart; @@ -899,9 +905,9 @@ void EditLog::deleteButtonData() while(next!=NULL) { if(edit_log_list->isSelected(next)) { - if(next->text(12).toInt()!=END_MARKER_ID) { + if(next->text(13).toInt()!=END_MARKER_ID) { if(count==0) { - line=next->text(13).toInt(); + line=next->text(14).toInt(); } count++; } @@ -915,14 +921,14 @@ void EditLog::deleteButtonData() void EditLog::upButtonData() { QListViewItem *item=SingleSelection(); - if((item==NULL)||(item->text(13).toInt()==0)|| - (item->text(12).toInt()==END_MARKER_ID)) { + if((item==NULL)||(item->text(14).toInt()==0)|| + (item->text(13).toInt()==END_MARKER_ID)) { return; } - int id=item->text(12).toInt(); - sscanf((const char *)item->text(12),"%u",&id); - edit_log_event->move(item->text(13).toInt(), - item->text(13).toInt()-1); + int id=item->text(13).toInt(); + sscanf((const char *)item->text(13),"%u",&id); + edit_log_event->move(item->text(14).toInt(), + item->text(14).toInt()-1); edit_changed=true; RefreshList(); SelectRecord(id); @@ -934,13 +940,13 @@ void EditLog::downButtonData() { QListViewItem *item=SingleSelection(); - if((item==NULL)||(item->text(13).toInt()==(edit_log_list->childCount()-2))|| - (item->text(12).toInt()==END_MARKER_ID)) { + if((item==NULL)||(item->text(14).toInt()==(edit_log_list->childCount()-2))|| + (item->text(13).toInt()==END_MARKER_ID)) { return; } - int id=item->text(12).toInt(); - edit_log_event->move(item->text(13).toInt(), - item->text(13).toInt()+1); + int id=item->text(13).toInt(); + edit_log_event->move(item->text(14).toInt(), + item->text(14).toInt()+1); edit_changed=true; RefreshList(); SelectRecord(id); @@ -950,7 +956,7 @@ void EditLog::downButtonData() void EditLog::cutButtonData() { - copyButtonData(); + LoadClipboard(false); deleteButtonData(); UpdateTracks(); UpdateSelection(); @@ -959,17 +965,7 @@ void EditLog::cutButtonData() void EditLog::copyButtonData() { - QListViewItem *next=edit_log_list->firstChild(); - - edit_clipboard->clear(); - while(next!=NULL) { - if((edit_log_list->isSelected(next))&& - (next->text(12).toInt()!=END_MARKER_ID)) { - edit_clipboard-> - push_back(*edit_log_event->logLine(next->text(13).toInt())); - } - next=next->nextSibling(); - } + LoadClipboard(true); } @@ -979,14 +975,15 @@ void EditLog::pasteButtonData() if((item==NULL)||(edit_clipboard->size()==0)) { return; } - int line=item->text(13).toInt(); - int id=item->text(12).toInt(); + int line=item->text(14).toInt(); + int id=item->text(13).toInt(); edit_log_event->insert(line,edit_clipboard->size()); for(unsigned i=0;isize();i++) { edit_clipboard->at(i).setId(edit_log_event->logLine(line+i)->id()); *edit_log_event->logLine(line+i)=edit_clipboard->at(i); - edit_log_event->logLine(line+i)->clearExternalData(); + // edit_log_event->logLine(line+i)->clearExternalData(); edit_log_event->logLine(line+i)->setSource(RDLogLine::Manual); + edit_clipboard->at(i).clearExternalData(); } edit_changed=true; RefreshList(); @@ -1020,18 +1017,18 @@ void EditLog::cartDroppedData(int line,RDLogLine *ll) edit_changed=true; if(appended) { item=(RDListViewItem *)edit_log_list->lastItem(); - item->setText(13,QString().sprintf("%d",item->text(13).toInt()+1)); + item->setText(14,QString().sprintf("%d",item->text(14).toInt()+1)); } else { item=(RDListViewItem *)edit_log_list-> - findItem(QString().sprintf("%d",line),13); - item->setText(13,QString().sprintf("%d",item->text(13).toInt()+1)); + findItem(QString().sprintf("%d",line),14); + item->setText(14,QString().sprintf("%d",item->text(14).toInt()+1)); while((item=(RDListViewItem *)item->nextSibling())!=NULL) { - item->setText(13,QString().sprintf("%d",item->text(13).toInt()+1)); + item->setText(14,QString().sprintf("%d",item->text(14).toInt()+1)); } } item=new RDListViewItem(edit_log_list); - item->setText(13,QString().sprintf("%d",line)); + item->setText(14,QString().sprintf("%d",line)); RefreshLine(item); edit_log_list->sort(); edit_log_list->clearSelection(); @@ -1156,6 +1153,9 @@ void EditLog::okData() #ifndef WIN32 edit_player->stop(); #endif // WIN32 + for(unsigned i=0;isize();i++) { + edit_clipboard->at(i).clearExternalData(); + } done(0); } @@ -1186,6 +1186,9 @@ void EditLog::cancelData() #ifndef WIN32 edit_player->stop(); #endif // WIN32 + for(unsigned i=0;isize();i++) { + edit_clipboard->at(i).clearExternalData(); + } done(1); } @@ -1290,7 +1293,7 @@ void EditLog::DeleteLines(int line,int count) } } item=(RDListViewItem *)edit_log_list-> - findItem(QString().sprintf("%d",line),13); + findItem(QString().sprintf("%d",line),14); for(int i=0;inextSibling(); delete item; @@ -1339,7 +1342,7 @@ void EditLog::SaveLog() void EditLog::RefreshLine(RDListViewItem *item) { - int line=item->text(13).toInt(); + int line=item->text(14).toInt(); if(line<0) { return; } @@ -1514,8 +1517,9 @@ void EditLog::RefreshLine(RDListViewItem *item) item->setText(11,tr("Voice Tracker")); break; } + item->setText(12,logline->extData()); item-> - setText(12,QString().sprintf("%d",logline->id())); + setText(13,QString().sprintf("%d",logline->id())); UpdateColor(item,logline); } @@ -1527,11 +1531,11 @@ void EditLog::RefreshList() edit_log_list->clear(); l=new RDListViewItem(edit_log_list); l->setText(6,tr("--- end of log ---")); - l->setText(12,QString().sprintf("%d",END_MARKER_ID)); - l->setText(13,QString().sprintf("%d",edit_log_event->size())); + l->setText(13,QString().sprintf("%d",END_MARKER_ID)); + l->setText(14,QString().sprintf("%d",edit_log_event->size())); for(int i=edit_log_event->size()-1;i>=0;i--) { l=new RDListViewItem(edit_log_list); - l->setText(13,QString().sprintf("%d",i)); + l->setText(14,QString().sprintf("%d",i)); RefreshLine(l); } } @@ -1548,11 +1552,11 @@ void EditLog::UpdateSelection() int end_line=-1; while(next!=NULL) { if(edit_log_list->isSelected(next)) { - if((start_line<0)&&(next->text(12).toInt()!=END_MARKER_ID)) { - start_line=next->text(13).toInt(); + if((start_line<0)&&(next->text(13).toInt()!=END_MARKER_ID)) { + start_line=next->text(14).toInt(); } - if(next->text(12).toInt()!=END_MARKER_ID) { - end_line=next->text(13).toInt(); + if(next->text(13).toInt()!=END_MARKER_ID) { + end_line=next->text(14).toInt(); } } next=next->nextSibling(); @@ -1563,11 +1567,11 @@ void EditLog::UpdateSelection() } return; } - if(rditem->text(12).toInt()>0) { + if(rditem->text(13).toInt()>0) { edit_endtime_edit->setText(RDGetTimeLength(edit_log_event-> - length(rditem->text(13).toInt(),edit_log_event->size()),true,false)); + length(rditem->text(14).toInt(),edit_log_event->size()),true,false)); edit_stoptime_label->setText(tr("Next Stop:")); - int stoplen=edit_log_event->lengthToStop(rditem->text(13).toInt()); + int stoplen=edit_log_event->lengthToStop(rditem->text(14).toInt()); if(stoplen>=0) { edit_stoptime_edit->setText(RDGetTimeLength(stoplen,true,false)); } @@ -1648,11 +1652,11 @@ void EditLog::RenumberList(int line) item=item->nextSibling(); } while(item!=NULL) { - item->setText(13,QString().sprintf("%d",line++)); + item->setText(14,QString().sprintf("%d",line++)); prev=item; item=item->nextSibling(); } - prev->setText(12,QString().sprintf("%d",END_MARKER_ID)); + prev->setText(13,QString().sprintf("%d",END_MARKER_ID)); } @@ -1661,7 +1665,7 @@ void EditLog::SelectRecord(int id) QListViewItem *item=edit_log_list->firstChild(); while(item!=NULL) { - if(item->text(12).toInt()==id) { + if(item->text(13).toInt()==id) { edit_log_list->setSelected(item,true); edit_log_list->ensureItemVisible(item); return; @@ -1697,7 +1701,7 @@ bool EditLog::ValidateSvc() bool valid=true; RDListViewItem *item=(RDListViewItem *)edit_log_list->firstChild(); while(item!=NULL) { - if((logline=edit_log_event->logLine(item->text(13).toInt()))!=NULL) { + if((logline=edit_log_event->logLine(item->text(14).toInt()))!=NULL) { valid&=UpdateColor(item,logline); } item=(RDListViewItem *)item->nextSibling(); @@ -1739,3 +1743,22 @@ bool EditLog::DeleteTracks() } return true; } + + +void EditLog::LoadClipboard(bool clear_ext) +{ + QListViewItem *next=edit_log_list->firstChild(); + + edit_clipboard->clear(); + while(next!=NULL) { + if((edit_log_list->isSelected(next))&& + (next->text(13).toInt()!=END_MARKER_ID)) { + edit_clipboard-> + push_back(*edit_log_event->logLine(next->text(14).toInt())); + if(clear_ext) { + edit_clipboard->back().clearExternalData(); + } + } + next=next->nextSibling(); + } +} diff --git a/rdlogedit/edit_log.h b/rdlogedit/edit_log.h index 6597cc48..893e49a3 100644 --- a/rdlogedit/edit_log.h +++ b/rdlogedit/edit_log.h @@ -102,6 +102,7 @@ class EditLog : public QDialog void UpdateTracks(); bool DeleteTracks(); bool ValidateSvc(); + void LoadClipboard(bool clear_ext); RDListViewItem *SingleSelection(); RDLog *edit_log; RDLogEvent *edit_log_event; diff --git a/rdlogedit/rdlogedit_cs.ts b/rdlogedit/rdlogedit_cs.ts index 097657fd..0541c724 100644 --- a/rdlogedit/rdlogedit_cs.ts +++ b/rdlogedit/rdlogedit_cs.ts @@ -397,6 +397,10 @@ jež jsou pro vybranou službu zakázány! Unable to save log, audio deletion error! Soubor se zápisem nelze uložit, chyba při mazání zvuku! + + EXT DATA + + EditLogLine diff --git a/rdlogedit/rdlogedit_de.ts b/rdlogedit/rdlogedit_de.ts index 1726c8c1..cfa38cb7 100644 --- a/rdlogedit/rdlogedit_de.ts +++ b/rdlogedit/rdlogedit_de.ts @@ -397,6 +397,10 @@ die für den gewählten Service ungültig sind! Unable to save log, audio deletion error! Kann Logdatei nicht speichern, Audiolöschfehler! + + EXT DATA + + EditLogLine diff --git a/rdlogedit/rdlogedit_es.ts b/rdlogedit/rdlogedit_es.ts index 07aebe5b..20d92dfe 100644 --- a/rdlogedit/rdlogedit_es.ts +++ b/rdlogedit/rdlogedit_es.ts @@ -397,6 +397,10 @@ desactivados para el servicio actual! Unable to save log, audio deletion error! No es posible guardar la Lista, ¡error por eliminación de audio! + + EXT DATA + + EditLogLine diff --git a/rdlogedit/rdlogedit_fr.ts b/rdlogedit/rdlogedit_fr.ts index 24135a59..f2ad1b4f 100644 --- a/rdlogedit/rdlogedit_fr.ts +++ b/rdlogedit/rdlogedit_fr.ts @@ -388,6 +388,10 @@ for the selected service! Unable to save log, audio deletion error! + + EXT DATA + + EditLogLine diff --git a/rdlogedit/rdlogedit_nb.ts b/rdlogedit/rdlogedit_nb.ts index 8a98dc18..8b635ec7 100644 --- a/rdlogedit/rdlogedit_nb.ts +++ b/rdlogedit/rdlogedit_nb.ts @@ -404,6 +404,10 @@ skrudd av for denne tenesta! Unable to save log, audio deletion error! + + EXT DATA + + EditLogLine diff --git a/rdlogedit/rdlogedit_nn.ts b/rdlogedit/rdlogedit_nn.ts index 8a98dc18..8b635ec7 100644 --- a/rdlogedit/rdlogedit_nn.ts +++ b/rdlogedit/rdlogedit_nn.ts @@ -404,6 +404,10 @@ skrudd av for denne tenesta! Unable to save log, audio deletion error! + + EXT DATA + + EditLogLine diff --git a/rdlogedit/rdlogedit_pt_BR.ts b/rdlogedit/rdlogedit_pt_BR.ts index 200f622b..f888d982 100644 --- a/rdlogedit/rdlogedit_pt_BR.ts +++ b/rdlogedit/rdlogedit_pt_BR.ts @@ -399,6 +399,10 @@ para o serviço selecionado! Unable to save log, audio deletion error! + + EXT DATA + + EditLogLine diff --git a/rdlogmanager/edit_clock.cpp b/rdlogmanager/edit_clock.cpp index 4d4baf9d..db706f7c 100644 --- a/rdlogmanager/edit_clock.cpp +++ b/rdlogmanager/edit_clock.cpp @@ -123,16 +123,25 @@ EditClock::EditClock(QString clockname,bool new_clock, // Add Button // QPushButton *button=new QPushButton(this,"add_button"); - button->setGeometry(70,sizeHint().height()-210,80,50); + button->setGeometry(10,sizeHint().height()-210,80,50); button->setFont(bold_font); button->setText(tr("&Add")); connect(button,SIGNAL(clicked()),this,SLOT(addData())); + // + // Clone Button + // + button=new QPushButton(this,"clone_button"); + button->setGeometry(110,sizeHint().height()-210,80,50); + button->setFont(bold_font); + button->setText(tr("&Clone")); + connect(button,SIGNAL(clicked()),this,SLOT(cloneData())); + // // Edit Button // button=new QPushButton(this,"edit_button"); - button->setGeometry(160,sizeHint().height()-210,80,50); + button->setGeometry(210,sizeHint().height()-210,80,50); button->setFont(bold_font); button->setText(tr("&Edit")); connect(button,SIGNAL(clicked()),this,SLOT(editData())); @@ -141,7 +150,7 @@ EditClock::EditClock(QString clockname,bool new_clock, // Delete Button // button=new QPushButton(this,"delete_button"); - button->setGeometry(250,sizeHint().height()-210,80,50); + button->setGeometry(310,sizeHint().height()-210,80,50); button->setFont(bold_font); button->setText(tr("&Delete")); connect(button,SIGNAL(clicked()),this,SLOT(deleteData())); @@ -316,7 +325,6 @@ void EditClock::editData() return; } int line=item->text(4).toInt(); - line=item->text(4).toInt(); EditEventLine *edit_eventline=new EditEventLine(edit_clock->eventLine(line), edit_clock,line, this,"edit_eventline"); @@ -330,6 +338,38 @@ void EditClock::editData() RefreshList(); } +void EditClock::cloneData() +{ + RDListViewItem *item=(RDListViewItem *)edit_clocks_list->selectedItem(); + if(item==NULL) { + return; + } + if(item->text(4).isEmpty()) { + return; + } + int line=item->text(4).toInt(); + + RDEventLine *selectedEventLine = edit_clock->eventLine(line); + + RDEventLine eventline; + eventline.setName(selectedEventLine->name()); + eventline.setStartTime(selectedEventLine->startTime().addMSecs(selectedEventLine->length())); + eventline.setLength(selectedEventLine->length()); + + EditEventLine *edit_eventline=new EditEventLine(&eventline,edit_clock,-1, + this,"edit_eventline"); + if(edit_eventline->exec()<0) { + delete edit_eventline; + return; + } + delete edit_eventline; + edit_clock->insert(eventline.name(),line); + edit_clock->eventLine(line)->setStartTime(eventline.startTime()); + edit_clock->eventLine(line)->setLength(eventline.length()); + edit_clock->eventLine(line)->load(); + edit_modified=true; + RefreshList(line); +} void EditClock::deleteData() { diff --git a/rdlogmanager/edit_clock.h b/rdlogmanager/edit_clock.h index 96baf8c8..c88d4b8b 100644 --- a/rdlogmanager/edit_clock.h +++ b/rdlogmanager/edit_clock.h @@ -57,6 +57,7 @@ class EditClock : public QDialog private slots: void selectionChangedData(QListViewItem *); void addData(); + void cloneData(); void editData(); void deleteData(); void svcData(); diff --git a/rdlogmanager/edit_event.cpp b/rdlogmanager/edit_event.cpp index 05029d9c..139f933c 100644 --- a/rdlogmanager/edit_event.cpp +++ b/rdlogmanager/edit_event.cpp @@ -529,6 +529,23 @@ EditEvent::EditEvent(QString eventname,bool new_event, } delete q2; + // And code + + event_have_code2_label= + new QLabel(tr("and code"),this,"event_have_code2_label"); + event_have_code2_label->setFont(bold_font); + event_have_code2_label->setGeometry(CENTER_LINE+420,425,100,20); + + event_have_code2_box=new QComboBox(this,"event_have_code2_box"); + event_have_code2_box->setGeometry(CENTER_LINE+510,425,100,20); + event_have_code2_box->insertItem(""); + sql2="select CODE from SCHED_CODES order by CODE"; + q2=new RDSqlQuery(sql2); + while(q2->next()) { + event_have_code2_box->insertItem(q2->value(0).toString()); + } + delete q2; + // // Start Slop Time @@ -798,6 +815,7 @@ EditEvent::EditEvent(QString eventname,bool new_event, } event_title_sep_spinbox->setValue(event_event->titleSep()); event_have_code_box->setCurrentText(event_event->HaveCode()); + event_have_code2_box->setCurrentText(event_event->HaveCode2()); QColor color=event_event->color(); if(color.isValid()) { event_color_button->setPalette(QPalette(color,backgroundColor())); @@ -1070,6 +1088,8 @@ void EditEvent::importClickedData(int id) event_title_sep_spinbox->setEnabled(stateschedinv); event_have_code_box->setEnabled(stateschedinv); event_have_code_label->setEnabled(stateschedinv); + event_have_code2_box->setEnabled(stateschedinv); + event_have_code2_label->setEnabled(stateschedinv); } @@ -1511,7 +1531,14 @@ void EditEvent::Save() event_event->setProperties(GetProperties()); event_event->setSchedGroup(event_sched_group_box->currentText()); event_event->setTitleSep(event_title_sep_spinbox->value()); - event_event->setHaveCode(event_have_code_box->currentText()); + event_event->setHaveCode(event_have_code_box->currentText()); + if (event_have_code_box->currentText() != QString("")) { + event_event->setHaveCode2(event_have_code2_box->currentText()); + } else { + // save second code as first code when first code isn't defined + event_event->setHaveCode(event_have_code2_box->currentText()); + event_event->setHaveCode2(QString("")); + } listname=event_name; listname.replace(" ","_"); event_preimport_list->logEvent()-> diff --git a/rdlogmanager/edit_event.h b/rdlogmanager/edit_event.h index 433f66e1..88adb6d5 100644 --- a/rdlogmanager/edit_event.h +++ b/rdlogmanager/edit_event.h @@ -110,6 +110,8 @@ class EditEvent : public QDialog QLabel *event_title_sep_label; QComboBox* event_have_code_box; QLabel *event_have_code_label; + QComboBox* event_have_code2_box; + QLabel *event_have_code2_label; LibListView *event_lib_list; QPixmap *event_playout_map; QPixmap *event_macro_map; diff --git a/rdlogmanager/rdlogmanager_cs.ts b/rdlogmanager/rdlogmanager_cs.ts index 1c5f2cbf..2ecc2fed 100644 --- a/rdlogmanager/rdlogmanager_cs.ts +++ b/rdlogmanager/rdlogmanager_cs.ts @@ -185,6 +185,10 @@ Chcete je uložit? Remarks Poznámky + + &Clone + + EditEvent @@ -516,6 +520,10 @@ Chcete ji přepsat? IMPORT + + and code + + EditEventLine diff --git a/rdlogmanager/rdlogmanager_de.ts b/rdlogmanager/rdlogmanager_de.ts index bf8d90f4..3318329e 100644 --- a/rdlogmanager/rdlogmanager_de.ts +++ b/rdlogmanager/rdlogmanager_de.ts @@ -185,6 +185,10 @@ Wollen Sie sie speichern? Remarks Bemerkungen + + &Clone + + EditEvent @@ -516,6 +520,10 @@ Wollen Sie es überschreiben? IMPORT + + and code + + EditEventLine diff --git a/rdlogmanager/rdlogmanager_es.ts b/rdlogmanager/rdlogmanager_es.ts index b3a60a17..135fa886 100644 --- a/rdlogmanager/rdlogmanager_es.ts +++ b/rdlogmanager/rdlogmanager_es.ts @@ -187,6 +187,10 @@ horario Remarks Comentarios + + &Clone + + EditEvent @@ -518,6 +522,10 @@ Do you want to overwrite it? IMPORT IMPORTAR + + and code + + EditEventLine diff --git a/rdlogmanager/rdlogmanager_fr.ts b/rdlogmanager/rdlogmanager_fr.ts index 7b9fbb6b..85294697 100644 --- a/rdlogmanager/rdlogmanager_fr.ts +++ b/rdlogmanager/rdlogmanager_fr.ts @@ -182,6 +182,10 @@ Do you want to save? Remarks + + &Clone + + EditEvent @@ -511,6 +515,10 @@ Do you want to overwrite it? IMPORT + + and code + + EditEventLine diff --git a/rdlogmanager/rdlogmanager_nb.ts b/rdlogmanager/rdlogmanager_nb.ts index b6ae2944..499408b8 100644 --- a/rdlogmanager/rdlogmanager_nb.ts +++ b/rdlogmanager/rdlogmanager_nb.ts @@ -186,6 +186,10 @@ Vil du lagra? Remarks + + &Clone + + EditEvent @@ -525,6 +529,10 @@ Vil du byta henne ut? IMPORT + + and code + + EditEventLine diff --git a/rdlogmanager/rdlogmanager_nn.ts b/rdlogmanager/rdlogmanager_nn.ts index b6ae2944..499408b8 100644 --- a/rdlogmanager/rdlogmanager_nn.ts +++ b/rdlogmanager/rdlogmanager_nn.ts @@ -186,6 +186,10 @@ Vil du lagra? Remarks + + &Clone + + EditEvent @@ -525,6 +529,10 @@ Vil du byta henne ut? IMPORT + + and code + + EditEventLine diff --git a/rdlogmanager/rdlogmanager_pt_BR.ts b/rdlogmanager/rdlogmanager_pt_BR.ts index b86fc8af..29995146 100644 --- a/rdlogmanager/rdlogmanager_pt_BR.ts +++ b/rdlogmanager/rdlogmanager_pt_BR.ts @@ -187,6 +187,10 @@ Você quer salvar? That code is already in use! Este Código já está em uso! + + &Clone + + EditEvent @@ -518,6 +522,10 @@ Você quer sobreescrêve-lo? IMPORT + + and code + + EditEventLine diff --git a/ripcd/local_macros.cpp b/ripcd/local_macros.cpp index 1997df2c..0829cf6c 100644 --- a/ripcd/local_macros.cpp +++ b/ripcd/local_macros.cpp @@ -50,6 +50,7 @@ void MainObject::gpiChangedData(int matrix,int line,bool state) if(ripcd_gpi_macro[matrix][line][state]>0) { ExecCart(ripcd_gpi_macro[matrix][line][state]); } + LogGpioEvent(matrix,line,RDMatrix::GpioInput,state); } @@ -70,6 +71,7 @@ void MainObject::gpoChangedData(int matrix,int line,bool state) if(ripcd_gpo_macro[matrix][line][state]>0) { ExecCart(ripcd_gpo_macro[matrix][line][state]); } + LogGpioEvent(matrix,line,RDMatrix::GpioOutput,state); } @@ -125,6 +127,24 @@ void MainObject::ExecCart(int cartnum) } +void MainObject::LogGpioEvent(int matrix,int line,RDMatrix::GpioType type, + bool state) +{ + QString sql; + RDSqlQuery *q; + + sql=QString("insert into GPIO_EVENTS set ")+ + "STATION_NAME=\""+RDEscapeString(rdstation->name())+"\","+ + QString().sprintf("MATRIX=%d,",matrix)+ + QString().sprintf("NUMBER=%d,",line+1)+ + QString().sprintf("TYPE=%d,",type)+ + QString().sprintf("EDGE=%d,",state)+ + "EVENT_DATETIME=now()"; + q=new RDSqlQuery(sql); + delete q; +} + + void MainObject::LoadLocalMacros() { QString sql; diff --git a/ripcd/ripcd.h b/ripcd/ripcd.h index 5f6f800d..18b4c9f3 100644 --- a/ripcd/ripcd.h +++ b/ripcd/ripcd.h @@ -83,6 +83,7 @@ class MainObject : public QObject private: void SetUser(QString username); void ExecCart(int cartnum); + void LogGpioEvent(int matrix,int line,RDMatrix::GpioType type,bool state); void ParseCommand(int); void DispatchCommand(int); void KillSocket(int); diff --git a/rivendell.ism b/rivendell.ism index 3d7bf160..c3419303 100755 Binary files a/rivendell.ism and b/rivendell.ism differ diff --git a/rivendell.spec.in b/rivendell.spec.in index 69c58953..d22ea1ea 100644 --- a/rivendell.spec.in +++ b/rivendell.spec.in @@ -283,6 +283,7 @@ rm -rf $RPM_BUILD_ROOT @WIN32_PATH@ /etc/pam.d/rdalsaconfig-root /etc/security/console.apps/rdalsaconfig-root +%{_mandir}/man1/rdimport.1.gz %doc AUTHORS %doc ChangeLog %doc COPYING diff --git a/rlm/Makefile-example b/rlm/Makefile-example index f50cf4e1..d8f890ca 100644 --- a/rlm/Makefile-example +++ b/rlm/Makefile-example @@ -23,6 +23,7 @@ OBJS = rlm_ando.rlm\ rlm_icecast2.rlm\ rlm_inno713.rlm\ rlm_liqcomp.rlm\ + rlm_live365.rlm\ rlm_padpoint.rlm\ rlm_serial.rlm\ rlm_shoutcast1.rlm\ diff --git a/rlm/Makefile.am b/rlm/Makefile.am index f9eeb336..fe406e9e 100644 --- a/rlm/Makefile.am +++ b/rlm/Makefile.am @@ -29,6 +29,7 @@ RLM_MODULES=rlm_ando.rlm\ rlm_icecast2.rlm\ rlm_inno713.rlm\ rlm_liqcomp.rlm\ + rlm_live365.rlm\ rlm_padpoint.rlm\ rlm_serial.rlm\ rlm_shoutcast1.rlm\ @@ -65,6 +66,7 @@ EXTRA_DIST = Makefile-example\ rlm_icecast2.c\ rlm_inno713.c\ rlm_liqcomp.c\ + rlm_live365.c\ rlm_padpoint.c\ rlm_serial.c\ rlm_shoutcast1.c\ diff --git a/rlm/rlm_live365.c b/rlm/rlm_live365.c new file mode 100644 index 00000000..1467ac34 --- /dev/null +++ b/rlm/rlm_live365.c @@ -0,0 +1,303 @@ +/* rlm_live365.c + * + * (C) Copyright 2014 Fred Gleason + * + * 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. + * + * This is a Rivendell Loadable Module. It uses Now&Next PAD data + * to update the metadata on an Icecast2 mountpoint specified in the + * configuration file pointed to by the plugin argument. + * + * This module requires the curl(1) network transfer tool, included with + * most Linux distros. It is also available at http://curl.haxx.se/. + * + * To compile this module, just do: + * + * gcc -shared -o rlm_live365.rlm rlm_live365.c + */ + +#include +#include +#include +#include +#include +#include + +#include + +int rlm_live365_devs; +char *rlm_live365_stations; +char *rlm_live365_passwords; +char *rlm_live365_titles; +char *rlm_live365_artists; +char *rlm_live365_albums; +int *rlm_live365_masters; +int *rlm_live365_aux1s; +int *rlm_live365_aux2s; + + +int rlm_live365_BufferDiff(char *sString,int dOrigin,int dDiff,int dMaxSize) +{ + int dOldSize,dNewSize; + int i; + + /* + * Will it fit? + */ + dOldSize=strlen(sString); + if((dOldSize+dDiff)>=dMaxSize) { + return -1; + } + dNewSize=dOldSize+dDiff; + + /* + * Adding characters + */ + if(dDiff>0) { + for(i=dOldSize;i>dOrigin;i--) { + sString[i+dDiff]=sString[i]; + } + return dNewSize; + } + + /* + * No Change + */ + if(dDiff==0) { + return dNewSize; + } + + /* + * Deleting Characters + */ + if(dDiff<0) { + for(i=dOrigin;i'9') && (sString[i]<'A')) || + ((sString[i]>'Z') && (sString[i]<'a')) || + (sString[i]>'z'))) { + if(rlm_live365_BufferDiff(sString,i,2,dMaxSize)<0) { + return -1; + } + sprintf(sAccum,"%%%2x",sString[i]); + sString[i++]=sAccum[0]; + sString[i++]=sAccum[1]; + sString[i]=sAccum[2]; + } + if(sString[i]==' ') { + sString[i]='+'; + } + i++; + if(i>=dMaxSize) { + return -1; + } + } + return strlen(sString); +} + + +int rlm_live365_GetLogStatus(void *ptr,const char *arg,const char *section, + const char *logname) +{ + const char *tag=RLMGetStringValue(ptr,arg,section,logname,""); + if(strcasecmp(tag,"yes")==0) { + return 1; + } + if(strcasecmp(tag,"on")==0) { + return 1; + } + if(strcasecmp(tag,"true")==0) { + return 1; + } + if(strcasecmp(tag,"no")==0) { + return 0; + } + if(strcasecmp(tag,"off")==0) { + return 0; + } + if(strcasecmp(tag,"false")==0) { + return 0; + } + if(strcasecmp(tag,"onair")==0) { + return 2; + } + return 0; +} + + +void rlm_live365_RLMStart(void *ptr,const char *arg) +{ + char password[256]; + char section[256]; + char errtext[256]; + int i=1; + + rlm_live365_devs=0; + rlm_live365_stations=NULL; + rlm_live365_passwords=NULL; + rlm_live365_titles=NULL; + rlm_live365_artists=NULL; + rlm_live365_albums=NULL; + rlm_live365_masters=NULL; + rlm_live365_aux1s=NULL; + rlm_live365_aux2s=NULL; + + sprintf(section,"Station%d",i++); + strncpy(password,RLMGetStringValue(ptr,arg,section,"Password",""),255); + password[255]=0; + if(strlen(password)==0) { + RLMLog(ptr,LOG_WARNING,"rlm_live365: no Live365 stations specified"); + return; + } + while(strlen(password)>0) { + rlm_live365_passwords=realloc(rlm_live365_passwords, + (rlm_live365_devs+1)*(rlm_live365_devs+1)*256); + strcpy(rlm_live365_passwords+256*rlm_live365_devs,password); + rlm_live365_stations=realloc(rlm_live365_stations,(rlm_live365_devs+1)*256); + strncpy(rlm_live365_stations+256*rlm_live365_devs, + RLMGetStringValue(ptr,arg,section,"MemberName",""),256); + + rlm_live365_titles=realloc(rlm_live365_titles,(rlm_live365_devs+1)*256); + strncpy(rlm_live365_titles+256*rlm_live365_devs, + RLMGetStringValue(ptr,arg,section,"TitleString",""),256); + + rlm_live365_artists=realloc(rlm_live365_artists,(rlm_live365_devs+1)*256); + strncpy(rlm_live365_artists+256*rlm_live365_devs, + RLMGetStringValue(ptr,arg,section,"ArtistString",""),256); + + rlm_live365_albums=realloc(rlm_live365_albums,(rlm_live365_devs+1)*256); + strncpy(rlm_live365_albums+256*rlm_live365_devs, + RLMGetStringValue(ptr,arg,section,"AlbumString",""),256); + + + rlm_live365_masters=realloc(rlm_live365_masters, + (rlm_live365_devs+1)*sizeof(int)); + rlm_live365_masters[rlm_live365_devs]= + rlm_live365_GetLogStatus(ptr,arg,section,"MasterLog"); + rlm_live365_aux1s=realloc(rlm_live365_aux1s, + (rlm_live365_devs+1)*sizeof(int)); + rlm_live365_aux1s[rlm_live365_devs]= + rlm_live365_GetLogStatus(ptr,arg,section,"Aux1Log"); + rlm_live365_aux2s=realloc(rlm_live365_aux2s, + (rlm_live365_devs+1)*sizeof(int)); + rlm_live365_aux2s[rlm_live365_devs]= + rlm_live365_GetLogStatus(ptr,arg,section,"Aux2Log"); + sprintf(errtext,"rlm_live365: configured station \"%s\"", + rlm_live365_stations+256*rlm_live365_devs); + rlm_live365_devs++; + RLMLog(ptr,LOG_INFO,errtext); + sprintf(section,"Station%d",i++); + strncpy(password,RLMGetStringValue(ptr,arg,section,"Password",""),255); + password[255]=0; + } +} + + +void rlm_live365_RLMFree(void *ptr) +{ + free(rlm_live365_stations); + free(rlm_live365_passwords); + free(rlm_live365_titles); + free(rlm_live365_artists); + free(rlm_live365_albums); + free(rlm_live365_masters); + free(rlm_live365_aux1s); + free(rlm_live365_aux2s); +} + + +void rlm_live365_RLMPadDataSent(void *ptr,const struct rlm_svc *svc, + const struct rlm_log *log, + const struct rlm_pad *now, + const struct rlm_pad *next) +{ + int i; + int flag=0; + char station[1024]; + char password[1024]; + char title[1024]; + char artist[1024]; + char album[1024]; + char url[8192]; + char msg[1500]; + + for(i=0;ilog_mach) { + case 0: + flag=rlm_live365_masters[i]; + break; + + case 1: + flag=rlm_live365_aux1s[i]; + break; + + case 2: + flag=rlm_live365_aux2s[i]; + break; + } + if((flag==1)||((flag==2)&&(log->log_onair!=0))) { + strncpy(station,RLMResolveNowNext(ptr,now,next, + rlm_live365_stations+256*i),256); + rlm_live365_EncodeString(station,1023); + + strncpy(password,RLMResolveNowNext(ptr,now,next, + rlm_live365_passwords+256*i),256); + rlm_live365_EncodeString(title,1023); + + strncpy(title,RLMResolveNowNext(ptr,now,next, + rlm_live365_titles+256*i),256); + rlm_live365_EncodeString(title,1023); + strncpy(artist,RLMResolveNowNext(ptr,now,next, + rlm_live365_artists+256*i),256); + rlm_live365_EncodeString(artist,1023); + strncpy(album,RLMResolveNowNext(ptr,now,next, + rlm_live365_albums+256*i),256); + rlm_live365_EncodeString(album,1023); + snprintf(url,8192,"http://www.live365.com/cgi-bin/add_song.cgi?member_name=%s&password=%s&version=2&filename=Rivendell&seconds=%u&title=%s&artist=%s&album=%s", + station, + password, + now->rlm_len/1000, + title, + artist, + album); + if(strlen(now->rlm_title)!=0) { + if(fork()==0) { + execlp("curl","curl","-o","/dev/null","-s",url,(char *)NULL); + RLMLog(ptr,LOG_WARNING,"rlm_live365: unable to execute curl(1)"); + exit(0); + } + } + snprintf(msg,1500,"rlm_live365: sending pad update: \"%s\"", + (const char *)url); + RLMLog(ptr,LOG_INFO,msg); + } + } +} diff --git a/utils/rdgpimon/rdgpimon.cpp b/utils/rdgpimon/rdgpimon.cpp index 92961654..4cd22bf1 100644 --- a/utils/rdgpimon/rdgpimon.cpp +++ b/utils/rdgpimon/rdgpimon.cpp @@ -2,9 +2,7 @@ // // A Qt-based application for testing General Purpose Input (GPI) devices. // -// (C) Copyright 2002-2003 Fred Gleason -// -// $Id: rdgpimon.cpp,v 1.14.6.4 2014/01/21 21:59:34 cvs Exp $ +// (C) Copyright 2002-2014 Fred Gleason // // 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 @@ -39,6 +37,9 @@ #include #include #include +#include +#include +#include // // Icons @@ -49,6 +50,8 @@ MainWidget::MainWidget(QWidget *parent,const char *name) :QWidget(parent,name) { + gpi_scroll_mode=false; + // // Read Command Options // @@ -64,13 +67,17 @@ MainWidget::MainWidget(QWidget *parent,const char *name) setMaximumHeight(sizeHint().height()); // - // Create Font + // Create Fonts // QFont font("helvetica",10,QFont::Normal); font.setPixelSize(10); setFont(font); + QFont list_font("helvetica",12,QFont::Normal); + list_font.setPixelSize(12); QFont main_font("helvetica",12,QFont::Bold); main_font.setPixelSize(12); + QFont title_font("helvetica",14,QFont::Bold); + title_font.setPixelSize(14); // // Create And Set Icon @@ -138,12 +145,11 @@ MainWidget::MainWidget(QWidget *parent,const char *name) // // Type Selector // - gpi_type_box=new QComboBox(this,"gpi_type_box"); + gpi_type_box=new QComboBox(this); gpi_type_box->setGeometry(80,10,120,21); gpi_type_box->insertItem(tr("GPI (Inputs)")); gpi_type_box->insertItem(tr("GPO (Outputs)")); - QLabel *label= - new QLabel(gpi_type_box,tr("Show:"),this,"gpi_type_label"); + QLabel *label=new QLabel(gpi_type_box,tr("Show:"),this); label->setGeometry(20,10,55,21); label->setFont(main_font); label->setAlignment(AlignRight|AlignVCenter); @@ -153,12 +159,12 @@ MainWidget::MainWidget(QWidget *parent,const char *name) // // Matrix Selector // - gpi_matrix_box=new QComboBox(this,"gpi_matrix_box"); + gpi_matrix_box=new QComboBox(this); gpi_matrix_box->setGeometry(280,10,80,21); for(int i=0;iinsertItem(QString().sprintf("%d",i)); } - label=new QLabel(gpi_matrix_box,tr("Matrix:"),this,"gpi_matrix_label"); + label=new QLabel(gpi_matrix_box,tr("Matrix:"),this); label->setGeometry(220,10,55,21); label->setFont(main_font); label->setAlignment(AlignRight|AlignVCenter); @@ -183,23 +189,23 @@ MainWidget::MainWidget(QWidget *parent,const char *name) // Up Button // gpi_up_button= - new RDTransportButton(RDTransportButton::Up,this,"gpi_up_button"); - gpi_up_button->setGeometry(10,sizeHint().height()-60,80,50); + new RDTransportButton(RDTransportButton::Up,this); + gpi_up_button->setGeometry(10,360,80,50); connect(gpi_up_button,SIGNAL(clicked()),this,SLOT(upData())); // // Down Button // gpi_down_button= - new RDTransportButton(RDTransportButton::Down,this,"gpi_down_button"); - gpi_down_button->setGeometry(100,sizeHint().height()-60,80,50); + new RDTransportButton(RDTransportButton::Down,this); + gpi_down_button->setGeometry(100,360,80,50); connect(gpi_down_button,SIGNAL(clicked()),this,SLOT(downData())); // // Color Key // label=new QLabel(tr("Green = ON Cart"),this); - label->setGeometry(200,sizeHint().height()-50,300,12); + label->setGeometry(200,370,300,12); label->setFont(main_font); label->setAlignment(AlignLeft|AlignVCenter); QPalette p=palette(); @@ -209,7 +215,7 @@ MainWidget::MainWidget(QWidget *parent,const char *name) label->setPalette(p); label=new QLabel(tr("Red = OFF Cart"),this); - label->setGeometry(200,sizeHint().height()-32,300,12); + label->setGeometry(200,392,300,12); label->setFont(main_font); label->setAlignment(AlignLeft|AlignVCenter); p.setColor(QPalette::Active,QColorGroup::Foreground,darkRed); @@ -217,23 +223,84 @@ MainWidget::MainWidget(QWidget *parent,const char *name) p.setColor(QPalette::Disabled,QColorGroup::Foreground,darkRed); label->setPalette(p); + // + // Events Log + // + label=new QLabel(tr("Events Log"),this); + label->setFont(title_font); + label->setAlignment(Qt::AlignCenter); + label->setGeometry(110,423,sizeHint().width()-220,30); - // - // Close Button - // - gpi_close_button=new QPushButton(this,"gpi_close_button"); - gpi_close_button->setGeometry(sizeHint().width()-90,sizeHint().height()-60, - 80,50); - gpi_close_button->setFont(main_font); - gpi_close_button->setText(tr("&Close")); - connect(gpi_close_button,SIGNAL(clicked()),this,SLOT(quitMainWidget())); + gpi_events_date_edit=new QDateEdit(this); + gpi_events_date_edit->setGeometry(155,453,90,20); + gpi_events_date_edit->setDate(QDate::currentDate()); + connect(gpi_events_date_edit,SIGNAL(valueChanged(const QDate &)), + this,SLOT(eventsDateChangedData(const QDate &))); + gpi_events_date_label=new QLabel(gpi_events_date_edit,tr("Date")+":",this); + gpi_events_date_label->setGeometry(100,453,50,20); + gpi_events_date_label->setFont(main_font); + gpi_events_date_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter); + + gpi_events_state_box=new QComboBox(this); + gpi_events_state_box->setGeometry(280,453,55,20); + gpi_events_state_box->insertItem(tr("On")); + gpi_events_state_box->insertItem(tr("Off")); + gpi_events_state_box->insertItem(tr("Both")); + connect(gpi_events_state_box,SIGNAL(activated(int)), + this,SLOT(eventsStateChangedData(int))); + gpi_events_state_label=new QLabel(gpi_events_state_box,tr("State")+":",this); + gpi_events_state_label->setGeometry(225,453,50,20); + gpi_events_state_label->setFont(main_font); + gpi_events_state_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter); + + gpi_events_list=new RDListView(this); + gpi_events_list->setFont(main_font); + gpi_events_list->setGeometry(110,480,sizeHint().width()-220,230); + gpi_events_list->setItemMargin(5); + gpi_events_list->setSelectionMode(QListView::NoSelection); + + gpi_events_list->addColumn("Time"); + gpi_events_list->setColumnAlignment(0,Qt::AlignHCenter); + gpi_events_list->setColumnSortType(1,RDListView::TimeSort); + + gpi_events_list->addColumn(tr("Line")); + gpi_events_list->setColumnAlignment(1,Qt::AlignHCenter); + gpi_events_list->setColumnSortType(1,RDListView::GpioSort); + + gpi_events_list->addColumn(tr("State")); + gpi_events_list->setColumnAlignment(2,Qt::AlignHCenter); + + gpi_events_scroll_button=new QPushButton(tr("Scroll"),this); + gpi_events_scroll_button->setGeometry(sizeHint().width()-100,510,80,50); + gpi_events_scroll_button->setFont(main_font); + connect(gpi_events_scroll_button,SIGNAL(clicked()), + this,SLOT(eventsScrollData())); + gpi_scroll_color=palette(); + gpi_scroll_color.setColor(QPalette::Active,QColorGroup::ButtonText, + Qt::white); + gpi_scroll_color.setColor(QPalette::Active,QColorGroup::Button, + Qt::blue); + gpi_scroll_color.setColor(QPalette::Active,QColorGroup::Background, + lightGray); + gpi_scroll_color.setColor(QPalette::Inactive,QColorGroup::ButtonText, + Qt::white); + gpi_scroll_color.setColor(QPalette::Inactive,QColorGroup::Button, + Qt::blue); + gpi_scroll_color.setColor(QPalette::Inactive,QColorGroup::Background, + lightGray); + + gpi_events_report_button=new QPushButton(tr("Report"),this); + gpi_events_report_button->setGeometry(sizeHint().width()-100,570,80,50); + gpi_events_report_button->setFont(main_font); + connect(gpi_events_report_button,SIGNAL(clicked()), + this,SLOT(eventsReportData())); // // Start Up Timer // - QTimer *timer=new QTimer(this,"start_up_timer"); - connect(timer,SIGNAL(timeout()),this,SLOT(startUpData())); - timer->start(GPIMON_START_UP_DELAY,true); + gpi_events_startup_timer=new QTimer(this); + connect(gpi_events_startup_timer,SIGNAL(timeout()),this,SLOT(startUpData())); + gpi_events_startup_timer->start(GPIMON_START_UP_DELAY,true); } @@ -244,7 +311,7 @@ MainWidget::~MainWidget() QSize MainWidget::sizeHint() const { - return QSize(528,78*GPIMON_ROWS+110); + return QSize(528,78*GPIMON_ROWS+410); } @@ -290,6 +357,88 @@ void MainWidget::matrixActivatedData(int index) gpi_ripc->sendGpoCart(gpi_matrix_box->currentItem()); break; } + RefreshEventsList(); + gpi_events_startup_timer->start(1000,true); +} + + +void MainWidget::eventsDateChangedData(const QDate &date) +{ + RefreshEventsList(); +} + + +void MainWidget::eventsStateChangedData(int n) +{ + RefreshEventsList(); +} + + +void MainWidget::eventsScrollData() +{ + if(gpi_scroll_mode) { + gpi_events_scroll_button->setPalette(palette()); + gpi_scroll_mode=false; + } + else { + gpi_events_scroll_button->setPalette(gpi_scroll_color); + gpi_scroll_mode=true; + RDListViewItem *item=(RDListViewItem *)gpi_events_list->firstChild(); + RDListViewItem *last=NULL; + while(item!=NULL) { + last=item; + item=(RDListViewItem *)item->nextSibling(); + } + if(last!=NULL) { + gpi_events_list->ensureItemVisible(last); + } + } +} + + +void MainWidget::eventsReportData() +{ + QString report; + QString sql; + RDSqlQuery *q; + + report=" Rivendell GPIO Event Report\n"; + report+=" Date: "+gpi_events_date_edit->date().toString("MM/dd/yyyy")+ + " Station/Matrix: "+gpi_station->name()+":"+ + QString().sprintf("%d ",gpi_matrix_box->currentItem())+ + " State Filter: "+gpi_events_state_box->currentText()+"\n"; + report+="\n"; + + sql=QString("select EVENT_DATETIME,NUMBER,EDGE from GPIO_EVENTS where ")+ + "(STATION_NAME=\""+RDEscapeString(gpi_station->name())+"\")&&"+ + QString().sprintf("(MATRIX=%d)&&",gpi_matrix_box->currentItem())+ + QString().sprintf("(TYPE=%d)&&",gpi_type_box->currentItem())+ + "(EVENT_DATETIME>=\""+gpi_events_date_edit->date().toString("yyyy-MM-dd")+ + " 00:00:00\")&&"+ + "(EVENT_DATETIME<\""+gpi_events_date_edit->date().addDays(1). + toString("yyyy-MM-dd")+" 00:00:00\")"; + if(gpi_events_state_box->currentItem()==0) { + sql+="&&(EDGE=1)"; + } + if(gpi_events_state_box->currentItem()==1) { + sql+="&&(EDGE=0)"; + } + report+=" -- Time -- - Line - - State -\n"; + q=new RDSqlQuery(sql); + while(q->next()) { + report+=" "; + report+=q->value(0).toDateTime().toString("hh:mm:ss")+" "; + report+=QString().sprintf(" %5d ",q->value(1).toInt()); + if(q->value(2).toInt()==0) { + report+=tr("OFF"); + } + else { + report+=tr("ON "); + } + report+="\n"; + } + delete q; + RDTextFile(report); } @@ -308,6 +457,7 @@ void MainWidget::gpiStateChangedData(int matrix,int line,bool state) gpi_labels[i]->setState(state); } } + AddEventsItem(line,state); } @@ -326,6 +476,7 @@ void MainWidget::gpoStateChangedData(int matrix,int line,bool state) gpi_labels[i]->setState(state); } } + AddEventsItem(line,state); } @@ -412,6 +563,7 @@ void MainWidget::gpoCartChangedData(int matrix,int line,int off_cartnum, void MainWidget::startUpData() { + gpi_events_startup_timer->disconnect(); matrixActivatedData(0); } @@ -529,6 +681,76 @@ void MainWidget::UpdateLabelsDown(int first_line) } +void MainWidget::RefreshEventsList() +{ + QString sql; + RDSqlQuery *q; + + sql=QString("select EVENT_DATETIME,NUMBER,EDGE from GPIO_EVENTS where ")+ + "(STATION_NAME=\""+RDEscapeString(gpi_station->name())+"\")&&"+ + QString().sprintf("(MATRIX=%d)&&",gpi_matrix_box->currentItem())+ + QString().sprintf("(TYPE=%d)&&",gpi_type_box->currentItem())+ + "(EVENT_DATETIME>=\""+gpi_events_date_edit->date().toString("yyyy-MM-dd")+ + " 00:00:00\")&&"+ + "(EVENT_DATETIME<\""+gpi_events_date_edit->date().addDays(1). + toString("yyyy-MM-dd")+" 00:00:00\")"; + if(gpi_events_state_box->currentItem()==0) { + sql+="&&(EDGE=1)"; + } + if(gpi_events_state_box->currentItem()==1) { + sql+="&&(EDGE=0)"; + } + q=new RDSqlQuery(sql); + gpi_events_list->clear(); + RDListViewItem *item=NULL; + while(q->next()) { + item=new RDListViewItem(gpi_events_list); + item->setText(0,q->value(0).toDateTime().toString("hh:mm:ss")); + item->setText(1,QString().sprintf("%d",q->value(1).toInt())); + if(q->value(2).toInt()==0) { + item->setText(2,tr("Off")); + item->setTextColor(Qt::darkRed); + } + else { + item->setText(2,tr("On")); + item->setTextColor(Qt::darkGreen); + } + } + if(gpi_scroll_mode&&(item!=NULL)) { + gpi_events_list->ensureItemVisible(item); + } + delete q; +} + + +void MainWidget::AddEventsItem(int line,bool state) +{ + if(gpi_events_startup_timer->isActive()) { + return; + } + if((gpi_events_state_box->currentItem()==0)&&(!state)) { + return; + } + if((gpi_events_state_box->currentItem()==1)&&state) { + return; + } + RDListViewItem *item=new RDListViewItem(gpi_events_list); + item->setText(0,QTime::currentTime().toString("hh:mm:ss")); + item->setText(1,QString().sprintf("%d",line+1)); + if(state) { + item->setText(2,tr("On")); + item->setTextColor(Qt::darkGreen); + } + else { + item->setText(2,tr("Off")); + item->setTextColor(Qt::darkRed); + } + if(gpi_scroll_mode) { + gpi_events_list->ensureItemVisible(item); + } +} + + int main(int argc,char *argv[]) { QApplication a(argc,argv); diff --git a/utils/rdgpimon/rdgpimon.h b/utils/rdgpimon/rdgpimon.h index db8df5d9..9ea89ab9 100644 --- a/utils/rdgpimon/rdgpimon.h +++ b/utils/rdgpimon/rdgpimon.h @@ -35,7 +35,10 @@ #include #include #include +#include +#include +#include #include #include #include @@ -62,6 +65,10 @@ class MainWidget : public QWidget void userData(); void typeActivatedData(int index); void matrixActivatedData(int index); + void eventsDateChangedData(const QDate &date); + void eventsStateChangedData(int n); + void eventsScrollData(); + void eventsReportData(); void gpiStateChangedData(int matrix,int line,bool state); void gpoStateChangedData(int matrix,int line,bool state); void gpiMaskChangedData(int matrix,int line,bool state); @@ -76,6 +83,8 @@ class MainWidget : public QWidget private: void UpdateLabelsUp(int last_line); void UpdateLabelsDown(int first_line); + void RefreshEventsList(); + void AddEventsItem(int line,bool state); RDConfig *gpi_config; QSqlDatabase *gpi_db; RDRipc *gpi_ripc; @@ -83,14 +92,23 @@ class MainWidget : public QWidget RDMatrix *gpi_matrix; QComboBox *gpi_type_box; QComboBox *gpi_matrix_box; - QPushButton *gpi_close_button; QPixmap *gpi_rivendell_map; GpiLabel *gpi_labels[GPIMON_ROWS*GPIMON_COLS]; RDTransportButton *gpi_up_button; RDTransportButton *gpi_down_button; int gpi_first_line; int gpi_last_line; + QLabel *gpi_events_date_label; + QDateEdit *gpi_events_date_edit; + QLabel *gpi_events_state_label; + QComboBox *gpi_events_state_box; + QPushButton *gpi_events_scroll_button; + RDListView *gpi_events_list; + QTimer *gpi_events_startup_timer; + bool gpi_scroll_mode; + QPalette gpi_scroll_color; + QPushButton *gpi_events_report_button; }; -#endif +#endif // MAIN_WIDGET_H diff --git a/utils/rdgpimon/rdgpimon_cs.ts b/utils/rdgpimon/rdgpimon_cs.ts index 5d7d675b..dfb25e5e 100644 --- a/utils/rdgpimon/rdgpimon_cs.ts +++ b/utils/rdgpimon/rdgpimon_cs.ts @@ -43,11 +43,51 @@ - &Close + User - User + Line + + + + State + + + + Date + + + + Both + + + + On + + + + Off + + + + Scroll + + + + Events Log + + + + Report + + + + ON + + + + OFF diff --git a/utils/rdgpimon/rdgpimon_de.ts b/utils/rdgpimon/rdgpimon_de.ts index 51e7d49f..f144dd8f 100644 --- a/utils/rdgpimon/rdgpimon_de.ts +++ b/utils/rdgpimon/rdgpimon_de.ts @@ -24,7 +24,7 @@ &Close - S&chließen + S&chließen RDGpiMon - User: @@ -54,5 +54,49 @@ User + + Line + + + + State + + + + Date + + + + Both + + + + On + + + + Off + + + + Scroll + + + + Events Log + + + + Report + + + + ON + + + + OFF + + diff --git a/utils/rdgpimon/rdgpimon_es.ts b/utils/rdgpimon/rdgpimon_es.ts index b45b1d75..9c6f5c64 100644 --- a/utils/rdgpimon/rdgpimon_es.ts +++ b/utils/rdgpimon/rdgpimon_es.ts @@ -24,7 +24,7 @@ &Close - &Cerrar + &Cerrar RDGpiMon - User: @@ -54,5 +54,49 @@ User + + Line + + + + State + + + + Date + + + + Both + + + + On + + + + Off + + + + Scroll + + + + Events Log + + + + Report + + + + ON + + + + OFF + + diff --git a/utils/rdgpimon/rdgpimon_fr.ts b/utils/rdgpimon/rdgpimon_fr.ts index 9e0f922d..89b82be9 100644 --- a/utils/rdgpimon/rdgpimon_fr.ts +++ b/utils/rdgpimon/rdgpimon_fr.ts @@ -22,10 +22,6 @@ Matrix: - - &Close - - Show: @@ -50,5 +46,49 @@ User + + Line + + + + State + + + + Date + + + + Both + + + + On + + + + Off + + + + Scroll + + + + Events Log + + + + Report + + + + ON + + + + OFF + + diff --git a/utils/rdgpimon/rdgpimon_nb.ts b/utils/rdgpimon/rdgpimon_nb.ts index e59f1ac3..7df4dedb 100644 --- a/utils/rdgpimon/rdgpimon_nb.ts +++ b/utils/rdgpimon/rdgpimon_nb.ts @@ -24,7 +24,7 @@ &Close - &Lukk + &Lukk RDGpiMon - User: @@ -54,5 +54,49 @@ User + + Line + + + + State + + + + Date + + + + Both + + + + On + + + + Off + + + + Scroll + + + + Events Log + + + + Report + + + + ON + + + + OFF + + diff --git a/utils/rdgpimon/rdgpimon_nn.ts b/utils/rdgpimon/rdgpimon_nn.ts index e59f1ac3..7df4dedb 100644 --- a/utils/rdgpimon/rdgpimon_nn.ts +++ b/utils/rdgpimon/rdgpimon_nn.ts @@ -24,7 +24,7 @@ &Close - &Lukk + &Lukk RDGpiMon - User: @@ -54,5 +54,49 @@ User + + Line + + + + State + + + + Date + + + + Both + + + + On + + + + Off + + + + Scroll + + + + Events Log + + + + Report + + + + ON + + + + OFF + + diff --git a/utils/rdgpimon/rdgpimon_pt_BR.ts b/utils/rdgpimon/rdgpimon_pt_BR.ts index 5d7d675b..dfb25e5e 100644 --- a/utils/rdgpimon/rdgpimon_pt_BR.ts +++ b/utils/rdgpimon/rdgpimon_pt_BR.ts @@ -43,11 +43,51 @@ - &Close + User - User + Line + + + + State + + + + Date + + + + Both + + + + On + + + + Off + + + + Scroll + + + + Events Log + + + + Report + + + + ON + + + + OFF diff --git a/utils/rdhpiinfo/Makefile.am b/utils/rdhpiinfo/Makefile.am index 3925d9f4..e2139870 100644 --- a/utils/rdhpiinfo/Makefile.am +++ b/utils/rdhpiinfo/Makefile.am @@ -33,10 +33,12 @@ moc_%.cpp: %.h bin_PROGRAMS = rdhpiinfo dist_rdhpiinfo_SOURCES = change_mode.cpp change_mode.h\ - rdhpiinfo.cpp rdhpiinfo.h + rdhpiinfo.cpp rdhpiinfo.h\ + virtdetails.cpp virtdetails.h nodist_rdhpiinfo_SOURCES = moc_change_mode.cpp\ - moc_rdhpiinfo.cpp + moc_rdhpiinfo.cpp\ + moc_virtdetails.cpp rdhpiinfo_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ @LIBHPI@ diff --git a/utils/rdhpiinfo/change_mode.cpp b/utils/rdhpiinfo/change_mode.cpp index a62b92b6..68148248 100644 --- a/utils/rdhpiinfo/change_mode.cpp +++ b/utils/rdhpiinfo/change_mode.cpp @@ -2,9 +2,7 @@ // // Change the mode of an AudioScience Adapter. // -// (C) Copyright 2002-2005 Fred Gleason -// -// $Id: change_mode.cpp,v 1.6 2011/05/18 14:38:13 cvs Exp $ +// (C) Copyright 2002-2014 Fred Gleason // // 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 @@ -40,7 +38,7 @@ ChangeMode::ChangeMode(unsigned short card,unsigned short type,int mode, setMinimumHeight(sizeHint().height()); setMaximumHeight(sizeHint().height()); - setCaption(tr("RdhpiInfo - Change Mode")); + setCaption(tr("RdHPIInfo - Change Mode")); // // Create Fonts @@ -53,8 +51,7 @@ ChangeMode::ChangeMode(unsigned short card,unsigned short type,int mode, // // Adapter Type // - QLabel *label=new QLabel(QString().sprintf("AudioScience %X",type), - this,"type_label"); + QLabel *label=new QLabel(QString().sprintf("AudioScience %X",type),this); label->setGeometry(10,10,sizeHint().width()-20,15); label->setFont(label_font); label->setAlignment(AlignCenter); @@ -62,11 +59,11 @@ ChangeMode::ChangeMode(unsigned short card,unsigned short type,int mode, // // Adapter Mode // - change_mode_box=new QComboBox(this,"change_type_box"); + change_mode_box=new QComboBox(this); change_mode_box->setGeometry(10,35,sizeHint().width()-20,22); change_mode_box->setFont(font); int index=0; - for(uint32_t i=1;i<11;i++) { + for(uint32_t i=1;i<14;i++) { if(HPI_AdapterSetModeEx(NULL,card,i,HPI_ADAPTER_MODE_QUERY)==0) { switch(i) { case HPI_ADAPTER_MODE_4OSTREAM: @@ -86,16 +83,7 @@ ChangeMode::ChangeMode(unsigned short card,unsigned short type,int mode, break; case HPI_ADAPTER_MODE_16OSTREAM: - switch(type) { - case 0x6585: - change_mode_box-> - insertItem(tr("Multichannel Surround (Two Output Streams)")); - break; - - default: - change_mode_box->insertItem(tr("Sixteen Output Streams")); - break; - } + change_mode_box->insertItem(tr("Sixteen Output Streams")); break; case HPI_ADAPTER_MODE_1OSTREAM: @@ -118,6 +106,18 @@ ChangeMode::ChangeMode(unsigned short card,unsigned short type,int mode, change_mode_box->insertItem(tr("Surround Sound [SSX]")); break; + case HPI_ADAPTER_MODE_9OSTREAM: + change_mode_box->insertItem(tr("Nine Output Stream")); + break; + + case HPI_ADAPTER_MODE_MONO: + change_mode_box->insertItem(tr("Mono Mode")); + break; + + case HPI_ADAPTER_MODE_LOW_LATENCY: + change_mode_box->insertItem(tr("Low Latency Mode")); + break; + default: str=QString(tr("Unknown")); change_mode_box-> @@ -137,7 +137,7 @@ ChangeMode::ChangeMode(unsigned short card,unsigned short type,int mode, // // Ok Button // - QPushButton *ok_button=new QPushButton(this,"ok_button"); + QPushButton *ok_button=new QPushButton(this); ok_button->setGeometry(sizeHint().width()-140,sizeHint().height()-40,60,30); ok_button->setDefault(true); ok_button->setFont(font); diff --git a/utils/rdhpiinfo/rdhpiinfo.cpp b/utils/rdhpiinfo/rdhpiinfo.cpp index 86b90a27..d3963c67 100644 --- a/utils/rdhpiinfo/rdhpiinfo.cpp +++ b/utils/rdhpiinfo/rdhpiinfo.cpp @@ -2,9 +2,7 @@ // // A Qt-based application for display information on ASI cards. // -// (C) Copyright 2002-2005 Fred Gleason -// -// $Id: rdhpiinfo.cpp,v 1.8.6.4 2014/01/21 21:59:34 cvs Exp $ +// (C) Copyright 2002-2014 Fred Gleason // // 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 @@ -32,8 +30,9 @@ #include -#include -#include +#include "rdhpiinfo.h" +#include "change_mode.h" +#include "virtdetails.h" MainWidget::MainWidget(QWidget *parent,const char *name) :QWidget(parent,name) @@ -67,7 +66,6 @@ MainWidget::MainWidget(QWidget *parent,const char *name) // Open HPI // if(HPI_SubSysCreate()==NULL) { - printf("HERE\n"); QMessageBox::warning(this,tr("HPI Error"), tr("The ASI HPI Driver is not loaded!")); exit(1); @@ -77,25 +75,23 @@ MainWidget::MainWidget(QWidget *parent,const char *name) // HPI Version // HpiErr(HPI_SubSysGetVersionEx(NULL,&hpi_version),"HPI_SubSysGetVersionEx"); - QLabel *label=new QLabel(tr("HPI Version:"),this,"hpi_version_label"); + QLabel *label=new QLabel(tr("HPI Version:"),this); label->setGeometry(10,10,85,20); label->setFont(label_font); - label=new QLabel(QString().sprintf("%X.%02X.%02X", + label=new QLabel(QString().sprintf("%d.%02d.%02d", (unsigned)((hpi_version>>16)&0xffff), (unsigned)((hpi_version>>8)&0xff), - (unsigned)hpi_version&0xff), - this,"hpi_version"); + (unsigned)hpi_version&0xff),this); label->setGeometry(100,10,100,20); label->setFont(font); // // Adapter Name // - info_name_box=new QComboBox(this,"info_name_box"); + info_name_box=new QComboBox(this); info_name_box->setGeometry(100,34,sizeHint().width()-110,20); info_name_box->setFont(font); - info_name_label=new QLabel(info_name_box,tr("Adapter:"), - this,"info_name_label"); + info_name_label=new QLabel(info_name_box,tr("Adapter:"),this); info_name_label->setGeometry(10,34,85,20); info_name_label->setFont(label_font); info_name_label->setAlignment(AlignRight|AlignVCenter); @@ -105,11 +101,11 @@ MainWidget::MainWidget(QWidget *parent,const char *name) // // Adapter Index // - label=new QLabel(tr("Adapter Index:"),this,"index_number_label"); + label=new QLabel(tr("Adapter Index:"),this); label->setGeometry(10,58,105,20); label->setFont(label_font); label->setAlignment(AlignRight|AlignVCenter); - info_index_label=new QLabel(this,"info_index_label"); + info_index_label=new QLabel(this); info_index_label->setGeometry(120,58,100,20); info_index_label->setFont(font); info_index_label->setAlignment(AlignLeft|AlignVCenter); @@ -117,11 +113,11 @@ MainWidget::MainWidget(QWidget *parent,const char *name) // // Serial Number // - label=new QLabel(tr("Serial Number:"),this,"serial_number_label"); + label=new QLabel(tr("Serial Number:"),this); label->setGeometry(10,78,105,20); label->setFont(label_font); label->setAlignment(AlignRight|AlignVCenter); - info_serial_label=new QLabel(this,"info_serial_label"); + info_serial_label=new QLabel(this); info_serial_label->setGeometry(120,78,100,20); info_serial_label->setFont(font); info_serial_label->setAlignment(AlignLeft|AlignVCenter); @@ -129,11 +125,11 @@ MainWidget::MainWidget(QWidget *parent,const char *name) // // Output Streams // - label=new QLabel(tr("Input Streams:"),this,"input_streams_label"); + label=new QLabel(tr("Input Streams:"),this); label->setGeometry(10,98,105,20); label->setFont(label_font); label->setAlignment(AlignRight|AlignVCenter); - info_istreams_label=new QLabel(this,"info_istreams_label"); + info_istreams_label=new QLabel(this); info_istreams_label->setGeometry(120,98,100,20); info_istreams_label->setFont(font); info_istreams_label->setAlignment(AlignLeft|AlignVCenter); @@ -141,11 +137,11 @@ MainWidget::MainWidget(QWidget *parent,const char *name) // // Input Streams // - label=new QLabel(tr("Output Streams:"),this,"output_streams_label"); + label=new QLabel(tr("Output Streams:"),this); label->setGeometry(10,118,105,20); label->setFont(label_font); label->setAlignment(AlignRight|AlignVCenter); - info_ostreams_label=new QLabel(this,"info_ostreams_label"); + info_ostreams_label=new QLabel(this); info_ostreams_label->setGeometry(120,118,100,20); info_ostreams_label->setFont(font); info_ostreams_label->setAlignment(AlignLeft|AlignVCenter); @@ -153,11 +149,11 @@ MainWidget::MainWidget(QWidget *parent,const char *name) // // DSP Version // - label=new QLabel(tr("DSP Version:"),this,"dsp_version_label"); + label=new QLabel(tr("DSP Version:"),this); label->setGeometry(10,138,105,20); label->setFont(label_font); label->setAlignment(AlignRight|AlignVCenter); - info_dsp_label=new QLabel(this,"info_dsp_label"); + info_dsp_label=new QLabel(this); info_dsp_label->setGeometry(120,138,100,20); info_dsp_label->setFont(font); info_dsp_label->setAlignment(AlignLeft|AlignVCenter); @@ -165,48 +161,71 @@ MainWidget::MainWidget(QWidget *parent,const char *name) // // Adapter Version // - label=new QLabel(tr("Adapter Version:"),this,"adapter_version_label"); + label=new QLabel(tr("Adapter Version:"),this); label->setGeometry(10,158,105,20); label->setFont(label_font); label->setAlignment(AlignRight|AlignVCenter); - info_adapter_label=new QLabel(this,"info_adapter_label"); + info_adapter_label=new QLabel(this); info_adapter_label->setGeometry(120,158,100,20); info_adapter_label->setFont(font); info_adapter_label->setAlignment(AlignLeft|AlignVCenter); // - // Adapter Mode + // DSP Utilization // - label=new QLabel(tr("Adapter Mode:"),this,"adapter_mode_label"); - label->setGeometry(10,178,105,20); - label->setFont(label_font); - label->setAlignment(AlignRight|AlignVCenter); - info_mode_label=new QLabel(this,"info_mode_label"); - info_mode_label->setGeometry(120,178,sizeHint().width()-130,20); - info_mode_label->setFont(font); - info_mode_label->setAlignment(AlignLeft|AlignVCenter); + info_utilization_label=new QLabel(tr("DSP Utilization")+":",this); + info_utilization_label->setGeometry(10,183,105,20); + info_utilization_label->setFont(label_font); + info_utilization_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter); + info_utilization_label->setDisabled(true); + info_utilization_edit=new QLineEdit(this); + info_utilization_edit->setGeometry(120,183,60,20); + info_utilization_edit->setFont(font); + info_utilization_edit->setReadOnly(true); + info_utilization_edit->setDisabled(true); + info_utilization_button=new QPushButton(tr("Details"),this); + info_utilization_button->setGeometry(190,180,70,26); + info_utilization_button->setFont(font); + info_utilization_button->setDisabled(true); + connect(info_utilization_button,SIGNAL(clicked()), + this,SLOT(utilizationData())); // - // Change Mode Button + // Adapter Mode // + label=new QLabel(tr("Adapter Mode:"),this); + label->setGeometry(10,213,105,20); + label->setFont(label_font); + label->setAlignment(AlignRight|AlignVCenter); + info_mode_edit=new QLineEdit(this); + info_mode_edit->setGeometry(120,213,sizeHint().width()-210,20); + info_mode_edit->setReadOnly(true); + info_mode_edit->setFont(font); + info_mode_edit->setAlignment(AlignLeft|AlignVCenter); info_changemode_button= - new QPushButton(tr("Change Card Mode"),this,"info_changemode_button"); - info_changemode_button->setGeometry(130,200,170,30); - info_changemode_button->setFont(label_font); + new QPushButton(tr("Change"),this); + info_changemode_button->setGeometry(sizeHint().width()-80,210,70,26); + info_changemode_button->setFont(font); connect(info_changemode_button,SIGNAL(clicked()), this,SLOT(changeModeData())); // // Close Button // - QPushButton *button=new QPushButton(tr("Close"),this,"close_button"); + QPushButton *button=new QPushButton(tr("Close"),this); button->setGeometry(sizeHint().width()-60,sizeHint().height()-40,50,30); button->setFont(label_font); connect(button,SIGNAL(clicked()),qApp,SLOT(quit())); LoadAdapters(); + + hpi_profile_timer=new QTimer(this); + connect(hpi_profile_timer,SIGNAL(timeout()), + this,SLOT(updateDspUtilization())); + if(info_name_box->count()>0) { nameActivatedData(0); + hpi_profile_timer->start(1000); } } @@ -219,7 +238,7 @@ MainWidget::~MainWidget() QSize MainWidget::sizeHint() const { - return QSize(400,250); + return QSize(400,290); } @@ -250,71 +269,77 @@ void MainWidget::nameActivatedData(int id) hpi_card_version[card]&7)); switch(hpi_mode[card]) { case 0: // No mode support - info_mode_label->setText(tr("Standard")); + info_mode_edit->setText(tr("Standard")); info_changemode_button->setDisabled(true); break; case HPI_ADAPTER_MODE_4OSTREAM: - info_mode_label->setText(tr("Four Output Streams")); + info_mode_edit->setText(tr("Four Output Streams")); info_changemode_button->setEnabled(true); break; case HPI_ADAPTER_MODE_6OSTREAM: - info_mode_label->setText(tr("Six Output Streams")); + info_mode_edit->setText(tr("Six Output Streams")); info_changemode_button->setEnabled(true); break; case HPI_ADAPTER_MODE_8OSTREAM: - info_mode_label->setText(tr("Eight Output Streams")); + info_mode_edit->setText(tr("Eight Output Streams")); info_changemode_button->setEnabled(true); break; case HPI_ADAPTER_MODE_12OSTREAM: - info_mode_label->setText(tr("Twelve Output Streams")); + info_mode_edit->setText(tr("Twelve Output Streams")); info_changemode_button->setEnabled(true); break; case HPI_ADAPTER_MODE_16OSTREAM: - switch(hpi_type[card]) { - case 0x6585: - info_mode_label-> - setText(tr("Multichannel Surround (Two Output Streams)")); - break; - - default: - info_mode_label->setText(tr("Sixteen Output Streams")); - break; - } + info_mode_edit->setText(tr("Sixteen Output Streams")); info_changemode_button->setEnabled(true); break; case HPI_ADAPTER_MODE_1OSTREAM: - info_mode_label->setText(tr("One Output Stream")); + info_mode_edit->setText(tr("One Output Stream")); info_changemode_button->setEnabled(true); break; case HPI_ADAPTER_MODE_1: - info_mode_label->setText(tr("Mode 1")); + info_mode_edit->setText(tr("Mode 1")); info_changemode_button->setEnabled(true); break; case HPI_ADAPTER_MODE_2: - info_mode_label->setText(tr("Mode 2")); + info_mode_edit->setText(tr("Mode 2")); info_changemode_button->setEnabled(true); break; case HPI_ADAPTER_MODE_3: - info_mode_label->setText(tr("Mode 3")); + info_mode_edit->setText(tr("Mode 3")); info_changemode_button->setEnabled(true); break; case HPI_ADAPTER_MODE_MULTICHANNEL: - info_mode_label->setText(tr("Surround Sound [SSX]")); + info_mode_edit->setText(tr("Surround Sound [SSX]")); info_changemode_button->setEnabled(true); break; + case HPI_ADAPTER_MODE_9OSTREAM: + info_mode_edit->setText(tr("Nine Output Stream")); + info_changemode_button->setEnabled(true); + break; + + case HPI_ADAPTER_MODE_MONO: + info_mode_edit->setText(tr("Mono Mode")); + info_changemode_button->setEnabled(true); + break; + + case HPI_ADAPTER_MODE_LOW_LATENCY: + info_mode_edit->setText(tr("Low Latency Mode")); + info_changemode_button->setEnabled(true); + break; + default: - info_mode_label->setText(tr("N/A")); + info_mode_edit->setText(tr("N/A")); info_changemode_button->setDisabled(true); if(hpi_mode[card]!=hpi_serial[card]) { str=QString(tr("rdhpiinfo: unknown adapter mode")); @@ -355,6 +380,41 @@ void MainWidget::changeModeData() } +void MainWidget::utilizationData() +{ + VirtDetails *d=new VirtDetails(hpi_indexes[info_name_box->currentItem()], + hpi_profile[info_name_box->currentItem()], + hpi_profile_quan[info_name_box->currentItem()], + this); + hpi_profile_timer->stop(); + d->exec(); + hpi_profile_timer->start(1000); + delete d; +} + + +void MainWidget::updateDspUtilization() +{ + uint32_t util=0; + + if(HpiErr(HPI_ProfileGetUtilization(NULL, + hpi_profile[info_name_box->currentItem()], + &util))==0) { + info_utilization_edit->setText(QString().sprintf("%5.1lf%%", + (double)util/100.0)); + info_utilization_label->setEnabled(true); + info_utilization_edit->setEnabled(true); + info_utilization_button->setEnabled(true); + } + else { + info_utilization_edit->setText("xx.x"); + info_utilization_label->setDisabled(true); + info_utilization_edit->setDisabled(true); + info_utilization_button->setDisabled(true); + } +} + + void MainWidget::LoadAdapters() { int num_adapters; @@ -380,17 +440,19 @@ void MainWidget::LoadAdapters() HpiErr(HPI_AdapterGetMode(NULL,hpi_indexes[i],&hpi_mode[i]), "HPI_AdapterGetMode"); HpiErr(HPI_AdapterClose(NULL,hpi_indexes[i]),"HPI_AdapterClose"); + HpiErr(HPI_ProfileOpenAll(NULL,hpi_indexes[i],0,&hpi_profile[i], + &hpi_profile_quan[i])); } } } -void MainWidget::HpiErr(hpi_err_t err,const char *func_name) const +hpi_err_t MainWidget::HpiErr(hpi_err_t err,const char *func_name) const { char hpi_str[200]; if(err==HPI_ERROR_INVALID_FUNC) { - return; + return err; } if(err!=0) { HPI_GetErrorText(err,hpi_str); @@ -401,6 +463,7 @@ void MainWidget::HpiErr(hpi_err_t err,const char *func_name) const fprintf(stderr,"rdhpiinfo[%s]: %s\n",func_name,hpi_str); } } + return err; } diff --git a/utils/rdhpiinfo/rdhpiinfo.h b/utils/rdhpiinfo/rdhpiinfo.h index a0509e95..cb63baaf 100644 --- a/utils/rdhpiinfo/rdhpiinfo.h +++ b/utils/rdhpiinfo/rdhpiinfo.h @@ -27,7 +27,9 @@ #include #include #include +#include #include +#include #include #if HPI_VER < 0x040600 @@ -49,19 +51,24 @@ class MainWidget : public QWidget private slots: void nameActivatedData(int id); void changeModeData(); + void utilizationData(); + void updateDspUtilization(); private: void LoadAdapters(); - void HpiErr(hpi_err_t err,const char *func_name=0) const; + hpi_err_t HpiErr(hpi_err_t err,const char *func_name=0) const; QLabel *info_name_label; QComboBox *info_name_box; + QLabel *info_utilization_label; + QLineEdit *info_utilization_edit; + QPushButton *info_utilization_button; QLabel *info_index_label; QLabel *info_serial_label; QLabel *info_istreams_label; QLabel *info_ostreams_label; QLabel *info_dsp_label; QLabel *info_adapter_label; - QLabel *info_mode_label; + QLineEdit *info_mode_edit; QPushButton *info_changemode_button; uint32_t hpi_version; QString hpi_name[HPI_MAX_ADAPTERS]; @@ -73,6 +80,9 @@ class MainWidget : public QWidget uint32_t hpi_serial[HPI_MAX_ADAPTERS]; uint16_t hpi_type[HPI_MAX_ADAPTERS]; uint32_t hpi_mode[HPI_MAX_ADAPTERS]; + hpi_handle_t hpi_profile[HPI_MAX_ADAPTERS]; + uint16_t hpi_profile_quan[HPI_MAX_ADAPTERS]; + QTimer *hpi_profile_timer; }; diff --git a/utils/rdhpiinfo/virtdetails.cpp b/utils/rdhpiinfo/virtdetails.cpp new file mode 100644 index 00000000..665f0054 --- /dev/null +++ b/utils/rdhpiinfo/virtdetails.cpp @@ -0,0 +1,200 @@ +// virtdetails.cpp +// +// Show profile details for an AudioScience adapter. +// +// (C) Copyright 2014 Fred Gleason +// +// 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 +#include +#include + +#include "virtdetails.h" + +VirtDetails::VirtDetails(uint16_t card,hpi_handle_t profile, + uint16_t profile_quan,QWidget *parent) + : QDialog(parent,"",true) +{ + char name[200]; + + virt_card=card; + virt_profile=profile; + + // + // Fix the Window Size + // + setMinimumWidth(sizeHint().width()); + setMaximumWidth(sizeHint().width()); + setMinimumHeight(sizeHint().height()); + setMaximumHeight(sizeHint().height()); + + setCaption(tr("RdHPIInfo - Profile Details")); + + // + // Create Fonts + // + QFont font=QFont("Helvetica",12,QFont::Normal); + font.setPixelSize(12); + QFont label_font=QFont("Helvetica",12,QFont::Bold); + label_font.setPixelSize(12); + + // + // Adapter Mode + // + virt_profile_box=new QComboBox(this); + virt_profile_box->setGeometry(75,10,sizeHint().width()-85,20); + virt_profile_box->setFont(font); + virt_profile_label=new QLabel(virt_profile_box,tr("Profile")+":",this); + virt_profile_label->setGeometry(10,10,60,20); + virt_profile_label->setFont(label_font); + virt_profile_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter); + for(uint16_t i=0;iinsertItem(name); + } + } + } + + // + // Utilization Counter + // + virt_utilization_label=new QLabel(tr("Overall DSP Utilization")+":",this); + virt_utilization_label->setGeometry(10,35,160,20); + virt_utilization_label->setFont(label_font); + virt_utilization_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter); + virt_utilization_edit=new QLineEdit(this); + virt_utilization_edit->setGeometry(175,35,90,20); + virt_utilization_edit->setFont(font); + virt_utilization_edit->setReadOnly(true); + + // + // Profile Interval Counter + // + virt_interval_label=new QLabel(tr("Profile Interval")+":",this); + virt_interval_label->setGeometry(10,57,160,20); + virt_interval_label->setFont(label_font); + virt_interval_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter); + virt_interval_edit=new QLineEdit(this); + virt_interval_edit->setGeometry(175,57,90,20); + virt_interval_edit->setFont(font); + virt_interval_edit->setReadOnly(true); + + // + // Total Tick Count Counter + // + virt_total_ticks_label=new QLabel(tr("Total Tick Count")+":",this); + virt_total_ticks_label->setGeometry(10,79,160,20); + virt_total_ticks_label->setFont(label_font); + virt_total_ticks_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter); + virt_total_ticks_edit=new QLineEdit(this); + virt_total_ticks_edit->setGeometry(175,79,90,20); + virt_total_ticks_edit->setFont(font); + virt_total_ticks_edit->setReadOnly(true); + + // + // Call Count Counter + // + virt_call_count_label=new QLabel(tr("Call Count")+":",this); + virt_call_count_label->setGeometry(10,101,160,20); + virt_call_count_label->setFont(label_font); + virt_call_count_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter); + virt_call_count_edit=new QLineEdit(this); + virt_call_count_edit->setGeometry(175,101,90,20); + virt_call_count_edit->setFont(font); + virt_call_count_edit->setReadOnly(true); + + // + // Maximum Ticks Counter + // + virt_max_ticks_label=new QLabel(tr("Maximum Ticks / Pass")+":",this); + virt_max_ticks_label->setGeometry(10,123,160,20); + virt_max_ticks_label->setFont(label_font); + virt_max_ticks_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter); + virt_max_ticks_edit=new QLineEdit(this); + virt_max_ticks_edit->setGeometry(175,123,90,20); + virt_max_ticks_edit->setFont(font); + virt_max_ticks_edit->setReadOnly(true); + + // + // Ticks per Millisecond Counter + // + virt_ticks_per_ms_label=new QLabel(tr("Ticks / mS")+":",this); + virt_ticks_per_ms_label->setGeometry(10,145,160,20); + virt_ticks_per_ms_label->setFont(label_font); + virt_ticks_per_ms_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter); + virt_ticks_per_ms_edit=new QLineEdit(this); + virt_ticks_per_ms_edit->setGeometry(175,145,90,20); + virt_ticks_per_ms_edit->setFont(font); + virt_ticks_per_ms_edit->setReadOnly(true); + + // + // Close Button + // + QPushButton *close_button=new QPushButton(this); + close_button->setGeometry(sizeHint().width()-70,sizeHint().height()-40, + 60,30); + close_button->setFont(font); + close_button->setText(tr("&Close")); + connect(close_button,SIGNAL(clicked()),this,SLOT(closeData())); + + QTimer *timer=new QTimer(this); + connect(timer,SIGNAL(timeout()),this,SLOT(updateProfileData())); + timer->start(1000); +} + + +QSize VirtDetails::sizeHint() const +{ + return QSize(280,222); +} + + +QSizePolicy VirtDetails::sizePolicy() const +{ + return QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); +} + + +void VirtDetails::updateProfileData() +{ + uint32_t utilization; + uint16_t interval; + uint32_t total_ticks; + uint32_t call_count; + uint32_t max_ticks; + uint32_t ticks_per_ms; + + if(HPI_ProfileGetUtilization(NULL,virt_profile,&utilization)==0) { + virt_utilization_edit-> + setText(QString().sprintf("%5.1lf%%",(double)utilization/100.0)); + } + if(HPI_ProfileGet(NULL,virt_profile,virt_profile_box->currentItem(), + &interval,&total_ticks,&call_count,&max_ticks, + &ticks_per_ms)==0) { + virt_interval_edit->setText(QString().sprintf("%u sec",interval)); + virt_total_ticks_edit->setText(QString().sprintf("%u",total_ticks)); + virt_call_count_edit->setText(QString().sprintf("%u",call_count)); + virt_max_ticks_edit->setText(QString().sprintf("%u",max_ticks)); + virt_ticks_per_ms_edit->setText(QString().sprintf("%u",ticks_per_ms)); + } +} + + +void VirtDetails::closeData() +{ + done(0); +} diff --git a/utils/rdhpiinfo/virtdetails.h b/utils/rdhpiinfo/virtdetails.h new file mode 100644 index 00000000..8082d419 --- /dev/null +++ b/utils/rdhpiinfo/virtdetails.h @@ -0,0 +1,66 @@ +// virtdetails.h +// +// Show profiling data for an AudioScience adapter +// +// (C) Copyright 2014 Fred Gleason +// +// 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 VIRTDETAILS_H +#define VIRTDETAILS_H + +#include + +#include +#include +#include +#include + +#include + +class VirtDetails : public QDialog +{ + Q_OBJECT + public: + VirtDetails(uint16_t card,hpi_handle_t profile,uint16_t profile_quan, + QWidget *parent=0); + QSize sizeHint() const; + QSizePolicy sizePolicy() const; + +private slots: + void updateProfileData(); + void closeData(); + + private: + uint16_t virt_card; + hpi_handle_t virt_profile; + QLabel *virt_utilization_label; + QLineEdit *virt_utilization_edit; + QLabel *virt_profile_label; + QComboBox *virt_profile_box; + QLabel *virt_interval_label; + QLineEdit *virt_interval_edit; + QLabel *virt_total_ticks_label; + QLineEdit *virt_total_ticks_edit; + QLabel *virt_call_count_label; + QLineEdit *virt_call_count_edit; + QLabel *virt_max_ticks_label; + QLineEdit *virt_max_ticks_edit; + QLabel *virt_ticks_per_ms_label; + QLineEdit *virt_ticks_per_ms_edit; +}; + + +#endif // VIRTDETAILS_H 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..11807727 --- /dev/null +++ b/utils/rdimport/markerset.cpp @@ -0,0 +1,179 @@ +// markerset.cpp +// +// Abstract a set of marker parameters. +// +// (C) Copyright 2014 Fred Gleason +// +// 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 +#include + +#include "markerset.h" + +MarkerSet::MarkerSet() +{ + marker_start_valid=false; + marker_start_value=0; + marker_end_valid=false; + marker_end_value=0; + marker_fade_valid=false; + marker_fade_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(FrontReference(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(FrontReference(marker_end_value),lo_limit,hi_limit); +} + + +bool MarkerSet::hasFadeValue() const +{ + return marker_fade_valid; +} + + +int MarkerSet::fadeValue(int lo_limit,int hi_limit) const +{ + return LimitCheck(FrontReference(marker_fade_value),lo_limit,hi_limit); +} + + +void MarkerSet::loadMarker(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;ikeys();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::loadFade(RDCmdSwitch *cmd,const QString &marker) +{ + QString key="--set-marker-"+marker; + marker_marker=marker; + for(unsigned i=0;ikeys();i++) { + if(cmd->key(i)==key) { + marker_fade_value=cmd->value(i).toInt(&marker_fade_valid); + if(!marker_fade_valid) { + fprintf(stderr,"rdimport: invalid argment to %s\n", + (const char *)key); + exit(255); + } + cmd->setProcessed(i,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); + } + if(marker_fade_valid) { + printf(" Marker %s: ",(const char *)marker_marker); + printf("%d mS\n",marker_fade_value); + } +} + + +int MarkerSet::LimitCheck(int value,int lo_limit,int hi_limit) const +{ + if(lo_limit!=-1) { + if(valuehi_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..6fe9c607 --- /dev/null +++ b/utils/rdimport/markerset.h @@ -0,0 +1,55 @@ +// markerset.h +// +// Abstract a set of marker parameters. +// +// (C) Copyright 2014 Fred Gleason +// +// 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 + +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; + bool hasFadeValue() const; + int fadeValue(int lo_limit=-1,int hi_limit=-1) const; + void loadMarker(RDCmdSwitch *cmd,const QString &marker); + void loadFade(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; + bool marker_fade_valid; + int marker_fade_value; + int marker_audio_length; +}; + + +#endif // MARKERSET_H diff --git a/utils/rdimport/rdimport.cpp b/utils/rdimport/rdimport.cpp index 64e650fe..3dac0e57 100644 --- a/utils/rdimport/rdimport.cpp +++ b/utils/rdimport/rdimport.cpp @@ -2,9 +2,7 @@ // // A Batch Importer for Rivendell. // -// (C) Copyright 2002-2008 Fred Gleason -// -// $Id: rdimport.cpp,v 1.34.4.9.2.3 2014/07/15 00:45:16 cvs Exp $ +// (C) Copyright 2002-2014 Fred Gleason // // 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 @@ -87,6 +85,10 @@ MainObject::MainObject(QObject *parent,const char *name) import_create_dates=false; import_create_startdate_offset=0; import_create_enddate_offset=0; + import_string_bpm=0; + import_string_year=0; + import_clear_datetimes=false; + import_clear_dayparts=false; // // Read Command Options @@ -162,6 +164,62 @@ MainObject::MainObject(QObject *parent,const char *name) exit(256); } } + if(import_cmd->key(i)=="--clear-datetimes") { + import_clear_datetimes=true; + import_cmd->setProcessed(i,true); + } + if(import_cmd->key(i)=="--set-datetimes") { + QStringList f0=QStringList().split(",",import_cmd->value(i)); + if(f0.size()!=2) { + fprintf(stderr,"rdimport: invalid argument to --set-datetimes\n"); + exit(256); + } + for(unsigned j=0;j<2;j++) { + if((f0[j].length()!=15)||(f0[j].mid(8,1)!="-")) { + fprintf(stderr,"rdimport: invalid argument to --set-datetimes\n"); + exit(256); + } + unsigned year=f0[j].left(4).toUInt(&ok); + if(!ok) { + fprintf(stderr,"rdimport: invalid year argument to --set-datetimes\n"); + exit(256); + } + unsigned month=f0[j].mid(4,2).toUInt(&ok); + if((!ok)||(month>12)) { + fprintf(stderr,"rdimport: invalid month argument to --set-datetimes\n"); + exit(256); + } + unsigned day=f0[j].mid(6,2).toUInt(&ok); + if((!ok)||(day>31)) { + fprintf(stderr,"rdimport: invalid day argument to --set-datetimes\n"); + exit(256); + } + unsigned hour=f0[j].mid(9,2).toUInt(&ok); + if((!ok)||(hour>23)) { + fprintf(stderr,"rdimport: invalid hour argument to --set-datetimes\n"); + exit(256); + } + unsigned min=f0[j].mid(11,2).toUInt(&ok); + if((!ok)||(min>59)) { + fprintf(stderr,"rdimport: invalid minute argument to --set-datetimes\n"); + exit(256); + } + unsigned sec=f0[j].right(2).toUInt(&ok); + if((!ok)||(sec>59)) { + fprintf(stderr,"rdimport: invalid seconds argument to --set-datetimes\n"); + exit(256); + } + import_datetimes[j]=QDateTime(QDate(year,month,day), + QTime(hour,min,sec)); + if(!import_datetimes[j].isValid()) { + fprintf(stderr,"rdimport: invalid argument to --set-datetimes\n"); + } + } + if(import_datetimes[0]>=import_datetimes[1]) { + fprintf(stderr,"rdimport: datetime cannot end before it begins\n"); + exit(256); + } + } if(import_cmd->key(i)=="--set-daypart-times") { QStringList f0=QStringList().split(",",import_cmd->value(i)); if(f0.size()!=2) { @@ -195,6 +253,10 @@ MainObject::MainObject(QObject *parent,const char *name) exit(256); } } + if(import_cmd->key(i)=="--clear-daypart-times") { + import_clear_dayparts=true; + import_cmd->setProcessed(i,true); + } if(import_cmd->key(i)=="--drop-box") { import_drop_box=true; if(import_persistent_dropbox_id<0) { @@ -245,7 +307,100 @@ MainObject::MainObject(QObject *parent,const char *name) } import_create_dates=true; } + if(import_cmd->key(i)=="--set-string-agency") { + import_string_agency=import_cmd->value(i); + import_cmd->setProcessed(i,true); + } + if(import_cmd->key(i)=="--set-string-album") { + import_string_album=import_cmd->value(i); + import_cmd->setProcessed(i,true); + } + if(import_cmd->key(i)=="--set-string-artist") { + import_string_artist=import_cmd->value(i); + import_cmd->setProcessed(i,true); + } + if(import_cmd->key(i)=="--set-string-bpm") { + import_string_bpm=import_cmd->value(i).toInt(&ok); + if(!ok) { + fprintf(stderr,"rdimport: invalid value for --set-string-bpm\n"); + exit(255); + } + import_cmd->setProcessed(i,true); + } + if(import_cmd->key(i)=="--set-string-client") { + import_string_client=import_cmd->value(i); + import_cmd->setProcessed(i,true); + } + if(import_cmd->key(i)=="--set-string-composer") { + import_string_composer=import_cmd->value(i); + import_cmd->setProcessed(i,true); + } + if(import_cmd->key(i)=="--set-string-conductor") { + import_string_conductor=import_cmd->value(i); + import_cmd->setProcessed(i,true); + } + if(import_cmd->key(i)=="--set-string-description") { + import_string_description=import_cmd->value(i); + import_cmd->setProcessed(i,true); + } + if(import_cmd->key(i)=="--set-string-label") { + import_string_label=import_cmd->value(i); + import_cmd->setProcessed(i,true); + } + if(import_cmd->key(i)=="--set-string-outcue") { + import_string_outcue=import_cmd->value(i); + import_cmd->setProcessed(i,true); + } + if(import_cmd->key(i)=="--set-string-publisher") { + import_string_publisher=import_cmd->value(i); + import_cmd->setProcessed(i,true); + } + if(import_cmd->key(i)=="--set-string-song-id") { + import_string_song_id=import_cmd->value(i); + import_cmd->setProcessed(i,true); + } + if(import_cmd->key(i)=="--set-string-title") { + if(import_cmd->value(i).isEmpty()) { + fprintf(stderr,"title field cannot be empty\n"); + exit(255); + } + import_string_title=import_cmd->value(i); + import_cmd->setProcessed(i,true); + } + if(import_cmd->key(i)=="--set-string-user-defined") { + import_string_user_defined=import_cmd->value(i); + import_cmd->setProcessed(i,true); + } + if(import_cmd->key(i)=="--set-string-year") { + import_string_year=import_cmd->value(i).toInt(&ok); + if(!ok) { + fprintf(stderr,"rdimport: invalid value for --set-string-year\n"); + exit(255); + } + import_cmd->setProcessed(i,true); + } } + if(import_datetimes[0].isValid()&&import_clear_datetimes) { + fprintf(stderr,"rdimport: --set-datetimes and --clear-datetimes are mutually exclusive\n"); + exit(255); + } + if((!import_dayparts[1].isNull())&&import_clear_dayparts) { + fprintf(stderr,"rdimport: --set-daypart-times and --clear-daypart-times are mutually exclusive\n"); + exit(255); + } + + import_cut_markers=new MarkerSet(); + import_cut_markers->loadMarker(import_cmd,"cut"); + import_talk_markers=new MarkerSet(); + import_talk_markers->loadMarker(import_cmd,"talk"); + import_hook_markers=new MarkerSet(); + import_hook_markers->loadMarker(import_cmd,"hook"); + import_segue_markers=new MarkerSet(); + import_segue_markers->loadMarker(import_cmd,"segue"); + import_fadedown_marker=new MarkerSet(); + import_fadedown_marker->loadFade(import_cmd,"fadedown"); + import_fadeup_marker=new MarkerSet(); + import_fadeup_marker->loadFade(import_cmd,"fadeup"); // // Read Configuration @@ -375,8 +530,8 @@ MainObject::MainObject(QObject *parent,const char *name) if(import_cmd->key(i)=="--segue-level") { n=import_cmd->value(i).toInt(&ok); if(ok&&(n<=0)) { - import_segue_level=100*n; - } + import_segue_level=n; + } else { fprintf(stderr,"rdimport: invalid segue level\n"); delete import_cmd; @@ -491,6 +646,18 @@ MainObject::MainObject(QObject *parent,const char *name) printf(" End Daypart = %s\n", (const char *)import_dayparts[1].toString("hh:mm:ss")); } + if(import_clear_dayparts) { + printf(" Clearing daypart times\n"); + } + if((!import_datetimes[0].isNull())||(!import_datetimes[1].isNull())) { + printf(" Start DateTime = %s\n", + (const char *)import_datetimes[0].toString("MM/dd/yyyy hh:mm:ss")); + printf(" End DateTime = %s\n", + (const char *)import_datetimes[1].toString("MM/dd/yyyy hh:mm:ss")); + } + if(import_clear_datetimes) { + printf(" Clearing datetimes\n"); + } if(import_fix_broken_formats) { printf(" Broken format workarounds are ENABLED\n"); } @@ -508,6 +675,59 @@ MainObject::MainObject(QObject *parent,const char *name) if(import_persistent_dropbox_id>=0) { printf(" Persistent DropBox ID = %d\n",import_persistent_dropbox_id); } + if(!import_string_agency.isNull()) { + printf(" Agency set to: %s\n",(const char *)import_string_agency); + } + if(!import_string_album.isNull()) { + printf(" Album set to: %s\n",(const char *)import_string_album); + } + if(!import_string_artist.isNull()) { + printf(" Artist set to: %s\n",(const char *)import_string_artist); + } + if(import_string_bpm!=0) { + printf(" BPM set to: %d\n",import_string_bpm); + } + if(!import_string_client.isNull()) { + printf(" Client set to: %s\n",(const char *)import_string_client); + } + if(!import_string_composer.isNull()) { + printf(" Composer set to: %s\n",(const char *)import_string_composer); + } + if(!import_string_conductor.isNull()) { + printf(" Conductor set to: %s\n",(const char *)import_string_conductor); + } + if(!import_string_description.isNull()) { + printf(" Description set to: %s\n", + (const char *)import_string_description); + } + if(!import_string_label.isNull()) { + printf(" Label set to: %s\n",(const char *)import_string_label); + } + if(!import_string_outcue.isNull()) { + printf(" Outcue set to: %s\n",(const char *)import_string_outcue); + } + if(!import_string_publisher.isNull()) { + printf(" Publisher set to: %s\n",(const char *)import_string_publisher); + } + if(!import_string_song_id.isNull()) { + printf(" Song ID set to: %s\n",(const char *)import_string_song_id); + } + if(!import_string_title.isNull()) { + printf(" Title set to: %s\n",(const char *)import_string_title); + } + if(!import_string_user_defined.isNull()) { + printf(" User Defined set to: %s\n", + (const char *)import_string_user_defined); + } + if(import_string_year!=0) { + printf(" Year set to: %d\n",import_string_year); + } + import_cut_markers->dump(); + import_talk_markers->dump(); + import_hook_markers->dump(); + import_segue_markers->dump(); + import_fadedown_marker->dump(); + import_fadeup_marker->dump(); printf(" Files to process:\n"); for(unsigned i=import_file_key;ikeys();i++) { printf(" \"%s\"\n",(const char *)import_cmd->key(i)); @@ -785,7 +1005,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), @@ -891,9 +1110,16 @@ MainObject::Result MainObject::ImportFile(const QString &filename, (const char *)RDGetBasePart(filename).utf8(),*cartnum); } else { - printf(" Importing file \"%s\" [%s] to cart %06u ... ", - (const char *)RDGetBasePart(filename).utf8(), - (const char *)wavedata->title().stripWhiteSpace(),*cartnum); + if(import_string_title.isNull()) { + printf(" Importing file \"%s\" [%s] to cart %06u ... ", + (const char *)RDGetBasePart(filename).utf8(), + (const char *)wavedata->title().stripWhiteSpace(),*cartnum); + } + else { + printf(" Importing file \"%s\" [%s] to cart %06u ... ", + (const char *)RDGetBasePart(filename).utf8(), + (const char *)import_string_title.stripWhiteSpace(),*cartnum); + } } fflush(stdout); } @@ -944,7 +1170,8 @@ MainObject::Result MainObject::ImportFile(const QString &filename, } cut->setMetadata(wavedata); } - cut->autoSegue(import_segue_level,import_segue_length); + cut->autoSegue(import_segue_level,import_segue_length,import_station, + import_user,import_config); if((wavedata->title().length()==0)|| ((wavedata->title().length()>0)&&(wavedata->title()[0] == '\0'))) { QString title=effective_group->generateTitle(filename); @@ -965,6 +1192,9 @@ MainObject::Result MainObject::ImportFile(const QString &filename, cart->setTitle(wavedata->cutId()); } } + if(cut->description().isEmpty()) { // Final backstop, so we don't end up + cut->setDescription(cart->title()); // with an empty description field. + } if(!import_metadata_pattern.isEmpty()) { cart->setTitle(wavedata->title()); } @@ -996,13 +1226,102 @@ MainObject::Result MainObject::ImportFile(const QString &filename, for(unsigned i=0;iaddSchedCode(import_add_scheduler_codes[i]); } + if(!import_string_agency.isNull()) { + cart->setAgency(import_string_agency); + } + if(!import_string_album.isNull()) { + cart->setAlbum(import_string_album); + } + if(!import_string_artist.isNull()) { + cart->setArtist(import_string_artist); + } + if(import_string_bpm!=0) { + cart->setBeatsPerMinute(import_string_bpm); + } + if(!import_string_client.isNull()) { + cart->setClient(import_string_client); + } + if(!import_string_composer.isNull()) { + cart->setComposer(import_string_composer); + } + if(!import_string_conductor.isNull()) { + cart->setConductor(import_string_conductor); + } + if(!import_string_description.isNull()) { + cut->setDescription(import_string_description); + } + if(!import_string_label.isNull()) { + cart->setLabel(import_string_label); + } + if(!import_string_outcue.isNull()) { + cut->setOutcue(import_string_outcue); + } + if(!import_string_publisher.isNull()) { + cart->setPublisher(import_string_publisher); + } + if(!import_string_song_id.isNull()) { + cart->setSongId(import_string_song_id); + } + if(!import_string_title.isNull()) { + cart->setTitle(import_string_title); + } if(!import_set_user_defined.isEmpty()) { cart->setUserDefined(import_set_user_defined); } + if(!import_string_user_defined.isNull()) { + cart->setUserDefined(import_string_user_defined); + } + if(import_string_year!=0) { + cart->setYear(import_string_year); + } if((!import_dayparts[0].isNull())||(!import_dayparts[1].isNull())) { cut->setStartDaypart(import_dayparts[0],true); cut->setEndDaypart(import_dayparts[1],true); } + if(import_clear_dayparts) { + cut->setStartDaypart(QTime(),false); + cut->setEndDaypart(QTime(),false); + } + if((!import_datetimes[0].isNull())||(!import_datetimes[1].isNull())) { + cut->setStartDatetime(import_datetimes[0],true); + cut->setEndDatetime(import_datetimes[1],true); + } + if(import_clear_datetimes) { + cut->setStartDatetime(QDateTime(),false); + cut->setEndDatetime(QDateTime(),false); + } + 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()); + } + 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)); + } + import_fadedown_marker->setAudioLength(wavefile->getExtTimeLength()); + if(import_fadedown_marker->hasFadeValue()) { + cut->setFadedownPoint(import_fadedown_marker->fadeValue(lo,hi)); + } + import_fadeup_marker->setAudioLength(wavefile->getExtTimeLength()); + if(import_fadeup_marker->hasFadeValue()) { + cut->setFadeupPoint(import_fadeup_marker->fadeValue(lo,hi)); + } + cart->updateLength(); delete settings; delete conv; delete cut; diff --git a/utils/rdimport/rdimport.h b/utils/rdimport/rdimport.h index fe9229b7..5d0eb153 100644 --- a/utils/rdimport/rdimport.h +++ b/utils/rdimport/rdimport.h @@ -44,11 +44,13 @@ #include #include +#include "markerset.h" + #define RDIMPORT_TEMP_BASENAME "rdimp" #define RDIMPORT_STDIN_BUFFER_LENGTH 1024 #define RDIMPORT_DROPBOX_SCAN_INTERVAL 5 #define RDIMPORT_DROPBOX_PASSES 3 -#define RDIMPORT_USAGE "[options] []*\n\nImport one or more files into the specified group in the library. By\ndefault, a new cart will be created for each file imported. A of \n'-' will cause RDImport to read the list of filespecs from standard input.\n\nThe following options are available:\n\n --verbose\n Print progress messages during processing.\n\n --log-mode\n Prepend date/time information to each line of printed status (implies\n the '--verbose' option).\n\n --normalization-level=\n Specify the level to use for normalizing the audio, in dBFS.\n Specifying '0' will turn off normalization.\n\n --autotrim-level=\n Specify the threshold level to use for autotrimming the audio, in\n dBFS. Specifying '0' will turn off autotrimming.\n\n --single-cart\n If more than one file is imported, place them within multiple cuts\n within a single cart, rather than creating separate carts for each\n file.\n\n --segue-level=\n Specify the threshold level to use for setting the segue markers,\n in dBFS.\n\n --segue-length=\n Length of the added segue in msecs.\n\n --to-cart=\n Specify the cart to import the audio into, rather than using the next\n available cart number for the group. If the cart does not exist, it will\n be created. Each file will be imported into a separate new cut within the\n cart. Use of this option implies the '--single-cart' option as well,\n and is mutually exclusive with the '--use-cartchunk-cutid' option.\n\n --use-cartchunk-cutid\n Import the audio into the cart specified by the CartChunk CutID parameter\n associated with the file. If the cart does not exist, it will be\n created. Use of this option is mutually exclusive with the '--to-cart'\n option.\n\n --title-from-cartchunk-cutid\n Set the cart title from CartChunk CutID.\n\n --cart-number-offset=\n Add to the cart number as determined from metadata pattern\n or --use-cartchunk-cutid\n\n --delete-source\n Delete each source file after successful import. Use with caution!\n\n --delete-cuts\n Delete all cuts within the destination cart before importing. Use\n with caution!\n\n --drop-box\n Operate in DropBox mode. RDImport will run continuously, periodically\n scanning for the specified files, importing and then deleting them when\n found. WARNING: use of this option in command-line mode also implies\n the '--delete-source' option!\n\n --metadata-pattern=\n Attempt to read metadata parameters from the source filename, using\n the pattern . Patterns consist of a sequence of macros and\n regular characters to indicate boundaries between metadata fields.\n The available macros are:\n\n %a - Artist\n %b - Record Label\n %c - Client\n %e - Agency\n %g - Rivendell Group\n %i - Cut Description\n %l - Album\n %m - Composer\n %n - Rivendell Cart Number\n %o - Outcue\n %p - Publisher\n %r - Conductor\n %s - Song ID\n %t - Title\n %u - User Defined\n %y - Release Year (four digit)\n %% - A literal '%'\n\n Detection of either the Rivendell Group [%g] or Rivendell Cart [%n]\n will cause RDImport to attempt to import the file to the specified Group\n and/or Cart, overriding whatever values were specified elsewhere on the\n command line. If the '--set-user-defined=' option has been used,\n then the value specified there will be used instead of %u.\n\n Boundaries between metadata fields are indicated by placing regular\n characters between macros. For example, the pattern '%t_%a_%g_%n.',\n when processing a filename of 'My Song_My Artist_TEMP_123456.mp3',\n would extract 'My Song' as the title and 'My Artist' as the artist,\n while importing it into cart 123456 in the TEMP group.\n\n --startdate-offset=\n If the imported file references a start date, offset the value by\n days.\n\n --enddate-offset=\n If the imported file references an end date, offset the value by\n days.\n\n --create-startdate-offset=\n If the imported file does not reference a start date, create with \n startdate offset by days relative to the current date.\n Cannot be greater than the value for --create-enddate-offset\n (default = 0).\n\n --create-enddate-offset=\n If the imported file does not reference an end date, create with\n end date offset by days relative to the current date.\n Cannot be less than the value the value for --create-startdate-offset\n (default = 0).\n\n --set-daypart-times=,\n Set the start and end daypart times, in the format HHMMSS.\n\n --fix-broken-formats\n Attempt to work around malformed audio input data.\n\n --add-scheduler-code=\n Add Scheduler Code to the target cart. The specified\n code must exist in RDAdmin->SchedulerCodes. This option may be\n specified multiple times.\n\n --set-user-defined=\n Set the User Defined field for the target cart to . This will\n override any value that might otherwise be set (see the\n '--metadata-pattern=' option above).\n\nNOTES\nIt may be necessary to enclose individual clauses in quotes in\norder to protect wildcard characters from expansion by the shell. A typical\nindicator that this is necessary is the failure of RDImport to process newly\nadded files when running in DropBox mode.\n" +#define RDIMPORT_USAGE "[options] []*\n\nAudio importation tool for the Rivendell Radio Automation System.\nDo 'man 1 rdimport' for the full manual.\n" #define RDIMPORT_GLOB_SIZE 10 class MainObject : public QObject @@ -102,7 +104,10 @@ class MainObject : public QObject bool import_create_dates; int import_create_startdate_offset; int import_create_enddate_offset; + QDateTime import_datetimes[2]; + bool import_clear_datetimes; QTime import_dayparts[2]; + bool import_clear_dayparts; bool import_fix_broken_formats; int import_persistent_dropbox_id; unsigned import_format; @@ -116,6 +121,21 @@ class MainObject : public QObject int import_segue_length; unsigned import_cart_number; QString import_metadata_pattern; + QString import_string_agency; + QString import_string_album; + QString import_string_artist; + int import_string_bpm; + QString import_string_client; + QString import_string_composer; + QString import_string_conductor; + QString import_string_description; + QString import_string_outcue; + QString import_string_publisher; + QString import_string_label; + QString import_string_song_id; + QString import_string_title; + QString import_string_user_defined; + int import_string_year; struct DropboxList { QString filename; unsigned size; @@ -127,6 +147,12 @@ 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; + MarkerSet *import_fadedown_marker; + MarkerSet *import_fadeup_marker; }; diff --git a/utils/rdmaint/rdmaint.cpp b/utils/rdmaint/rdmaint.cpp index ea42c20b..212397fb 100644 --- a/utils/rdmaint/rdmaint.cpp +++ b/utils/rdmaint/rdmaint.cpp @@ -132,6 +132,7 @@ void MainObject::RunSystemMaintenance() PurgeCuts(); PurgeLogs(); PurgeElr(); + PurgeGpioEvents(); sql="update VERSION set LAST_MAINT_DATETIME=now()"; q=new RDSqlQuery(sql); delete q; @@ -268,6 +269,19 @@ void MainObject::PurgeDropboxes() delete q; } + +void MainObject::PurgeGpioEvents() +{ + QString sql; + RDSqlQuery *q; + + sql=QString("delete from GPIO_EVENTS where ")+ + "EVENT_DATETIME<\""+ + QDate::currentDate().addDays(-30).toString("yyyy-MM-dd")+" 00:00:00\""; + q=new RDSqlQuery(sql); + delete q; +} + int main(int argc,char *argv[]) { diff --git a/utils/rdmaint/rdmaint.h b/utils/rdmaint/rdmaint.h index ac4f418d..7fca98eb 100644 --- a/utils/rdmaint/rdmaint.h +++ b/utils/rdmaint/rdmaint.h @@ -47,6 +47,7 @@ class MainObject : public QObject void PurgeLogs(); void PurgeElr(); void PurgeDropboxes(); + void PurgeGpioEvents(); RDConfig *maint_config; bool maint_verbose; bool maint_system; diff --git a/web/rdxport/Makefile.am b/web/rdxport/Makefile.am index cda2422c..ae0e9bc7 100644 --- a/web/rdxport/Makefile.am +++ b/web/rdxport/Makefile.am @@ -31,6 +31,7 @@ install-exec-hook: if test -z $(DESTDIR) ; then chown root $(DESTDIR)$(libexecdir)/rdxport.cgi ; chmod 4755 $(DESTDIR)$(libexecdir)/rdxport.cgi ; fi dist_rdxport_cgi_SOURCES = audioinfo.cpp\ + audiostore.cpp\ carts.cpp\ copyaudio.cpp\ deleteaudio.cpp\ diff --git a/web/rdxport/audiostore.cpp b/web/rdxport/audiostore.cpp new file mode 100644 index 00000000..9cd8642d --- /dev/null +++ b/web/rdxport/audiostore.cpp @@ -0,0 +1,53 @@ +// audiostore.cpp +// +// Rivendell web service portal -- AudioStore service +// +// (C) Copyright 2014 Fred Gleason +// +// 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +void Xport::AudioStore() +{ + struct statvfs stat; + + memset(&stat,0,sizeof(stat)); + if(statvfs(xport_config->audioRoot(),&stat)<0) { + XmlExit("Internal Error",400); + } + printf("Content-type: application/xml\n"); + printf("Status: 200\n\n"); + printf("\n"); + printf("\n"); + printf(" %lu\n",stat.f_bfree*stat.f_bsize); + printf(" %lu\n",stat.f_blocks*stat.f_bsize); + printf("\n"); + + Exit(0); +} diff --git a/web/rdxport/rdxport.cpp b/web/rdxport/rdxport.cpp index 55ac386c..d8b2db12 100644 --- a/web/rdxport/rdxport.cpp +++ b/web/rdxport/rdxport.cpp @@ -219,6 +219,10 @@ Xport::Xport(QObject *parent,const char *name) AudioInfo(); break; + case RDXPORT_COMMAND_AUDIOSTORE: + AudioStore(); + break; + case RDXPORT_COMMAND_LISTLOGS: ListLogs(); break; diff --git a/web/rdxport/rdxport.h b/web/rdxport/rdxport.h index cf556ebb..72e1252e 100644 --- a/web/rdxport/rdxport.h +++ b/web/rdxport/rdxport.h @@ -54,6 +54,7 @@ class Xport : public QObject void TrimAudio(); void CopyAudio(); void AudioInfo(); + void AudioStore(); void ListLogs(); void ListLog(); void ListServices(); diff --git a/web/tests/Makefile.am b/web/tests/Makefile.am index d1351884..b9219bc3 100644 --- a/web/tests/Makefile.am +++ b/web/tests/Makefile.am @@ -26,6 +26,7 @@ install-exec-am: cp addcart.html $(DESTDIR)@libexecdir@ cp addcut.html $(DESTDIR)@libexecdir@ cp audioinfo.html $(DESTDIR)@libexecdir@ + cp audiostore.html $(DESTDIR)@libexecdir@ cp copyaudio.html $(DESTDIR)@libexecdir@ cp delete_audio.html $(DESTDIR)@libexecdir@ cp editcart.html $(DESTDIR)@libexecdir@ @@ -50,6 +51,7 @@ uninstall: rm -f $(DESTDIR)@libexecdir@/addcart.html rm -f $(DESTDIR)@libexecdir@/addcut.html rm -f $(DESTDIR)@libexecdir@/audioinfo.html + rm -f $(DESTDIR)@libexecdir@/audiostore.html rm -f $(DESTDIR)@libexecdir@/copyaudio.html rm -f $(DESTDIR)@libexecdir@/delete_audio.html rm -f $(DESTDIR)@libexecdir@/editcart.html @@ -72,6 +74,7 @@ uninstall: EXTRA_DIST = addcart.html\ addcut.html\ audioinfo.html\ + audiostore.html\ copyaudio.html\ delete_audio.html\ editcart.html\ diff --git a/web/tests/audiostore.html b/web/tests/audiostore.html new file mode 100644 index 00000000..2a1fac7e --- /dev/null +++ b/web/tests/audiostore.html @@ -0,0 +1,25 @@ + + +Rivendell AUDIOSTORE Service Test Harness + +
+ + + + + + + + + + + + + + + + +
LOGIN NAME:
PASSWORD:
 
+
+ +