diff --git a/airtime_mvc/application/Bootstrap.php b/airtime_mvc/application/Bootstrap.php
index 62679c8b0..ee3bb7096 100644
--- a/airtime_mvc/application/Bootstrap.php
+++ b/airtime_mvc/application/Bootstrap.php
@@ -34,7 +34,13 @@ $front->registerPlugin(new RabbitMqPlugin());
//localization configuration
$codeset = 'UTF-8';
-$lang = Application_Model_Preference::GetLocale().'.'.$codeset;
+$auth = Zend_Auth::getInstance();
+if ($auth->hasIdentity()) {
+ $id = $auth->getIdentity()->id;
+ $lang = Application_Model_Preference::GetCurrentUserLocale($id).'.'.$codeset;
+} else {
+ $lang = Application_Model_Preference::GetLocale().'.'.$codeset;
+}
putenv("LC_ALL=$lang");
putenv("LANG=$lang");
diff --git a/airtime_mvc/application/controllers/UserController.php b/airtime_mvc/application/controllers/UserController.php
index d5ee57e2f..e2f6fcfae 100644
--- a/airtime_mvc/application/controllers/UserController.php
+++ b/airtime_mvc/application/controllers/UserController.php
@@ -72,6 +72,11 @@ class UserController extends Zend_Controller_Action
$user->setJabber($formData['jabber']);
$user->save();
+ // Language settings are saved on a per-user basis
+ // By default, the general language setting on preferences
+ // page is what gets assigned.
+ Application_Model_Preference::SetUserLocale($user->getId());
+
$form->reset();
$this->view->form = $form;
@@ -150,6 +155,7 @@ class UserController extends Zend_Controller_Action
$user->setSkype($formData['cu_skype']);
$user->setJabber($formData['cu_jabber']);
$user->save();
+ Application_Model_Preference::SetUserLocale($user->getId(), $formData['cu_locale']);
$this->view->successMessage = "
"._("User updated successfully!")."
";
}
$this->view->form = $form;
diff --git a/airtime_mvc/application/forms/EditUser.php b/airtime_mvc/application/forms/EditUser.php
index b4906b9e7..c775eb023 100644
--- a/airtime_mvc/application/forms/EditUser.php
+++ b/airtime_mvc/application/forms/EditUser.php
@@ -29,6 +29,7 @@ class Application_Form_EditUser extends Zend_Form
$login->setLabel(_('Username:'));
$login->setValue($userData["login"]);
$login->setAttrib('class', 'input_text');
+ $login->setAttrib('readonly', 'readonly');
$login->setRequired(true);
$login->addValidator($notEmptyValidator);
$login->addFilter('StringTrim');
@@ -96,6 +97,12 @@ class Application_Form_EditUser extends Zend_Form
$jabber->setDecorators(array('viewHelper'));
$this->addElement($jabber);
+ $locale = new Zend_Form_Element_Select("cu_locale");
+ $locale->setLabel(_("Language"));
+ $locale->setMultiOptions(Application_Model_Locale::getLocales());
+ $locale->setValue(Application_Model_Preference::GetUserLocale($currentUser->getId()));
+ $locale->setDecorators(array('ViewHelper'));
+ $this->addElement($locale);
/*
$saveBtn = new Zend_Form_Element_Button('cu_save_user');
$saveBtn->setAttrib('class', 'btn btn-small right-floated');
diff --git a/airtime_mvc/application/forms/StreamSettingSubForm.php b/airtime_mvc/application/forms/StreamSettingSubForm.php
index c5d8a19b2..eea40d8a7 100644
--- a/airtime_mvc/application/forms/StreamSettingSubForm.php
+++ b/airtime_mvc/application/forms/StreamSettingSubForm.php
@@ -190,6 +190,30 @@ class Application_Form_StreamSettingSubForm extends Zend_Form_SubForm
}
$user->setAttrib('alt', 'regular_text');
$this->addElement($user);
+
+ $adminUser = new Zend_Form_Element_Text('admin_user');
+ $adminUser->setLabel(_("Admin User"))
+ ->setValue(Application_Model_StreamSetting::getAdminUser($prefix))
+ ->setValidators(array(
+ array('regex', false, array('/^[^ &<>]+$/', 'messages' => _('Invalid character entered')))))
+ ->setDecorators(array('ViewHelper'));
+ if ($disable_all) {
+ $adminUser->setAttrib("disabled", "disabled");
+ }
+ $adminUser->setAttrib('alt', 'regular_text');
+ $this->addElement($adminUser);
+
+ $adminPass = new Zend_Form_Element_Text('admin_pass');
+ $adminPass->setLabel(_("Admin Password"))
+ ->setValue(Application_Model_StreamSetting::getAdminPass($prefix))
+ ->setValidators(array(
+ array('regex', false, array('/^[^ &<>]+$/', 'messages' => _('Invalid character entered')))))
+ ->setDecorators(array('ViewHelper'));
+ if ($disable_all) {
+ $adminPass->setAttrib("disabled", "disabled");
+ }
+ $adminPass->setAttrib('alt', 'regular_text');
+ $this->addElement($adminPass);
$liquidsopa_error_msg = '
'._('Getting information from the server...').' ';
diff --git a/airtime_mvc/application/models/Preference.php b/airtime_mvc/application/models/Preference.php
index 326ab6bea..eef140cca 100644
--- a/airtime_mvc/application/models/Preference.php
+++ b/airtime_mvc/application/models/Preference.php
@@ -3,7 +3,12 @@
class Application_Model_Preference
{
- private static function setValue($key, $value, $isUserValue = false)
+ /**
+ *
+ * @param integer $userId is not null when we are setting a locale for a specific user
+ * @param boolean $isUserValue is true when we are setting a value for the current user
+ */
+ private static function setValue($key, $value, $isUserValue = false, $userId = null)
{
try {
//called from a daemon process
@@ -22,9 +27,12 @@ class Application_Model_Preference
$paramMap[':key'] = $key;
//For user specific preference, check if id matches as well
- if ($isUserValue) {
+ if ($isUserValue && is_null($userId)) {
$sql .= " AND subjid = :id";
$paramMap[':id'] = $id;
+ } else if (!is_null($userId)) {
+ $sql .= " AND subjid= :id";
+ $paramMap[':id'] = $userId;
}
$result = Application_Common_Database::prepareAndExecute($sql, $paramMap, 'column');
@@ -42,7 +50,11 @@ class Application_Model_Preference
$sql = "UPDATE cc_pref"
. " SET valstr = :value"
. " WHERE keystr = :key AND subjid = :id";
- $paramMap[':id'] = $id;
+ if (is_null($userId)) {
+ $paramMap[':id'] = $id;
+ } else {
+ $paramMap[':id'] = $userId;
+ }
}
} else {
// result not found
@@ -54,7 +66,11 @@ class Application_Model_Preference
// user pref
$sql = "INSERT INTO cc_pref (subjid, keystr, valstr)"
." VALUES (:id, :key, :value)";
- $paramMap[':id'] = $id;
+ if (is_null($userId)) {
+ $paramMap[':id'] = $id;
+ } else {
+ $paramMap[':id'] = $userId;
+ }
}
}
$paramMap[':key'] = $key;
@@ -428,16 +444,37 @@ class Application_Model_Preference
{
return self::getValue("timezone");
}
-
+
+ // This is the language setting on preferences page
public static function SetLocale($locale)
{
self::setValue("locale", $locale);
}
-
+
public static function GetLocale()
{
return self::getValue("locale");
}
+
+ public static function GetCurrentUserLocale($id)
+ {
+ return self::getValue("user_".$id."_locale", true);
+ }
+
+ public static function SetUserLocale($userId, $locale = null)
+ {
+ // When a new user is created they will get the default locale
+ // setting which the admin sets on preferences page
+ if (is_null($locale)) {
+ $locale = self::GetLocale();
+ }
+ self::setValue("user_".$userId."_locale", $locale, true, $userId);
+ }
+
+ public static function GetUserLocale($userId)
+ {
+ return self::getValue("user_".$userId."_locale");
+ }
public static function SetStationLogo($imagePath)
{
diff --git a/airtime_mvc/application/models/StreamSetting.php b/airtime_mvc/application/models/StreamSetting.php
index f1b1e372c..790772897 100644
--- a/airtime_mvc/application/models/StreamSetting.php
+++ b/airtime_mvc/application/models/StreamSetting.php
@@ -163,7 +163,7 @@ class Application_Model_StreamSetting
$con = Propel::getConnection();
$sql = "SELECT *"
." FROM cc_stream_setting"
- ." WHERE keyname not like '%_error'";
+ ." WHERE keyname not like '%_error' AND keyname not like '%_admin_%'";
$rows = $con->query($sql)->fetchAll();
@@ -433,4 +433,20 @@ class Application_Model_StreamSetting
{
return self::getValue("dj_live_stream_mp");
}
+
+ public static function getAdminUser($stream){
+ return self::getValue($stream."_admin_user");
+ }
+
+ public static function setAdminUser($stream, $v){
+ self::setValue($stream."_admin_user", $v, "string");
+ }
+
+ public static function getAdminPass($stream){
+ return self::getValue($stream."_admin_pass");
+ }
+
+ public static function setAdminPass($stream, $v){
+ self::setValue($stream."_admin_pass", $v, "string");
+ }
}
diff --git a/airtime_mvc/application/views/scripts/form/edit-user.phtml b/airtime_mvc/application/views/scripts/form/edit-user.phtml
index 927fd8a6d..3f0be44c3 100644
--- a/airtime_mvc/application/views/scripts/form/edit-user.phtml
+++ b/airtime_mvc/application/views/scripts/form/edit-user.phtml
@@ -114,6 +114,20 @@
+
+ element->getElement('cu_locale')->getLabel() ?>
+
+
+
+ element->getElement('cu_locale') ?>
+ element->getElement('cu_locale')->hasErrors()) : ?>
+
+ element->getElement('cu_locale')->getMessages() as $error): ?>
+
+
+
+
+
Save
diff --git a/airtime_mvc/application/views/scripts/form/stream-setting-form.phtml b/airtime_mvc/application/views/scripts/form/stream-setting-form.phtml
index 56345b839..3ed9345de 100644
--- a/airtime_mvc/application/views/scripts/form/stream-setting-form.phtml
+++ b/airtime_mvc/application/views/scripts/form/stream-setting-form.phtml
@@ -1,4 +1,4 @@
- stream_number;
?>
@@ -104,6 +104,34 @@
+
+ element->getElement('admin_user')->getLabel()?> :
+
+
+
+
+ element->getElement('admin_user')?>
+ element->getElement('admin_user')->hasErrors()) : ?>
+
+ element->getElement('admin_user')->getMessages() as $error): ?>
+
+
+
+
+
+
+ element->getElement('admin_pass')->getLabel()?> :
+
+
+ element->getElement('admin_pass')?>
+ element->getElement('admin_pass')->hasErrors()) : ?>
+
+ element->getElement('admin_pass')->getMessages() as $error): ?>
+
+
+
+
+
diff --git a/airtime_mvc/application/views/scripts/library/get-file-metadata.ajax.phtml b/airtime_mvc/application/views/scripts/library/get-file-metadata.ajax.phtml
index 0ab387ca1..4b1a38839 100644
--- a/airtime_mvc/application/views/scripts/library/get-file-metadata.ajax.phtml
+++ b/airtime_mvc/application/views/scripts/library/get-file-metadata.ajax.phtml
@@ -18,7 +18,7 @@
echo _("Isrc Number:"); ?> md["MDATA_KEY_ISRC"]);?>
echo _("Website:"); ?> md["MDATA_KEY_URL"]);?>
echo _("Language:"); ?> md["MDATA_KEY_LANGUAGE"]);?>
- echo _("File"); ?> echo _("Path:"); ?> md["MDATA_KEY_FILEPATH"]);?>
+ echo _("File Path:"); ?> md["MDATA_KEY_FILEPATH"]);?>
diff --git a/airtime_mvc/build/sql/defaultdata.sql b/airtime_mvc/build/sql/defaultdata.sql
index 704fcbb81..894a9a42e 100644
--- a/airtime_mvc/build/sql/defaultdata.sql
+++ b/airtime_mvc/build/sql/defaultdata.sql
@@ -25,6 +25,8 @@ INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_host', '1
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_port', '8000', 'integer');
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_user', '', 'string');
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_pass', 'hackme', 'string');
+INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_admin_user', '', 'string');
+INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_admin_pass', '', 'string');
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_mount', 'airtime_128', 'string');
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_url', 'http://airtime.sourcefabric.org', 'string');
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_description', 'Airtime Radio! Stream #1', 'string');
@@ -38,6 +40,8 @@ INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s2_host', ''
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s2_port', '', 'integer');
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s2_user', '', 'string');
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s2_pass', '', 'string');
+INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s2_admin_user', '', 'string');
+INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s2_admin_pass', '', 'string');
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s2_mount', '', 'string');
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s2_url', '', 'string');
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s2_description', '', 'string');
@@ -51,6 +55,8 @@ INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s3_host', ''
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s3_port', '', 'integer');
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s3_user', '', 'string');
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s3_pass', '', 'string');
+INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s3_admin_user', '', 'string');
+INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s3_admin_pass', '', 'string');
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s3_mount', '', 'string');
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s3_url', '', 'string');
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s3_description', '', 'string');
@@ -313,6 +319,8 @@ INSERT INTO cc_stream_setting (keyname, value, type) VALUES ('s3_channels', 'ste
-- added in 2.3
INSERT INTO cc_pref("keystr", "valstr") VALUES('locale', 'en_CA');
+INSERT INTO cc_pref("subjid", "keystr", "valstr") VALUES(1, 'user_1_locale', 'en_CA');
+
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('zh_CN', 'Chinese');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('en_CA', 'English');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('en_US', 'English - US');
diff --git a/airtime_mvc/public/css/styles.css b/airtime_mvc/public/css/styles.css
index 60145e306..e1d0fe90a 100644
--- a/airtime_mvc/public/css/styles.css
+++ b/airtime_mvc/public/css/styles.css
@@ -109,7 +109,8 @@ select {
}
.airtime_auth_help_icon, .custom_auth_help_icon, .stream_username_help_icon,
-.playlist_type_help_icon, .master_username_help_icon, .repeat_tracks_help_icon{
+.playlist_type_help_icon, .master_username_help_icon, .repeat_tracks_help_icon,
+.admin_username_help_icon {
cursor: help;
position: relative;
display:inline-block; zoom:1;
@@ -2941,14 +2942,14 @@ dd .stream-status {
}
.edit-user-global dt {
- width: 90px;
+ width: 100px;
float: left;
margin-top: 4px;
margin-left: 2px;
}
.edit-user-global dd {
- width: 230px;
+ width: 240px;
padding-bottom: 5px;
}
diff --git a/airtime_mvc/public/js/airtime/dashboard/dashboard.js b/airtime_mvc/public/js/airtime/dashboard/dashboard.js
index 7f86f705d..764751fb4 100644
--- a/airtime_mvc/public/js/airtime/dashboard/dashboard.js
+++ b/airtime_mvc/public/js/airtime/dashboard/dashboard.js
@@ -460,7 +460,7 @@ $(document).ready(function() {
clearTimeout(timer);
});
- $('.tipsy').live('mouseout', function() {
+ $('.tipsy').live('blur', function() {
timer = setTimeout("$('#current-user').tipsy('hide')", 500);
});
diff --git a/airtime_mvc/public/js/airtime/preferences/streamsetting.js b/airtime_mvc/public/js/airtime/preferences/streamsetting.js
index 28dd07db1..7fa712a58 100644
--- a/airtime_mvc/public/js/airtime/preferences/streamsetting.js
+++ b/airtime_mvc/public/js/airtime/preferences/streamsetting.js
@@ -355,6 +355,27 @@ function setupEventListeners() {
},
})
+ $(".admin_username_help_icon").qtip({
+ content: {
+ text: $.i18n._("This admin username and password for Icecast to get listener statistics.")
+ },
+ hide: {
+ delay: 500,
+ fixed: true
+ },
+ style: {
+ border: {
+ width: 0,
+ radius: 4
+ },
+ classes: "ui-tooltip-dark ui-tooltip-rounded"
+ },
+ position: {
+ my: "left bottom",
+ at: "right center"
+ },
+ })
+
$(".master_username_help_icon").qtip({
content: {
text: $.i18n._("If your live streaming client does not ask for a username, this field should be 'source'.")
diff --git a/python_apps/pypo/listenerstat.py b/python_apps/pypo/listenerstat.py
index 431f05e98..10efbc586 100644
--- a/python_apps/pypo/listenerstat.py
+++ b/python_apps/pypo/listenerstat.py
@@ -31,7 +31,7 @@ class ListenerStat(Thread):
def get_icecast_xml(self, ip):
- encoded = base64.b64encode("%(admin_user)s:%(admin_password)s" % ip)
+ encoded = base64.b64encode("%(admin_user)s:%(admin_pass)s" % ip)
header = {"Authorization":"Basic %s" % encoded}
self.logger.debug(ip)
@@ -78,8 +78,6 @@ class ListenerStat(Thread):
#streams are the same server, we will still initiate 3 separate
#connections
for k, v in stream_parameters.items():
- v["admin_user"] = "admin"
- v["admin_password"] = "hackme"
if v["enable"] == 'true':
stats.append(self.get_icecast_stats(v))
#stats.append(get_shoutcast_stats(ip))
@@ -103,8 +101,7 @@ class ListenerStat(Thread):
self.push_stream_stats(stats)
except Exception, e:
- top = traceback.format_exc()
- self.logger.error('Exception: %s', top)
+ self.logger.error('Exception: %s', e)
time.sleep(120)
diff --git a/python_apps/pypo/pypofetch.py b/python_apps/pypo/pypofetch.py
index 2641b5c61..37c8d2f6c 100644
--- a/python_apps/pypo/pypofetch.py
+++ b/python_apps/pypo/pypofetch.py
@@ -188,28 +188,6 @@ class PypoFetch(Thread):
self.update_liquidsoap_station_name(info['station_name'])
self.update_liquidsoap_transition_fade(info['transition_fade'])
- def write_liquidsoap_config(self, setting):
- fh = open('/etc/airtime/liquidsoap.cfg', 'w')
- self.logger.info("Rewriting liquidsoap.cfg...")
- fh.write("################################################\n")
- fh.write("# THIS FILE IS AUTO GENERATED. DO NOT CHANGE!! #\n")
- fh.write("################################################\n")
- for k, d in setting:
- buffer_str = d[u'keyname'] + " = "
- if d[u'type'] == 'string':
- temp = d[u'value']
- buffer_str += '"%s"' % temp
- else:
- temp = d[u'value']
- if temp == "":
- temp = "0"
- buffer_str += temp
-
- buffer_str += "\n"
- fh.write(api_client.encode_to(buffer_str))
- fh.write("log_file = \"/var/log/airtime/pypo-liquidsoap/