diff --git a/airtime_mvc/application/common/ProvisioningHelper.php b/airtime_mvc/application/common/ProvisioningHelper.php
index 580c20e52..605617105 100644
--- a/airtime_mvc/application/common/ProvisioningHelper.php
+++ b/airtime_mvc/application/common/ProvisioningHelper.php
@@ -10,7 +10,7 @@ class ProvisioningHelper
// Parameter values
private $dbuser, $dbpass, $dbname, $dbhost, $dbowner, $apikey;
private $instanceId;
- private $station_name, $description;
+ private $stationName, $description;
public function __construct($apikey)
{
@@ -40,18 +40,14 @@ class ProvisioningHelper
if ($this->dbhost && !empty($this->dbhost)) {
$this->setNewDatabaseConnection();
- //if ($this->checkDatabaseExists()) {
- // throw new Exception("ERROR: Airtime database already exists");
- //}
-
if (!$this->checkDatabaseExists()) {
- throw new Exception("ERROR: $this->dbname database does not exist.");
+ throw new DatabaseDoesNotExistException("ERROR: $this->dbname database does not exist.");
}
//We really want to do this check because all the Propel-generated SQL starts with "DROP TABLE IF EXISTS".
//If we don't check, then a second call to this API endpoint would wipe all the tables!
if ($this->checkTablesExist()) {
- throw new Exception("ERROR: airtime tables already exists");
+ throw new DatabaseAlreadyExistsException();
}
$this->createDatabaseTables();
@@ -63,11 +59,19 @@ class ProvisioningHelper
//All we need to do is create the database tables.
$this->initializePrefs();
- } catch (Exception $e) {
+ } catch (DatabaseDoesNotExistException $e) {
http_response_code(400);
Logging::error($e->getMessage());
echo $e->getMessage() . PHP_EOL;
return;
+ } catch (DatabaseAlreadyExistsException $e) {
+ // When we recreate a terminated instance, the process will fail
+ // if we return a 40x response here. In order to circumvent this,
+ // just return a 200; we still avoid dropping the existing tables
+ http_response_code(200);
+ Logging::info($e->getMessage());
+ echo $e->getMessage() . PHP_EOL;
+ return;
}
http_response_code(201);
@@ -108,7 +112,7 @@ class ProvisioningHelper
$this->dbowner = $_POST['dbowner'];
$this->instanceId = $_POST['instanceid'];
- $this->station_name = $_POST['station_name'];
+ $this->stationName = $_POST['station_name'];
$this->description = $_POST['description'];
}
@@ -194,8 +198,8 @@ class ProvisioningHelper
* Initialize preference values passed from the dashboard (if any exist)
*/
private function initializePrefs() {
- if ($this->station_name) {
- Application_Model_Preference::SetStationName($this->station_name);
+ if ($this->stationName) {
+ Application_Model_Preference::SetStationName($this->stationName);
}
if ($this->description) {
Application_Model_Preference::SetStationDescription($this->description);
@@ -203,3 +207,14 @@ class ProvisioningHelper
}
}
+
+class DatabaseAlreadyExistsException extends Exception {
+ private static $_defaultMessage = "ERROR: airtime tables already exists";
+ public function __construct($message = null, $code = 0, Exception $previous = null) {
+ $message = _((is_null($message) ? self::$_defaultMessage : $message));
+ parent::__construct($message, $code, $previous);
+ }
+}
+
+class DatabaseDoesNotExistException extends Exception {}
+
diff --git a/airtime_mvc/application/common/TuneIn.php b/airtime_mvc/application/common/TuneIn.php
new file mode 100644
index 000000000..6040fb184
--- /dev/null
+++ b/airtime_mvc/application/common/TuneIn.php
@@ -0,0 +1,48 @@
+setLastPlayedTime($now);
+
+ // Push metadata to TuneIn
+ if (Application_Model_Preference::getTuneinEnabled()) {
+ $filePropelOrm = $file->getPropelOrm();
+ $title = urlencode($filePropelOrm->getDbTrackTitle());
+ $artist = urlencode($filePropelOrm->getDbArtistName());
+ Application_Common_TuneIn::sendMetadataToTunein($title, $artist);
+ }
}
} else {
// webstream
diff --git a/airtime_mvc/application/controllers/PreferenceController.php b/airtime_mvc/application/controllers/PreferenceController.php
index 2de1529c8..741125422 100644
--- a/airtime_mvc/application/controllers/PreferenceController.php
+++ b/airtime_mvc/application/controllers/PreferenceController.php
@@ -57,14 +57,19 @@ class PreferenceController extends Zend_Controller_Action
Application_Model_Preference::SetStationLogo($imagePath);
}
- Application_Model_Preference::SetUploadToSoundcloudOption($values["UploadToSoundcloudOption"]);
+ Application_Model_Preference::setTuneinEnabled($values["enable_tunein"]);
+ Application_Model_Preference::setTuneinStationId($values["tunein_station_id"]);
+ Application_Model_Preference::setTuneinPartnerKey($values["tunein_partner_key"]);
+ Application_Model_Preference::setTuneinPartnerId($values["tunein_partner_id"]);
+
+ /*Application_Model_Preference::SetUploadToSoundcloudOption($values["UploadToSoundcloudOption"]);
Application_Model_Preference::SetSoundCloudDownloadbleOption($values["SoundCloudDownloadbleOption"]);
Application_Model_Preference::SetSoundCloudUser($values["SoundCloudUser"]);
Application_Model_Preference::SetSoundCloudPassword($values["SoundCloudPassword"]);
Application_Model_Preference::SetSoundCloudTags($values["SoundCloudTags"]);
Application_Model_Preference::SetSoundCloudGenre($values["SoundCloudGenre"]);
Application_Model_Preference::SetSoundCloudTrackType($values["SoundCloudTrackType"]);
- Application_Model_Preference::SetSoundCloudLicense($values["SoundCloudLicense"]);
+ Application_Model_Preference::SetSoundCloudLicense($values["SoundCloudLicense"]);*/
$this->view->statusMsg = "
". _("Preferences updated.")."
";
$this->view->form = $form;
@@ -183,9 +188,14 @@ class PreferenceController extends Zend_Controller_Action
$num_of_stream = intval(Application_Model_Preference::GetNumOfStreams());
$form = new Application_Form_StreamSetting();
- $form->addElement('hash', 'csrf', array(
- 'salt' => 'unique'
- ));
+ // $form->addElement('hash', 'csrf', array(
+ // 'salt' => 'unique'
+ // ));
+
+ $csrf_namespace = new Zend_Session_Namespace('csrf_namespace');
+ $csrf_element = new Zend_Form_Element_Hidden('csrf');
+ $csrf_element->setValue($csrf_namespace->authtoken)->setRequired('true')->removeDecorator('HtmlTag')->removeDecorator('Label');
+ $form->addElement($csrf_element);
$form->setSetting($setting);
$form->startFrom();
@@ -465,4 +475,69 @@ class PreferenceController extends Zend_Controller_Action
}
$this->_helper->json->sendJson($out);
}
+
+ public function deleteAllFilesAction()
+ {
+ $this->view->layout()->disableLayout();
+ $this->_helper->viewRenderer->setNoRender(true);
+
+ // Only admin users should get here through ACL permissioning
+ // Only allow POST requests
+ $method = $_SERVER['REQUEST_METHOD'];
+ if (!($method == 'POST')) {
+ $this->getResponse()
+ ->setHttpResponseCode(405)
+ ->appendBody(_("Request method not accepted") . ": $method");
+ return;
+ }
+
+ $user = Application_Model_User::getCurrentUser();
+ $playlists = $blocks = $streams = [];
+
+ $allPlaylists = CcPlaylistQuery::create()->find();
+ foreach ($allPlaylists as $p) {
+ $playlists[] = $p->getDbId();
+ }
+
+ $allBlocks = CcBlockQuery::create()->find();
+ foreach ($allBlocks as $b) {
+ $blocks[] = $b->getDbId();
+ }
+
+ $allStreams = CcWebstreamQuery::create()->find();
+ foreach ($allStreams as $s) {
+ $streams[] = $s->getDbId();
+ }
+
+ // Delete all playlists, blocks, and streams
+ Application_Model_Playlist::deletePlaylists($playlists, $user->getId());
+ Application_Model_Block::deleteBlocks($blocks, $user->getId());
+ Application_Model_Webstream::deleteStreams($streams, $user->getId());
+
+ try {
+ // Delete all the cloud files
+ $CC_CONFIG = Config::getConfig();
+
+ foreach ($CC_CONFIG["supportedStorageBackends"] as $storageBackend) {
+ $proxyStorageBackend = new ProxyStorageBackend($storageBackend);
+ $proxyStorageBackend->deleteAllCloudFileObjects();
+ }
+ } catch(Exception $e) {
+ Logging::info($e->getMessage());
+ }
+
+ // Delete all files from the database
+ $files = CcFilesQuery::create()->find();
+ foreach ($files as $file) {
+ $storedFile = new Application_Model_StoredFile($file, null);
+ // Delete the files quietly to avoid getting Sentry errors for
+ // every S3 file we delete.
+ $storedFile->delete(true);
+ }
+
+ $this->getResponse()
+ ->setHttpResponseCode(200)
+ ->appendBody("OK");
+ }
+
}
diff --git a/airtime_mvc/application/controllers/ProvisioningController.php b/airtime_mvc/application/controllers/ProvisioningController.php
index cda59e0db..06ee7a2ab 100644
--- a/airtime_mvc/application/controllers/ProvisioningController.php
+++ b/airtime_mvc/application/controllers/ProvisioningController.php
@@ -57,13 +57,16 @@ class ProvisioningController extends Zend_Controller_Action
/**
* Delete the Airtime Pro station's files from Amazon S3
+ *
+ * FIXME: When we deploy this next time, we should ensure that
+ * this function can only be accessed with POST requests!
*/
public function terminateAction()
{
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
- if (!RestAuth::verifyAuth(true, true, $this)) {
+ if (!RestAuth::verifyAuth(true, false, $this)) {
return;
}
diff --git a/airtime_mvc/application/controllers/ScheduleController.php b/airtime_mvc/application/controllers/ScheduleController.php
index d8d0f1f42..8d7aa0587 100644
--- a/airtime_mvc/application/controllers/ScheduleController.php
+++ b/airtime_mvc/application/controllers/ScheduleController.php
@@ -1,4 +1,5 @@
setDecorators(array(
+ array('ViewScript', array('viewScript' => 'form/preferences_danger.phtml'))
+ ));
+
+ $clearLibrary = new Zend_Form_Element_Button('clear_library');
+ $clearLibrary->setLabel(_('Delete All Tracks in Library'));
+ //$submit->removeDecorator('Label');
+ $clearLibrary->setAttribs(array('class'=>'btn centered'));
+ $clearLibrary->setAttrib('onclick', 'deleteAllFiles();');
+ $clearLibrary->removeDecorator('DtDdWrapper');
+
+ $this->addElement($clearLibrary);
+ }
+
+}
diff --git a/airtime_mvc/application/forms/Preferences.php b/airtime_mvc/application/forms/Preferences.php
index 3e5158413..d410ed3c6 100644
--- a/airtime_mvc/application/forms/Preferences.php
+++ b/airtime_mvc/application/forms/Preferences.php
@@ -12,18 +12,30 @@ class Application_Form_Preferences extends Zend_Form
$general_pref = new Application_Form_GeneralPreferences();
- $this->addElement('hash', 'csrf', array(
- 'salt' => 'unique',
- 'decorators' => array(
- 'ViewHelper'
- )
- ));
+ // $this->addElement('hash', 'csrf', array(
+ // 'salt' => 'unique',
+ // 'decorators' => array(
+ // 'ViewHelper'
+ // )
+ // ));
+
+ $csrf_namespace = new Zend_Session_Namespace('csrf_namespace');
+ $csrf_element = new Zend_Form_Element_Hidden('csrf');
+ $csrf_element->setValue($csrf_namespace->authtoken)->setRequired('true')->removeDecorator('HtmlTag')->removeDecorator('Label');
+ $this->addElement($csrf_element);
$this->addSubForm($general_pref, 'preferences_general');
+ //tunein form
+ $tuneinPreferences = new Application_Form_TuneInPreferences();
+ $this->addSubForm($tuneinPreferences, 'preferences_tunein');
+
$soundcloud_pref = new Application_Form_SoundcloudPreferences();
$this->addSubForm($soundcloud_pref, 'preferences_soundcloud');
+ $danger_pref = new Application_Form_DangerousPreferences();
+ $this->addSubForm($danger_pref, 'preferences_danger');
+
$submit = new Zend_Form_Element_Submit('submit');
$submit->setLabel(_('Save'));
//$submit->removeDecorator('Label');
diff --git a/airtime_mvc/application/forms/TuneInPreferences.php b/airtime_mvc/application/forms/TuneInPreferences.php
new file mode 100644
index 000000000..7eee0d56f
--- /dev/null
+++ b/airtime_mvc/application/forms/TuneInPreferences.php
@@ -0,0 +1,144 @@
+setDecorators(array(
+ array('ViewScript', array('viewScript' => 'form/preferences_tunein.phtml'))
+ ));
+
+ $enableTunein = new Zend_Form_Element_Checkbox("enable_tunein");
+ $enableTunein->setDecorators(array(
+ 'ViewHelper',
+ 'Errors',
+ 'Label'
+ ));
+ $enableTunein->addDecorator('Label', array('class' => 'enable-tunein'));
+ $enableTunein->setLabel(_("Push metadata to your station on TuneIn?"));
+ $enableTunein->setValue(Application_Model_Preference::getTuneinEnabled());
+ $enableTunein->setAttrib("class", "block-display");
+ $this->addElement($enableTunein);
+
+ $tuneinStationId = new Zend_Form_Element_Text("tunein_station_id");
+ $tuneinStationId->setLabel(_("Station ID:"));
+ $tuneinStationId->setValue(Application_Model_Preference::getTuneinStationId());
+ $tuneinStationId->setAttrib("class", "input_text");
+ $this->addElement($tuneinStationId);
+
+ $tuneinPartnerKey = new Zend_Form_Element_Text("tunein_partner_key");
+ $tuneinPartnerKey->setLabel(_("Partner Key:"));
+ $tuneinPartnerKey->setValue(Application_Model_Preference::getTuneinPartnerKey());
+ $tuneinPartnerKey->setAttrib("class", "input_text");
+ $this->addElement($tuneinPartnerKey);
+
+ $tuneinPartnerId = new Zend_Form_Element_Text("tunein_partner_id");
+ $tuneinPartnerId->setLabel(_("Partner Id:"));
+ $tuneinPartnerId->setValue(Application_Model_Preference::getTuneinPartnerId());
+ $tuneinPartnerId->setAttrib("class", "input_text");
+ $this->addElement($tuneinPartnerId);
+ }
+
+ public function isValid($data)
+ {
+ $valid = true;
+ // Make request to TuneIn API to test the settings are valid.
+ // TuneIn does not have an API to make test requests to check if
+ // the credentials are correct. Therefore we will make a request
+ // with the commercial flag set to true, which removes the metadata
+ // from the station on TuneIn. After that, and if the test request
+ // succeeds, we will make another request with the real metadata.
+ if ($data["enable_tunein"]) {
+ $credentialsQryStr = "?partnerId=".$data["tunein_partner_id"]."&partnerKey=".$data["tunein_partner_key"]."&id=".$data["tunein_station_id"];
+ $commercialFlagQryStr = "&commercial=true";
+
+ $metadata = Application_Model_Schedule::getCurrentPlayingTrack();
+
+ if (is_null($metadata)) {
+ $qryStr = $credentialsQryStr . $commercialFlagQryStr;
+ } else {
+ $metadata["artist"] = empty($metadata["artist"]) ? "n/a" : $metadata["artist"];
+ $metadata["title"] = empty($metadata["title"]) ? "n/a" : $metadata["title"];
+ $metadataQryStr = "&artist=" . $metadata["artist"] . "&title=" . $metadata["title"];
+
+ $qryStr = $credentialsQryStr . $metadataQryStr;
+ }
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, TUNEIN_API_URL . $qryStr);
+ curl_setopt($ch, CURLOPT_FAILONERROR, 1);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+
+ $xmlData = curl_exec($ch);
+ if (curl_error($ch)) {
+ Logging::error("Failed to reach TuneIn: ". curl_errno($ch)." - ". curl_error($ch) . " - " . curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
+ if (curl_error($ch) == "The requested URL returned error: 403 Forbidden") {
+ $this->getElement("enable_tunein")->setErrors(array(_("Invalid TuneIn Settings. Please ensure your TuneIn settings are correct and try again.")));
+
+ $valid = false;
+ }
+ }
+ curl_close($ch);
+
+ if ($valid) {
+ $xmlObj = new SimpleXMLElement($xmlData);
+ if (!$xmlObj || $xmlObj->head->status != "200") {
+ $valid = false;
+ } else if ($xmlObj->head->status == "200") {
+ $valid = true;
+
+ // Make another request to TuneIn to update the metadata right away
+ // and to turn off the commercial flag.
+
+ /*$metadata = Application_Model_Schedule::getCurrentPlayingTrack();
+
+ if (!is_null($metadata)) {
+
+ Logging::info($metadata);
+ // Replace empty strings with "n/a" since the TuneIn API will complain
+ // and return an error that title and/or artist is not set.
+ $metadata["artist"] = empty($metadata["artist"]) ? "n/a" : $metadata["artist"];
+ $metadata["title"] = empty($metadata["title"]) ? "n/a" : $metadata["title"];
+ Logging::info($metadata);
+
+ $metadataQryStr = "&artist=" . $metadata["artist"] . "&title=" . $metadata["title"];
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, TUNEIN_API_URL . $qry_str . "&commercial=false" . $metadataQryStr);
+ curl_setopt($ch, CURLOPT_FAILONERROR, 1);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+
+ $xmlData = curl_exec($ch);
+ Logging::info($xmlData);
+ if (curl_error($ch)) {
+ Logging::error("Failed to reach TuneIn: " . curl_errno($ch) . " - " . curl_error($ch) . " - " . curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
+ }
+
+ curl_close($ch);
+ $xmlObj = new SimpleXMLElement($xmlData);
+ if (!$xmlObj || $xmlObj->head->status != "200") {
+ Logging::error("Failed updating metadata on TuneIn");
+ }
+ }*/
+
+ }
+ }
+ } else {
+ $valid = true;
+ }
+
+ if (!$valid) {
+ // Set values to what the user entered since the form is invalid so they
+ // don't have to enter in the values again and can see what they entered.
+ $this->getElement("enable_tunein")->setValue($data["enable_tunein"]);
+ $this->getElement("tunein_partner_key")->setValue($data["tunein_partner_key"]);
+ $this->getElement("tunein_partner_id")->setValue($data["tunein_partner_id"]);
+ $this->getElement("tunein_station_id")->setValue($data["tunein_station_id"]);
+ }
+
+ return $valid;
+ }
+}
diff --git a/airtime_mvc/application/models/Preference.php b/airtime_mvc/application/models/Preference.php
index 64263b94c..1387d326b 100644
--- a/airtime_mvc/application/models/Preference.php
+++ b/airtime_mvc/application/models/Preference.php
@@ -1453,4 +1453,44 @@ class Application_Model_Preference
{
return self::getValue("provisioning_status");
}
+
+ public static function setTuneinEnabled($value)
+ {
+ self::setValue("tunein_enabled", $value);
+ }
+
+ public static function getTuneinEnabled()
+ {
+ return self::getValue("tunein_enabled");
+ }
+
+ public static function setTuneinPartnerKey($value)
+ {
+ self::setValue("tunein_partner_key", $value);
+ }
+
+ public static function getTuneinPartnerKey()
+ {
+ return self::getValue("tunein_partner_key");
+ }
+
+ public static function setTuneinPartnerId($value)
+ {
+ self::setValue("tunein_partner_id", $value);
+ }
+
+ public static function getTuneinPartnerId()
+ {
+ return self::getValue("tunein_partner_id");
+ }
+
+ public static function setTuneinStationId($value)
+ {
+ self::setValue("tunein_station_id", $value);
+ }
+
+ public static function getTuneinStationId()
+ {
+ return self::getValue("tunein_station_id");
+ }
}
diff --git a/airtime_mvc/application/models/RabbitMq.php b/airtime_mvc/application/models/RabbitMq.php
index 5daf227a2..fa05f3986 100644
--- a/airtime_mvc/application/models/RabbitMq.php
+++ b/airtime_mvc/application/models/RabbitMq.php
@@ -112,12 +112,7 @@ class Application_Model_RabbitMq
$data['original_filename'] = $originalFilename;
$data['callback_url'] = $callbackUrl;
$data['api_key'] = $apiKey;
- // Pass station name to the analyzer so we can set it with the file's
- // metadata before uploading it to the cloud. This isn't a requirement
- // for cloud storage, but put there as a safeguard, since all Airtime
- // Pro stations will share the same bucket.
- $data['station_domain'] = $stationDomain = Application_Model_Preference::GetStationName();
-
+
// We add a prefix to the resource name so files are not all placed
// under the root folder. We do this in case we need to restore a
// customer's file/s; File restoration is done via the S3 Browser
diff --git a/airtime_mvc/application/models/Schedule.php b/airtime_mvc/application/models/Schedule.php
index 2993dc03d..66d00661b 100644
--- a/airtime_mvc/application/models/Schedule.php
+++ b/airtime_mvc/application/models/Schedule.php
@@ -56,6 +56,29 @@ SQL;
return $real_streams;
}
+
+ /**
+ * Returns an array with 2 elements: artist and title name of the track that is currently playing.
+ * Elements will be set to null if metadata is not set for those fields.
+ *
+ * Returns null if no track is currently playing.
+ *
+ * Data is based on GetPlayOrderRange() in this class.
+ */
+ public static function getCurrentPlayingTrack()
+ {
+ $currentScheduleInfo = self::GetPlayOrderRange();
+ if (empty($currentScheduleInfo["tracks"]["current"])) {
+ return null;
+ }
+
+ $currentTrackArray = explode(" - ", $currentScheduleInfo["tracks"]["current"]["name"]);
+ $currentTrackMetadata = array(
+ "artist" => empty($currentTrackArray[0]) ? null : urlencode($currentTrackArray[0]),
+ "title" => empty($currentTrackArray[1]) ? null : urlencode($currentTrackArray[1])
+ );
+ return $currentTrackMetadata;
+ }
/**
* Returns data related to the scheduled items.
diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php
index 8e3dd7a59..32d6ec371 100644
--- a/airtime_mvc/application/models/StoredFile.php
+++ b/airtime_mvc/application/models/StoredFile.php
@@ -375,7 +375,7 @@ SQL;
* Deletes the physical file from the local file system or from the cloud
*
*/
- public function delete()
+ public function delete($quiet=false)
{
// Check if the file is scheduled to be played in the future
if (Application_Model_Schedule::IsFileScheduledInTheFuture($this->_file->getCcFileId())) {
@@ -405,8 +405,12 @@ SQL;
}
catch (Exception $e)
{
- //Just log the exception and continue.
- Logging::error($e);
+ if ($quiet) {
+ Logging::info($e);
+ } else {
+ //Just log the exception and continue.
+ Logging::error($e);
+ }
}
}
diff --git a/airtime_mvc/application/views/scripts/form/preferences.phtml b/airtime_mvc/application/views/scripts/form/preferences.phtml
index 0ffe1ea9d..d200bf627 100644
--- a/airtime_mvc/application/views/scripts/form/preferences.phtml
+++ b/airtime_mvc/application/views/scripts/form/preferences.phtml
@@ -2,8 +2,22 @@
element->getElement('csrf') ?>
element->getSubform('preferences_general') ?>
+
+
+
+ element->getSubform('preferences_tunein') ?>
+
+
+
+
+
+ element->getSubform('preferences_danger') ?>
+
+
+
+
element->submit->render() ?>
diff --git a/airtime_mvc/application/views/scripts/form/preferences_danger.phtml b/airtime_mvc/application/views/scripts/form/preferences_danger.phtml
new file mode 100644
index 000000000..7ea8a78d1
--- /dev/null
+++ b/airtime_mvc/application/views/scripts/form/preferences_danger.phtml
@@ -0,0 +1,14 @@
+
diff --git a/airtime_mvc/application/views/scripts/form/preferences_tunein.phtml b/airtime_mvc/application/views/scripts/form/preferences_tunein.phtml
new file mode 100644
index 000000000..d5fd34dd5
--- /dev/null
+++ b/airtime_mvc/application/views/scripts/form/preferences_tunein.phtml
@@ -0,0 +1,18 @@
+
\ No newline at end of file
diff --git a/airtime_mvc/public/css/styles.css b/airtime_mvc/public/css/styles.css
index b80cbfe8e..4331af511 100644
--- a/airtime_mvc/public/css/styles.css
+++ b/airtime_mvc/public/css/styles.css
@@ -1788,7 +1788,7 @@ ul.errors {
width:278px;
}
-ul.errors li {
+ul.errors li, .warning {
color:#902d2d;
font-size:11px;
padding:2px 4px;
@@ -1798,6 +1798,11 @@ ul.errors li {
list-style: none;
}
+.warning-label {
+ font-size: medium;
+ text-align: center;
+}
+
div.success{
color:#3B5323;
font-size:11px;
@@ -2255,14 +2260,9 @@ dd.radio-inline-list, .preferences dd.radio-inline-list, .stream-config dd.radio
.radio-inline-list label {
margin-right:12px;
}
-.preferences.simple-formblock dd.block-display {
- width: 100%;
-}
-
-.preferences.simple-formblock dd.block-display select, .stream-config.simple-formblock dd.block-display select {
- width: 100%;
-}
-.preferences dd.block-display .input_select, .stream-config dd.block-display .input_select {
+.preferences.simple-formblock dd.block-display,
+ .preferences.simple-formblock dd.block-display select, .stream-config.simple-formblock dd.block-display select,
+ .preferences dd.block-display .input_select, .stream-config dd.block-display .input_select {
width: 100%;
}
.preferences dd.block-display .input_text_area, .preferences dd.block-display .input_text
@@ -2284,6 +2284,15 @@ dd.radio-inline-list, .preferences dd.radio-inline-list, .stream-config dd.radio
margin-bottom: 4px;
}
+.preferences #Logo-img-container {
+ margin-top: 30px;
+}
+
+.centered {
+ margin: 0 auto;
+ display: block;
+}
+
#show_time_info {
font-size:12px;
height:30px;
@@ -3248,3 +3257,7 @@ dd .stream-status {
padding-bottom: 0px;
padding-top: 13px;
}
+
+.enable-tunein {
+ font-weight:bold;
+}
diff --git a/airtime_mvc/public/js/airtime/preferences/preferences.js b/airtime_mvc/public/js/airtime/preferences/preferences.js
index 1dffe24d2..252a64a99 100644
--- a/airtime_mvc/public/js/airtime/preferences/preferences.js
+++ b/airtime_mvc/public/js/airtime/preferences/preferences.js
@@ -1,18 +1,13 @@
function showErrorSections() {
- if($("#soundcloud-settings .errors").length > 0) {
- $("#soundcloud-settings").show();
- $(window).scrollTop($("#soundcloud-settings .errors").position().top);
- }
-
- if($("#email-server-settings .errors").length > 0) {
- $("#email-server-settings").show();
- $(window).scrollTop($("#email-server-settings .errors").position().top);
- }
-
- if($("#livestream-settings .errors").length > 0) {
- $("#livestream-settings").show();
- $(window).scrollTop($("#livestream-settings .errors").position().top);
- }
+ var selector = $("[id$=-settings]");
+ selector.each(function(i) {
+ var el = $(this);
+ var errors = el.find(".errors");
+ if (errors.length > 0) {
+ el.show();
+ $(window).scrollTop(errors.position().top);
+ }
+ });
}
function setConfigureMailServerListener() {
@@ -63,6 +58,30 @@ function setMailServerInputReadonly() {
setMsAuthenticationFieldsReadonly(requiresAuthCB);
}
+function setTuneInSettingsListener() {
+ var enableTunein = $("#enable_tunein");
+ enableTunein.click(function(event){
+ setTuneInSettingsReadonly();
+ });
+}
+
+function setTuneInSettingsReadonly() {
+ var enableTunein = $("#enable_tunein");
+ var stationId = $("#tunein_station_id");
+ var partnerKey = $("#tunein_partner_key");
+ var partnerId = $("#tunein_partner_id");
+
+ if (enableTunein.is(':checked')) {
+ stationId.removeAttr("readonly");
+ partnerKey.removeAttr("readonly");
+ partnerId.removeAttr("readonly");
+ } else {
+ stationId.attr("readonly", "readonly");
+ partnerKey.attr("readonly", "readonly");
+ partnerId.attr("readonly", "readonly");
+ }
+}
+
/*
* Enable/disable mail server authentication fields
*/
@@ -120,6 +139,14 @@ function removeLogo() {
location.reload();
}
+function deleteAllFiles() {
+ var resp = confirm($.i18n._("Are you sure you want to delete all the tracks in your library?"))
+ if (resp) {
+ $.post(baseUrl+'Preference/delete-all-files', function(json){});
+ location.reload();
+ }
+}
+
$(document).ready(function() {
$('.collapsible-header').live('click',function() {
@@ -128,6 +155,10 @@ $(document).ready(function() {
return false;
}).next().hide();
+ if ($("#tunein-settings").find(".errors").length > 0) {
+ $(".collapsible-content#tunein-settings").show();
+ }
+
/* No longer using AJAX for this form. Zend + our code makes it needlessly hard to deal with. -- Albert
$('#pref_save').live('click', function() {
var data = $('#pref_form').serialize();
@@ -151,4 +182,6 @@ $(document).ready(function() {
setConfigureMailServerListener();
setEnableSystemEmailsListener();
setCollapsibleWidgetJsCode();
+ setTuneInSettingsReadonly();
+ setTuneInSettingsListener();
});
diff --git a/python_apps/pypo/liquidsoap_scripts/ls_script.liq b/python_apps/pypo/liquidsoap_scripts/ls_script.liq
index ccc3a0776..fb3452181 100644
--- a/python_apps/pypo/liquidsoap_scripts/ls_script.liq
+++ b/python_apps/pypo/liquidsoap_scripts/ls_script.liq
@@ -249,6 +249,7 @@ s = if dj_live_stream_port != 0 and dj_live_stream_mp != "" then
on_connect=live_dj_connect,
on_disconnect=live_dj_disconnect))
+ dj_live = on_metadata(notify_queue, dj_live)
ignore(output.dummy(dj_live, fallible=true))
switch(id="show_schedule_noise_switch",
@@ -271,6 +272,7 @@ s = if master_live_stream_port != 0 and master_live_stream_mp != "" then
on_connect=master_dj_connect,
on_disconnect=master_dj_disconnect))
+ master_dj = on_metadata(notify_queue, master_dj)
ignore(output.dummy(master_dj, fallible=true))
switch(id="master_show_schedule_noise_switch",
@@ -282,6 +284,8 @@ else
s
end
+# Send metadata notifications when using master source
+s = on_metadata(notify_queue, s)
# Attach a skip command to the source s:
#add_skip_command(s)