Merge branch '2.3.x' into 2.3.x-saas

This commit is contained in:
Martin Konecny 2013-01-24 17:49:08 -05:00
commit 6f5ffdc1e7
29 changed files with 7386 additions and 95 deletions

20
CREDITS
View File

@ -2,6 +2,26 @@
CREDITS CREDITS
======= =======
Version 2.3.0
-------------
Martin Konecny (martin.konecny@sourcefabric.org)
Role: Developer Team Lead
James Moon (james.moon@sourcefabric.org)
Role: Software Developer
Denise Rigato (denise.rigato@sourcefabric.org)
Role: Software Developer
Cliff Wang (cliff.wang@sourcefabric.org)
Role: QA
Mikayel Karapetian (michael.karapetian@sourcefabric.org)
Role: QA
Daniel James (daniel.james@sourcefabric.org)
Role: Documentor & QA
Version 2.2.1 Version 2.2.1
------------- -------------
Martin Konecny (martin.konecny@sourcefabric.org) Martin Konecny (martin.konecny@sourcefabric.org)

View File

@ -141,6 +141,12 @@ Non-linked code:
- Web site: http://www.python.org/ - Web site: http://www.python.org/
- License: PSF License. See http://docs.python.org/license.html - License: PSF License. See http://docs.python.org/license.html
* Silan
- What is it: Silence detector
- Web site: https://github.com/x42/silan
- License: GPL-2+
- Compatible with GPLv3? Yes.
------------- -------------
Show Recorder Show Recorder
------------- -------------
@ -175,8 +181,6 @@ Non-linked code:
- Web site: http://www.python.org/ - Web site: http://www.python.org/
- License: PSF License. See http://docs.python.org/license.html - License: PSF License. See http://docs.python.org/license.html
* Liquidsoap 1.0.0 * Liquidsoap 1.0.1
- Web site: http://savonet.sourceforge.net/ - Web site: http://savonet.sourceforge.net/
- License: GPLv2 - License: GPLv2

View File

