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') ?> + element->getElement('cu_locale')->hasErrors()) : ?> + + +
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; ?>

">stream_number?>

@@ -104,6 +104,34 @@ +
+ +
+
+ element->getElement('admin_user')?> + element->getElement('admin_user')->hasErrors()) : ?> + + +
+
+ +
+
+ element->getElement('admin_pass')?> + element->getElement('admin_pass')->hasErrors()) : ?> + + +
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 @@ md["MDATA_KEY_ISRC"]);?> md["MDATA_KEY_URL"]);?> md["MDATA_KEY_LANGUAGE"]);?> - md["MDATA_KEY_FILEPATH"]);?> +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/