diff --git a/airtime_mvc/application/controllers/PreferenceController.php b/airtime_mvc/application/controllers/PreferenceController.php index 75b8fc2e8..7d0f21210 100644 --- a/airtime_mvc/application/controllers/PreferenceController.php +++ b/airtime_mvc/application/controllers/PreferenceController.php @@ -43,6 +43,7 @@ class PreferenceController extends Zend_Controller_Action if ($form->isValid($values)) { Application_Model_Preference::SetHeadTitle($values["stationName"], $this->view); + Application_Model_Preference::SetDefaultCrossfadeDuration($values["stationDefaultCrossfadeDuration"]); Application_Model_Preference::SetDefaultFadeIn($values["stationDefaultFadeIn"]); Application_Model_Preference::SetDefaultFadeOut($values["stationDefaultFadeOut"]); Application_Model_Preference::SetAllow3rdPartyApi($values["thirdPartyApi"]); diff --git a/airtime_mvc/application/forms/GeneralPreferences.php b/airtime_mvc/application/forms/GeneralPreferences.php index f73320e28..29c819fac 100644 --- a/airtime_mvc/application/forms/GeneralPreferences.php +++ b/airtime_mvc/application/forms/GeneralPreferences.php @@ -26,6 +26,25 @@ class Application_Form_GeneralPreferences extends Zend_Form_SubForm 'ViewHelper' ) )); + + //Default station fade in + $this->addElement('text', 'stationDefaultCrossfadeDuration', array( + 'class' => 'input_text', + 'label' => _('Default Crossfade Duration (s):'), + 'required' => true, + 'filters' => array('StringTrim'), + 'validators' => array( + array( + $rangeValidator, + $notEmptyValidator, + 'regex', false, array('/^[0-9]{1,2}(\.\d{1})?$/', 'messages' => _('enter a time in seconds 0{.0}')) + ) + ), + 'value' => Application_Model_Preference::GetDefaultCrossfadeDuration(), + 'decorators' => array( + 'ViewHelper' + ) + )); //Default station fade in $this->addElement('text', 'stationDefaultFadeIn', array( diff --git a/airtime_mvc/application/models/Playlist.php b/airtime_mvc/application/models/Playlist.php index d0df1b19d..806d57955 100644 --- a/airtime_mvc/application/models/Playlist.php +++ b/airtime_mvc/application/models/Playlist.php @@ -36,6 +36,7 @@ class Application_Model_Playlist implements Application_Model_LibraryEditable "cueout" => "00:00:00", "fadein" => "0.0", "fadeout" => "0.0", + "crossfadeDuration" => 0 ); //using propel's phpNames. @@ -62,6 +63,7 @@ class Application_Model_Playlist implements Application_Model_LibraryEditable $this->plItem["fadein"] = Application_Model_Preference::GetDefaultFadeIn(); $this->plItem["fadeout"] = Application_Model_Preference::GetDefaultFadeOut(); + $this->plItem["crossfadeDuration"] = Application_Model_Preference::GetDefaultCrossfadeDuration(); $this->con = isset($con) ? $con : Propel::getConnection(CcPlaylistPeer::DATABASE_NAME); $this->id = $this->pl->getDbId(); diff --git a/airtime_mvc/application/models/Preference.php b/airtime_mvc/application/models/Preference.php index 2e0096a49..0735c87e4 100644 --- a/airtime_mvc/application/models/Preference.php +++ b/airtime_mvc/application/models/Preference.php @@ -195,6 +195,23 @@ class Application_Model_Preference } } + public static function SetDefaultCrossfadeDuration($duration) + { + self::setValue("default_crossfade_duration", $duration); + } + + public static function GetDefaultCrossfadeDuration() + { + $duration = self::getValue("default_crossfade_duration"); + + if ($duration === "") { + // the default value of the fade is 00.5 + return "0"; + } + + return $duration; + } + public static function SetDefaultFadeIn($fade) { self::setValue("default_fade_in", $fade); diff --git a/airtime_mvc/application/models/Scheduler.php b/airtime_mvc/application/models/Scheduler.php index 3778cf007..f2c435e2d 100644 --- a/airtime_mvc/application/models/Scheduler.php +++ b/airtime_mvc/application/models/Scheduler.php @@ -17,6 +17,8 @@ class Application_Model_Scheduler private $epochNow; private $nowDT; private $user; + + private $crossfadeDuration; private $checkUserPermissions = true; @@ -38,6 +40,8 @@ class Application_Model_Scheduler } $this->user = Application_Model_User::getCurrentUser(); + + $this->crossfadeDuration = Application_Model_Preference::GetDefaultCrossfadeDuration(); } public function setCheckUserPermissions($value) @@ -201,12 +205,9 @@ class Application_Model_Scheduler $data["cuein"] = $file->getDbCuein(); $data["cueout"] = $file->getDbCueout(); - $defaultFade = Application_Model_Preference::GetDefaultFade(); - if (isset($defaultFade)) { - //fade is in format SS.uuuuuu - $data["fadein"] = $defaultFade; - $data["fadeout"] = $defaultFade; - } + //fade is in format SS.uuuuuu + $data["fadein"] = Application_Model_Preference::GetDefaultFadeIn(); + $data["fadeout"] = Application_Model_Preference::GetDefaultFadeOut(); $files[] = $data; } @@ -260,12 +261,11 @@ class Application_Model_Scheduler $cuein = Application_Common_DateHelper::calculateLengthInSeconds($data["cuein"]); $cueout = Application_Common_DateHelper::calculateLengthInSeconds($data["cueout"]); $data["cliplength"] = Application_Common_DateHelper::secondsToPlaylistTime($cueout - $cuein); - $defaultFade = Application_Model_Preference::GetDefaultFade(); - if (isset($defaultFade)) { - //fade is in format SS.uuuuuu - $data["fadein"] = $defaultFade; - $data["fadeout"] = $defaultFade; - } + + //fade is in format SS.uuuuuu + $data["fadein"] = Application_Model_Preference::GetDefaultFadeIn(); + $data["fadeout"] = Application_Model_Preference::GetDefaultFadeOut(); + $data["type"] = 0; $files[] = $data; } @@ -286,12 +286,9 @@ class Application_Model_Scheduler $data["cueout"] = $stream->getDbLength(); $data["type"] = 1; - $defaultFade = Application_Model_Preference::GetDefaultFade(); - if (isset($defaultFade)) { - //fade is in format SS.uuuuuu - $data["fadein"] = $defaultFade; - $data["fadeout"] = $defaultFade; - } + //fade is in format SS.uuuuuu + $data["fadein"] = Application_Model_Preference::GetDefaultFadeIn(); + $data["fadeout"] = Application_Model_Preference::GetDefaultFadeOut(); $files[] = $data; } @@ -321,12 +318,11 @@ class Application_Model_Scheduler $cuein = Application_Common_DateHelper::calculateLengthInSeconds($data["cuein"]); $cueout = Application_Common_DateHelper::calculateLengthInSeconds($data["cueout"]); $data["cliplength"] = Application_Common_DateHelper::secondsToPlaylistTime($cueout - $cuein); - $defaultFade = Application_Model_Preference::GetDefaultFade(); - if (isset($defaultFade)) { - //fade is in format SS.uuuuuu - $data["fadein"] = $defaultFade; - $data["fadeout"] = $defaultFade; - } + + //fade is in format SS.uuuuuu + $data["fadein"] = Application_Model_Preference::GetDefaultFadeIn(); + $data["fadeout"] = Application_Model_Preference::GetDefaultFadeOut(); + $data["type"] = 0; $files[] = $data; } @@ -336,6 +332,31 @@ class Application_Model_Scheduler return $files; } + + /* + * @param DateTime startDT in UTC + * @param string duration + * in format H:i:s.u (could be more that 24 hours) + * + * @return DateTime endDT in UTC + */ + private function findTimeDifference($p_startDT, $p_seconds) + { + $startEpoch = $p_startDT->format("U.u"); + + //add two float numbers to 6 subsecond precision + //DateTime::createFromFormat("U.u") will have a problem if there is no decimal in the resulting number. + $newEpoch = bcsub($startEpoch , (string) $p_seconds, 6); + + $dt = DateTime::createFromFormat("U.u", $newEpoch, new DateTimeZone("UTC")); + + if ($dt === false) { + //PHP 5.3.2 problem + $dt = DateTime::createFromFormat("U", intval($newEpoch), new DateTimeZone("UTC")); + } + + return $dt; + } /* * @param DateTime startDT in UTC @@ -393,6 +414,43 @@ class Application_Model_Scheduler return $nextDT; } + + /* + * @param int $showInstance + * This function recalculates the start/end times of items in a gapless show to + * account for crossfade durations. + */ + private function calculateCrossfades($showInstance) + { + Logging::info("adjusting start, end times of scheduled items to account for crossfades show instance #".$showInstance); + + $instance = CcShowInstancesQuery::create()->findPK($showInstance, $this->con); + if (is_null($instance)) { + throw new OutDatedScheduleException(_("The schedule you're viewing is out of date!")); + } + + $itemStartDT = $instance->getDbStarts(null); + $itemEndDT = null; + + $schedule = CcScheduleQuery::create() + ->filterByDbInstanceId($showInstance) + ->orderByDbStarts() + ->find($this->con); + + foreach ($schedule as $item) { + + $itemEndDT = $item->getDbEnds(null); + + $item + ->setDbStarts($itemStartDT) + ->setDbEnds($itemEndDT); + + $itemStartDT = $this->findTimeDifference($itemEndDT, $this->crossfadeDuration); + $itemEndDT = $this->findEndTime($itemStartDT, $item->getDbClipLength()); + } + + $schedule->save($this->con); + } /* * @param int $showInstance @@ -648,6 +706,8 @@ class Application_Model_Scheduler $pend = microtime(true); Logging::debug("adjusting all following items."); Logging::debug(floatval($pend) - floatval($pstart)); + + $this->calculateCrossfades($instance->getDbId()); } }//for each instance @@ -929,6 +989,7 @@ class Application_Model_Scheduler foreach ($showInstances as $instance) { $this->removeGaps($instance); + $this->calculateCrossfades($instance); } } diff --git a/airtime_mvc/application/views/scripts/form/preferences_general.phtml b/airtime_mvc/application/views/scripts/form/preferences_general.phtml index 85582411c..a438fb446 100644 --- a/airtime_mvc/application/views/scripts/form/preferences_general.phtml +++ b/airtime_mvc/application/views/scripts/form/preferences_general.phtml @@ -40,6 +40,19 @@ +
+ +
+
+ element->getElement('stationDefaultCrossfadeDuration') ?> + element->getElement('stationDefaultCrossfadeDuration')->hasErrors()) : ?> + + +