@ -46,7 +46,7 @@ class AudiopreviewController extends Zend_Controller_Action
} }
if ($type == "audioclip") { if ($type == "audioclip") {
$uri = $baseUrl."/api/get-media/file/".$audioFileID; $uri = $baseUrl."api/get-media/file/".$audioFileID;
$media = Application_Model_StoredFile::Recall($audioFileID); $media = Application_Model_StoredFile::Recall($audioFileID);
$mime = $media->getPropelOrm()->getDbMime(); $mime = $media->getPropelOrm()->getDbMime();
} elseif ($type == "stream") { } elseif ($type == "stream") {

View File

@ -9,6 +9,7 @@ class ScheduleController extends Zend_Controller_Action
{ {
$ajaxContext = $this->_helper->getHelper('AjaxContext'); $ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('event-feed', 'json') $ajaxContext->addActionContext('event-feed', 'json')
->addActionContext('event-feed-preload', 'json')
->addActionContext('make-context-menu', 'json') ->addActionContext('make-context-menu', 'json')
->addActionContext('add-show-dialog', 'json') ->addActionContext('add-show-dialog', 'json')
->addActionContext('add-show', 'json') ->addActionContext('add-show', 'json')
@ -88,15 +89,23 @@ class ScheduleController extends Zend_Controller_Action
$this->view->headLink()->appendStylesheet($baseUrl.'css/showbuilder.css?'.$CC_CONFIG['airtime_version']); $this->view->headLink()->appendStylesheet($baseUrl.'css/showbuilder.css?'.$CC_CONFIG['airtime_version']);
//End Show builder JS/CSS requirements //End Show builder JS/CSS requirements
Application_Model_Schedule::createNewFormSections($this->view); Application_Model_Schedule::createNewFormSections($this->view);
$user = Application_Model_User::getCurrentUser(); $user = Application_Model_User::getCurrentUser();
if ($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) { if ($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
$this->view->preloadShowForm = true; $this->view->preloadShowForm = true;
} }
$this->view->headScript()->appendScript("var weekStart = ".Application_Model_Preference::GetWeekStartDay().";"); $this->view->headScript()->appendScript(
"var calendarPref = {};\n".
"calendarPref.weekStart = ".Application_Model_Preference::GetWeekStartDay().";\n".
"calendarPref.timestamp = ".time().";\n".
"calendarPref.timezoneOffset = ".date("Z").";\n".
"calendarPref.timeScale = '".Application_Model_Preference::GetCalendarTimeScale()."';\n".
"calendarPref.timeInterval = ".Application_Model_Preference::GetCalendarTimeInterval().";\n".
"calendarPref.weekStartDay = ".Application_Model_Preference::GetWeekStartDay().";\n".
"var calendarEvents = null;"
);
} }
public function eventFeedAction() public function eventFeedAction()
@ -108,10 +117,28 @@ class ScheduleController extends Zend_Controller_Action
$userInfo = Zend_Auth::getInstance()->getStorage()->read(); $userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id); $user = new Application_Model_User($userInfo->id);
if ($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) { $editable = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$editable = true;
$events = &Application_Model_Show::getFullCalendarEvents($start, $end, $editable);
$this->view->events = $events;
}
public function eventFeedPreloadAction()
{
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
$editable = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$calendar_interval = Application_Model_Preference::GetCalendarTimeScale();
Logging::info($calendar_interval);
if ($calendar_interval == "agendaDay") {
list($start, $end) = Application_Model_Show::getStartEndCurrentDayView();
} else if ($calendar_interval == "agendaWeek") {
list($start, $end) = Application_Model_Show::getStartEndCurrentWeekView();
} else if ($calendar_interval == "month") {
list($start, $end) = Application_Model_Show::getStartEndCurrentMonthView();
} else { } else {
$editable = false; Logging::error("Invalid Calendar Interval '$calendar_interval'");
} }
$events = &Application_Model_Show::getFullCalendarEvents($start, $end, $editable); $events = &Application_Model_Show::getFullCalendarEvents($start, $end, $editable);

View File

@ -378,10 +378,8 @@ SQL;
$row->setDbCliplength($info["cliplength"]); $row->setDbCliplength($info["cliplength"]);
$row->setDbCuein($info["cuein"]); $row->setDbCuein($info["cuein"]);
$row->setDbCueout($info["cueout"]); $row->setDbCueout($info["cueout"]);
$info["fadein"] = Application_Common_DateHelper::secondsToPlaylistTime($info["fadein"]); $row->setDbFadein(Application_Common_DateHelper::secondsToPlaylistTime($info["fadein"]));
$info["fadeout"] = Application_Common_DateHelper::secondsToPlaylistTime($info["fadeout"]); $row->setDbFadeout(Application_Common_DateHelper::secondsToPlaylistTime($info["fadeout"]));
$row->setDbFadein($info["fadein"]);
$row->setDbFadeout($info["fadeout"]);
$row->save($this->con); $row->save($this->con);
// above save result update on cc_block table on length column. // above save result update on cc_block table on length column.
// but $this->block doesn't get updated automatically // but $this->block doesn't get updated automatically

View File

@ -348,10 +348,8 @@ SQL;
$row->setDbCliplength($info["cliplength"]); $row->setDbCliplength($info["cliplength"]);
$row->setDbCuein($info["cuein"]); $row->setDbCuein($info["cuein"]);
$row->setDbCueout($info["cueout"]); $row->setDbCueout($info["cueout"]);
$info["fadein"] = Application_Common_DateHelper::secondsToPlaylistTime($info["fadein"]); $row->setDbFadein(Application_Common_DateHelper::secondsToPlaylistTime($info["fadein"]));
$info["fadeout"] = Application_Common_DateHelper::secondsToPlaylistTime($info["fadeout"]); $row->setDbFadeout(Application_Common_DateHelper::secondsToPlaylistTime($info["fadeout"]));
$row->setDbFadein($info["fadein"]);
$row->setDbFadeout($info["fadeout"]);
if ($info["ftype"] == "audioclip") { if ($info["ftype"] == "audioclip") {
$row->setDbFileId($info["id"]); $row->setDbFileId($info["id"]);
$type = 0; $type = 0;

View File

@ -1750,12 +1750,15 @@ SQL;
$interval = $p_start->diff($p_end); $interval = $p_start->diff($p_end);
$days = $interval->format('%a'); $days = $interval->format('%a');
$shows = Application_Model_Show::getShows($p_start, $p_end); $shows = Application_Model_Show::getShows($p_start, $p_end);
$nowEpoch = time();
$content_count = Application_Model_ShowInstance::getContentCount( $content_count = Application_Model_ShowInstance::getContentCount(
$p_start, $p_end); $p_start, $p_end);
$isFull = Application_Model_ShowInstance::getIsFull($p_start, $p_end);
$timezone = date_default_timezone_get(); $timezone = date_default_timezone_get();
$current_timezone = new DateTimeZone($timezone);
$utc = new DateTimeZone("UTC");
$now = new DateTime("now", $utc);
foreach ($shows as $show) { foreach ($shows as &$show) {
$options = array(); $options = array();
//only bother calculating percent for week or day view. //only bother calculating percent for week or day view.
@ -1763,11 +1766,8 @@ SQL;
$options["percent"] = Application_Model_Show::getPercentScheduled($show["starts"], $show["ends"], $show["time_filled"]); $options["percent"] = Application_Model_Show::getPercentScheduled($show["starts"], $show["ends"], $show["time_filled"]);
} }
$utc = new DateTimeZone("UTC");
if (isset($show["parent_starts"])) { if (isset($show["parent_starts"])) {
$parentStartsDT = new DateTime($show["parent_starts"], $utc); $parentStartsDT = new DateTime($show["parent_starts"], $utc);
$parentStartsEpoch = intval($parentStartsDT->format("U"));
} }
$startsDT = DateTime::createFromFormat("Y-m-d G:i:s", $startsDT = DateTime::createFromFormat("Y-m-d G:i:s",
@ -1775,39 +1775,53 @@ SQL;
$endsDT = DateTime::createFromFormat("Y-m-d G:i:s", $endsDT = DateTime::createFromFormat("Y-m-d G:i:s",
$show["ends"], $utc); $show["ends"], $utc);
$startsEpochStr = $startsDT->format("U");
$endsEpochStr = $endsDT->format("U");
$startsEpoch = intval($startsEpochStr);
$endsEpoch = intval($endsEpochStr);
$startsDT->setTimezone(new DateTimeZone($timezone));
$endsDT->setTimezone(new DateTimeZone($timezone));
if( $p_editable ) { if( $p_editable ) {
if ($show["record"] && $nowEpoch > $startsEpoch) { if ($show["record"] && $now > $startsDT) {
$options["editable"] = false; $options["editable"] = false;
} elseif ($show["rebroadcast"] && } elseif ($show["rebroadcast"] &&
$nowEpoch > $parentStartsEpoch) { $now > $parentStartsDT) {
$options["editable"] = false; $options["editable"] = false;
} elseif ($nowEpoch < $endsEpoch) { } elseif ($now < $endsDT) {
$options["editable"] = true; $options["editable"] = true;
} }
} }
$startsDT->setTimezone($current_timezone);
$showInstance = new Application_Model_ShowInstance( $endsDT->setTimezone($current_timezone);
$show["instance_id"]);
$options["show_empty"] = (array_key_exists($show['instance_id'], $options["show_empty"] = (array_key_exists($show['instance_id'],
$content_count)) ? 0 : 1; $content_count)) ? 0 : 1;
$options["show_partial_filled"] = $showInstance->showPartialFilled();
$events[] = &self::makeFullCalendarEvent($show, $options, $options["show_partial_filled"] = !$isFull[$show['instance_id']];
$startsDT, $endsDT, $startsEpochStr, $endsEpochStr);
$event = array();
$event["id"] = intval($show["instance_id"]);
$event["title"] = $show["name"];
$event["start"] = $startsDT->format("Y-m-d H:i:s");
$event["end"] = $endsDT->format("Y-m-d H:i:s");
$event["allDay"] = false;
$event["showId"] = intval($show["show_id"]);
$event["record"] = intval($show["record"]);
$event["rebroadcast"] = intval($show["rebroadcast"]);
$event["soundcloud_id"] = is_null($show["soundcloud_id"])
? -1 : $show["soundcloud_id"];
//event colouring
if ($show["color"] != "") {
$event["textColor"] = "#".$show["color"];
}
if ($show["background_color"] != "") {
$event["color"] = "#".$show["background_color"];
}
foreach ($options as $key => $value) {
$event[$key] = $value;
}
$events[] = $event;
} }
return $events; return $events;
} }
@ -1824,7 +1838,7 @@ SQL;
return $percent; return $percent;
} }
private static function &makeFullCalendarEvent(&$show, $options=array(), $startDateTime, $endDateTime, $startsEpoch, $endsEpoch) /* private static function &makeFullCalendarEvent(&$show, $options=array(), $startDateTime, $endDateTime, $startsEpoch, $endsEpoch)
{ {
$event = array(); $event = array();
@ -1855,7 +1869,7 @@ SQL;
} }
return $event; return $event;
} }*/
/* Takes in a UTC DateTime object. /* Takes in a UTC DateTime object.
* Converts this to local time, since cc_show days * Converts this to local time, since cc_show days
@ -2162,4 +2176,42 @@ SQL;
} }
return $assocArray; return $assocArray;
} }
public static function getStartEndCurrentMonthView() {
$first_day_of_calendar_month_view = mktime(0, 0, 0, date("n"), 1);
$weekStart = Application_Model_Preference::GetWeekStartDay();
while (date('w', $first_day_of_calendar_month_view) != $weekStart) {
$first_day_of_calendar_month_view -= 60*60*24;
}
$last_day_of_calendar_view = $first_day_of_calendar_month_view + 3600*24*42;
$start = new DateTime("@".$first_day_of_calendar_month_view);
$end = new DateTime("@".$last_day_of_calendar_view);
return array($start, $end);
}
public static function getStartEndCurrentWeekView() {
$first_day_of_calendar_week_view = mktime(0, 0, 0, date("n"), date("j"));
$weekStart = Application_Model_Preference::GetWeekStartDay();
while (date('w', $first_day_of_calendar_week_view) != $weekStart) {
$first_day_of_calendar_week_view -= 60*60*24;
}
$last_day_of_calendar_view = $first_day_of_calendar_week_view + 3600*24*7;
$start = new DateTime("@".$first_day_of_calendar_week_view);
$end = new DateTime("@".$last_day_of_calendar_view);
return array($start, $end);
}
public static function getStartEndCurrentDayView() {
$today = mktime(0, 0, 0, date("n"), date("j"));
$tomorrow = $today + 3600*24;
$start = new DateTime("@".$today);
$end = new DateTime("@".$tomorrow);
return array($start, $end);
}
} }

View File

@ -661,10 +661,8 @@ SQL;
return $returnStr; return $returnStr;
} }
public static function getContentCount($p_start, $p_end) public static function getContentCount($p_start, $p_end)
{ {
$sql = <<<SQL $sql = <<<SQL
SELECT instance_id, SELECT instance_id,
count(*) AS instance_count count(*) AS instance_count
@ -687,20 +685,26 @@ SQL;
} }
public function showPartialFilled() public static function getIsFull($p_start, $p_end)
{ {
$sql = <<<SQL $sql = <<<SQL
SELECT time_filled > '00:00:00' SELECT id, ends-starts-'00:00:05' < time_filled as filled
AND time_filled < ends - starts from cc_show_instances
AND file_id IS null AS partial_filled WHERE ends > :p_start::TIMESTAMP
FROM cc_show_instances AND starts < :p_end::TIMESTAMP
WHERE id = :instance_id
SQL; SQL;
$res = Application_Common_Database::prepareAndExecute($sql, $res = Application_Common_Database::prepareAndExecute($sql, array(
array(':instance_id' => $this->_instanceId), 'all'); ':p_start' => $p_start->format("Y-m-d G:i:s"),
':p_end' => $p_end->format("Y-m-d G:i:s"))
, 'all');
return $res[0]["partial_filled"]; $isFilled = array();
foreach ($res as $r) {
$isFilled[$r['id']] = $r['filled'];
}
return $isFilled;
} }
public function showEmpty() public function showEmpty()

View File

@ -326,12 +326,14 @@ INSERT INTO cc_pref("keystr", "valstr") VALUES('locale', 'en_CA');
INSERT INTO cc_pref("subjid", "keystr", "valstr") VALUES(1, 'user_locale', 'en_CA'); INSERT INTO cc_pref("subjid", "keystr", "valstr") VALUES(1, 'user_locale', 'en_CA');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('en_CA', 'English'); INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('en_CA', 'English');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('fr_FR', 'Français'); INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('cs_CZ', 'Český');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('de_DE', 'Deutsch'); INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('de_DE', 'Deutsch');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('es_ES', 'Español');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('fr_FR', 'Français');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('it_IT', 'Italiano'); INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('it_IT', 'Italiano');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('ko_KR', '한국어'); INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('ko_KR', '한국어');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('pt_BR', 'Português Brasileiro');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('ru_RU', 'Русский'); INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('ru_RU', 'Русский');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('es_ES', 'Español');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('zh_CN', '简体中文'); INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('zh_CN', '简体中文');
-- end of added in 2.3 -- end of added in 2.3

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,7 @@ function createDateInput(el, onSelect) {
dayNamesMin: i18n_days_short, dayNamesMin: i18n_days_short,
closeText: $.i18n._('Close'), closeText: $.i18n._('Close'),
//showButtonPanel: true, //showButtonPanel: true,
firstDay: weekStart firstDay: calendarPref.weekStart
}); });
} }
@ -324,7 +324,7 @@ function setAddShowEvents() {
dayNamesMin: i18n_days_short, dayNamesMin: i18n_days_short,
closeText: 'Close', closeText: 'Close',
showButtonPanel: true, showButtonPanel: true,
firstDay: weekStart firstDay: calendarPref.weekStart
}); });
form.find('input[name^="add_show_rebroadcast_time"]').timepicker({ form.find('input[name^="add_show_rebroadcast_time"]').timepicker({
amPmText: ['', ''], amPmText: ['', ''],

View File

@ -326,21 +326,36 @@ function eventResize( event, dayDelta, minuteDelta, revertFunc, jsEvent, ui, vie
}); });
} }
function getFullCalendarEvents(start, end, callback) { function preloadEventFeed () {
var url, start_date, end_date; var url = baseUrl+'Schedule/event-feed-preload';
start_date = makeTimeStamp(start);
end_date = makeTimeStamp(end);
url = baseUrl+'Schedule/event-feed';
var d = new Date(); var d = new Date();
$.post(url, {format: "json", start: start_date, end: end_date, cachep: d.getTime()}, function(json){ $.post(url, {format: "json", cachep: d.getTime()}, function(json){
callback(json.events); calendarEvents = json.events;
createFullCalendar({calendarInit: calendarPref});
}); });
} }
var initialLoad = true;
function getFullCalendarEvents(start, end, callback) {
if (initialLoad) {
initialLoad = false;
callback(calendarEvents);
} else {
var url, start_date, end_date;
start_date = makeTimeStamp(start);
end_date = makeTimeStamp(end);
url = baseUrl+'Schedule/event-feed';
var d = new Date();
$.post(url, {format: "json", start: start_date, end: end_date, cachep: d.getTime()}, function(json){
callback(json.events);
});
}
}
function checkSCUploadStatus(){ function checkSCUploadStatus(){
var url = baseUrl+'Library/get-upload-to-soundcloud-status/format/json'; var url = baseUrl+'Library/get-upload-to-soundcloud-status/format/json';
$("span[class*=progress]").each(function(){ $("span[class*=progress]").each(function(){
@ -541,6 +556,7 @@ function alertShowErrorAndReload(){
window.location.reload(); window.location.reload();
} }
preloadEventFeed();
$(document).ready(function(){ $(document).ready(function(){
setInterval( "checkSCUploadStatus()", 5000 ); setInterval( "checkSCUploadStatus()", 5000 );
setInterval( "getCurrentShow()", 5000 ); setInterval( "getCurrentShow()", 5000 );

View File

@ -328,9 +328,6 @@ function alertShowErrorAndReload(){
} }
$(document).ready(function() { $(document).ready(function() {
$.ajax({ url: baseUrl+"Api/calendar-init/format/json", dataType:"json", success:createFullCalendar
, error:function(jqXHR, textStatus, errorThrown){}});
setInterval(checkCalendarSCUploadStatus, 5000); setInterval(checkCalendarSCUploadStatus, 5000);
$.contextMenu({ $.contextMenu({

View File

@ -0,0 +1,18 @@
//Czech
{
"sProcessing": "Provádím...",
"sLengthMenu": "Zobraz záznamů _MENU_",
"sZeroRecords": "Žádné záznamy nebyly nalezeny",
"sInfo": "Zobrazuji _START_ až _END_ z celkem _TOTAL_ záznamů",
"sInfoEmpty": "Zobrazuji 0 až 0 z 0 záznamů",
"sInfoFiltered": "(filtrováno z celkem _MAX_ záznamů)",
"sInfoPostFix": "",
"sSearch": "",
"sUrl": "",
"oPaginate": {
"sFirst": "První",
"sPrevious": "Předchozí",
"sNext": "Další",
"sLast": "Poslední"
}
}

View File

@ -0,0 +1,18 @@
//Portuguese Brasil
{
"sProcessing": "Processando...",
"sLengthMenu": "Mostrar _MENU_ registros",
"sZeroRecords": "Não foram encontrados resultados",
"sInfo": "Mostrando de _START_ até _END_ de _TOTAL_ registros",
"sInfoEmpty": "Mostrando de 0 até 0 de 0 registros",
"sInfoFiltered": "(filtrado de _MAX_ registros no total)",
"sInfoPostFix": "",
"sSearch": "",
"sUrl": "",
"oPaginate": {
"sFirst": "Primeiro",
"sPrevious": "Anterior",
"sNext": "Seguinte",
"sLast": "Último"
}
}

View File

@ -0,0 +1,27 @@
//Czech
plupload.addI18n({
'Select files' : $.i18n._('Select files'),
'Add files to the upload queue and click the start button.' : $.i18n._('Add files to the upload queue and click the start button.'),
'Filename' : $.i18n._('Filename'),
'Status' : $.i18n._('Status'),
'Size' : $.i18n._('Size'),
'Add files' : $.i18n._('Add files'),
'Stop current upload' : $.i18n._('Stop current upload'),
'Start uploading queue' : $.i18n._('Start uploading queue'),
'Uploaded %d/%d files': $.i18n._('Uploaded %d/%d files'),
'N/A' : $.i18n._('N/A'),
'Drag files here.' : $.i18n._('Drag files here.'),
'File extension error.': $.i18n._('File extension error.'),
'File size error.': $.i18n._('File size error.'),
'Init error.': $.i18n._('Init error.'),
'HTTP Error.': $.i18n._('HTTP Error.'),
'Security error.': $.i18n._('Security error.'),
'Generic error.': $.i18n._('Generic error.'),
'IO error.': $.i18n._('IO error.'),
'Stop Upload': $.i18n._('Stop Upload'),
'Add Files': $.i18n._('Add Files'),
'Start Upload': $.i18n._('Start Upload'),
'Start upload': $.i18n._('Start upload'),
'%d files queued': $.i18n._('%d files queued'),
"Error: Invalid file extension: " : $.i18n._("Error: Invalid file extension: ")
});

View File

@ -0,0 +1,27 @@
//Portuguese Brazilian
plupload.addI18n({
'Select files' : $.i18n._('Select files'),
'Add files to the upload queue and click the start button.' : $.i18n._('Add files to the upload queue and click the start button.'),
'Filename' : $.i18n._('Filename'),
'Status' : $.i18n._('Status'),
'Size' : $.i18n._('Size'),
'Add files' : $.i18n._('Add files'),
'Stop current upload' : $.i18n._('Stop current upload'),
'Start uploading queue' : $.i18n._('Start uploading queue'),
'Uploaded %d/%d files': $.i18n._('Uploaded %d/%d files'),
'N/A' : $.i18n._('N/A'),
'Drag files here.' : $.i18n._('Drag files here.'),
'File extension error.': $.i18n._('File extension error.'),
'File size error.': $.i18n._('File size error.'),
'Init error.': $.i18n._('Init error.'),
'HTTP Error.': $.i18n._('HTTP Error.'),
'Security error.': $.i18n._('Security error.'),
'Generic error.': $.i18n._('Generic error.'),
'IO error.': $.i18n._('IO error.'),
'Stop Upload': $.i18n._('Stop Upload'),
'Add Files': $.i18n._('Add Files'),
'Start Upload': $.i18n._('Start Upload'),
'Start upload': $.i18n._('Start upload'),
'%d files queued': $.i18n._('%d files queued'),
"Error: Invalid file extension: " : $.i18n._("Error: Invalid file extension: ")
});

View File

@ -1,3 +1,14 @@
2.3.0 - Jan 21st, 2013
* New features
* Localization (Brazilian, Chinese, Czech, English, French, German, Italian, Korean, Portugese, Russian, Spanish)
* User management page for non-admin users
* Listener statistics (Icecast/Shoutcast)
* Airtime no longer requires Apache document root
* Replay Gain offset in real-time
* Enable/disable replay gain
* Liquidsoap memory footprint improvements
* Automatically set cue points on import to avoid leading/trailing silence
2.2.1 - December 4th, 2012 2.2.1 - December 4th, 2012
* Bug fixes * Bug fixes
* Improved fades between webstreams * Improved fades between webstreams

22
debian/changelog vendored
View File

@ -1,8 +1,26 @@
airtime (2.3.0-1) unstable; urgency=low
* Nightly development snapshot of Airtime 2.3.x
-- Daniel James <daniel@64studio.com> Tue, 22 Jan 2013 11:44:57 +0000
airtime (2.2.1-1) unstable; urgency=low
* Upstream 2.2.1 release
-- Daniel James <daniel@64studio.com> Tue, 04 Dec 2012 11:10:37 +0000
airtime (2.2.0-2) unstable; urgency=low
* Added dependency on flac package for metaflac support
-- Daniel James <daniel@64studio.com> Mon, 05 Nov 2012 10:54:49 +0000
airtime (2.2.0-1) unstable; urgency=low airtime (2.2.0-1) unstable; urgency=low
* Nightly development snapshot of Airtime 2.2.x * Upstream 2.2.0 release
-- Daniel James <daniel@64studio.com> Thu, 02 Aug 2012 11:19:03 +0100 -- Daniel James <daniel@64studio.com> Fri, 26 Oct 2012 10:44:06 +0100
airtime (2.1.3-2) unstable; urgency=low airtime (2.1.3-2) unstable; urgency=low

1
debian/control vendored
View File

@ -41,6 +41,7 @@ Depends: apache2,
pwgen, pwgen,
python, python,
rabbitmq-server, rabbitmq-server,
silan,
sudo, sudo,
sysv-rc, sysv-rc,
tar (>= 1.22), tar (>= 1.22),

7
debian/postinst vendored
View File

@ -12,7 +12,7 @@ includefile="${configdir}/apache.conf"
a2tplfile="${configdir}/apache.vhost.tpl" a2tplfile="${configdir}/apache.vhost.tpl"
phpinifile="${configdir}/airtime.ini" phpinifile="${configdir}/airtime.ini"
OLDVERSION="$2" OLDVERSION="$2"
NEWVERSION="2.2.0" NEWVERSION="2.3.0"
case "$1" in case "$1" in
configure|reconfigure) configure|reconfigure)
@ -126,6 +126,11 @@ case "$1" in
ICESOURCE=$RET ICESOURCE=$RET
sed -i "s:'s1_pass', 'hackme', 'string':'s1_pass', '$ICESOURCE', 'string':g" ${tmpdir}/airtime_mvc/build/sql/defaultdata.sql sed -i "s:'s1_pass', 'hackme', 'string':'s1_pass', '$ICESOURCE', 'string':g" ${tmpdir}/airtime_mvc/build/sql/defaultdata.sql
db_get airtime/icecast-adminpw
ICEADMIN=$RET
sed -i "s:'s1_admin_user', '', 'string':'s1_admin_user', 'admin', 'string':g" ${tmpdir}/airtime_mvc/build/sql/defaultdata.sql
sed -i "s:'s1_admin_pass', '', 'string':'s1_admin_pass', '$ICEADMIN', 'string':g" ${tmpdir}/airtime_mvc/build/sql/defaultdata.sql
else else
echo "The icecast2 package does not appear to be installed on this server." echo "The icecast2 package does not appear to be installed on this server."
fi fi

View File

@ -3,7 +3,6 @@
# Run from the directory containg the files checked out from git # Run from the directory containg the files checked out from git
VERSION=2.3.0~$(date "+%Y%m%d") VERSION=2.3.0~$(date "+%Y%m%d")
#VERSION=2.2.0-rc1
BUILDDEST=/tmp/airtime-${VERSION}/ BUILDDEST=/tmp/airtime-${VERSION}/
DEBDIR=`pwd`/debian DEBDIR=`pwd`/debian
@ -24,9 +23,9 @@ cd ${BUILDDEST} || exit
# Set the version of the snapshot package # Set the version of the snapshot package
sed -i "1s:(2.2.0-1):(${VERSION}):g" debian/changelog sed -i "1s:(2.3.0-1):(${VERSION}):g" debian/changelog
# FIXES for 2.2.0 ############# # FIXES for 2.3.0 #############
# these are all moved to debian/copyright # these are all moved to debian/copyright
rm airtime/python_apps/pypo/LICENSE rm airtime/python_apps/pypo/LICENSE
@ -35,7 +34,7 @@ rm airtime/airtime_mvc/library/phing/LICENSE
rm airtime/airtime_mvc/library/propel/LICENSE rm airtime/airtime_mvc/library/propel/LICENSE
rm airtime/airtime_mvc/library/soundcloud-api/README.md rm airtime/airtime_mvc/library/soundcloud-api/README.md
# Remove Liquidsoap binaries # Remove Liquidsoap binary
rm -r airtime/python_apps/pypo/liquidsoap_bin/ rm -r airtime/python_apps/pypo/liquidsoap_bin/
#Remove phing library #Remove phing library

View File

@ -7,6 +7,7 @@ if [[ $EUID -ne 0 ]]; then
exit 1 exit 1
fi fi
set +e
dist=`lsb_release -is` dist=`lsb_release -is`
echo "Generating locales" echo "Generating locales"
for i in `ls /usr/share/airtime/locale | grep ".._.."`; do for i in `ls /usr/share/airtime/locale | grep ".._.."`; do
@ -19,6 +20,7 @@ for i in `ls /usr/share/airtime/locale | grep ".._.."`; do
locale-gen "$i.utf8" locale-gen "$i.utf8"
fi fi
done done
set -e
if [ "$dist" = "Debian" ]; then if [ "$dist" = "Debian" ]; then
/usr/sbin/locale-gen /usr/sbin/locale-gen

View File

@ -12,18 +12,20 @@ INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s3_admin_use
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s3_admin_pass', '', 'string'); INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s3_admin_pass', '', 'string');
--Make sure that cc_music_dir has a trailing '/' and cc_files does not have a leading '/' --Make sure that cc_music_dir has a trailing '/' and cc_files does not have a leading '/'
UPDATE cc_music_dir SET directory = directory || '/' where id in (select id from cc_music_dirs where substr(directory, length(directory)) != '/'); UPDATE cc_music_dirs SET directory = directory || '/' where id in (select id from cc_music_dirs where substr(directory, length(directory)) != '/');
UPDATE cc_files SET filepath = substring(filepath from 2) where id in (select id from cc_files where substring(filepath from 1 for 1) = '/') UPDATE cc_files SET filepath = substring(filepath from 2) where id in (select id from cc_files where substring(filepath from 1 for 1) = '/');
INSERT INTO cc_pref("keystr", "valstr") VALUES('locale', 'en_CA'); INSERT INTO cc_pref("keystr", "valstr") VALUES('locale', 'en_CA');
INSERT INTO cc_pref("subjid", "keystr", "valstr") VALUES(1, 'user_locale', 'en_CA'); INSERT INTO cc_pref("subjid", "keystr", "valstr") VALUES(1, 'user_locale', 'en_CA');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('en_CA', 'English'); INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('en_CA', 'English');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('fr_FR', 'Français'); INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('cs_CZ', 'Český');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('de_DE', 'Deutsch'); INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('de_DE', 'Deutsch');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('es_ES', 'Español');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('fr_FR', 'Français');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('it_IT', 'Italiano'); INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('it_IT', 'Italiano');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('ko_KR', '한국어'); INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('ko_KR', '한국어');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('pt_BR', 'Português Brasileiro');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('ru_RU', 'Русский'); INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('ru_RU', 'Русский');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('es_ES', 'Español');
INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('zh_CN', '简体中文'); INSERT INTO cc_locale (locale_code, locale_lang) VALUES ('zh_CN', '简体中文');

View File

@ -2,7 +2,7 @@
import re import re
from media.saas.launcher import setup_logger, setup_global, MM2 from media.saas.launcher import setup_logger, setup_global, MM2
from media.saas.airtimeinstance import AirtimeInstance from media.saas.airtimeinstance import AirtimeInstance
from os.path import isdir, join, abspath, exists from os.path import isdir, join, abspath, exists, dirname
from os import listdir from os import listdir
def list_dirs(d): return (x for x in listdir(d) if isdir(join(d,x))) def list_dirs(d): return (x for x in listdir(d) if isdir(join(d,x)))
@ -32,17 +32,17 @@ def main(main_cfg):
verify_exists(log_config) verify_exists(log_config)
log = setup_logger(log_config, log_path) log = setup_logger(log_config, log_path)
setup_global(log) setup_global(log)
for instance in autoscan_instances(main_cfg): for instance in autoscan_instances(main_cfg):
print("Launching instance: %s" % str(instance)) print("Launching instance: %s" % str(instance))
MM2(instance).start() #MM2(instance).start()
print("Launched all instances") print("Launched all instances")
if __name__ == '__main__': if __name__ == '__main__':
root = '/home/rudi/reps/Airtime/python_apps/media-monitor2' pwd = dirname(__file__)
default = { default = {
'log_path' : join(root, 'test.log'), # config for log 'log_path' : join(pwd, 'test.log'), # config for log
'log_config' : join(root, 'configs/logging.cfg'), # where to log 'log_config' : join(pwd, 'configs/logging.cfg'), # where to log
# root dir of all instances # root dir of all instances
'instance_root' : join(root, 'saas_stub') 'instance_root' : '/mnt/airtimepro/instances'
} }
main(default) main(default)

View File

@ -45,7 +45,7 @@ class AirtimeInstance(object):
touch_base_name = basename(touch_base_path) touch_base_name = basename(touch_base_path)
new_base_name = self.name + touch_base_name new_base_name = self.name + touch_base_name
return join(dirname(touch_base_path), new_base_name) return join(dirname(touch_base_path), new_base_name)
def __str__(self): def __str__(self):
return "%s,%s(%s)" % (self.name, self.root_path, self.config_paths) return "%s,%s(%s)" % (self.name, self.root_path, self.config_paths)