Merge branch '2.2.x' of dev.sourcefabric.org:airtime into 2.2.x
This commit is contained in:
commit
5f0fd0ef09
|
@ -268,7 +268,7 @@ SQL;
|
||||||
|
|
||||||
|
|
||||||
//We need to search 24 hours before and after the show times so that that we
|
//We need to search 24 hours before and after the show times so that that we
|
||||||
//capture all of the show's contents.
|
//capture all of the show's contents.
|
||||||
$p_track_start= $p_start->sub(new DateInterval("PT24H"))->format("Y-m-d H:i:s");
|
$p_track_start= $p_start->sub(new DateInterval("PT24H"))->format("Y-m-d H:i:s");
|
||||||
$p_track_end = $p_end->add(new DateInterval("PT24H"))->format("Y-m-d H:i:s");
|
$p_track_end = $p_end->add(new DateInterval("PT24H"))->format("Y-m-d H:i:s");
|
||||||
|
|
||||||
|
@ -661,6 +661,7 @@ SQL;
|
||||||
$data["media"][$switch_start]['start'] = $switch_start;
|
$data["media"][$switch_start]['start'] = $switch_start;
|
||||||
$data["media"][$switch_start]['end'] = $switch_start;
|
$data["media"][$switch_start]['end'] = $switch_start;
|
||||||
$data["media"][$switch_start]['event_type'] = "switch_off";
|
$data["media"][$switch_start]['event_type'] = "switch_off";
|
||||||
|
$data["media"][$kick_start]['type'] = "event";
|
||||||
$data["media"][$switch_start]['independent_event'] = true;
|
$data["media"][$switch_start]['independent_event'] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,66 +25,67 @@ class Application_Model_Soundcloud
|
||||||
|
|
||||||
public function uploadTrack($filepath, $filename, $description,
|
public function uploadTrack($filepath, $filename, $description,
|
||||||
$tags=array(), $release=null, $genre=null)
|
$tags=array(), $release=null, $genre=null)
|
||||||
{
|
{
|
||||||
if ($this->getToken()) {
|
|
||||||
if (count($tags)) {
|
|
||||||
$tags = join(" ", $tags);
|
|
||||||
$tags = $tags." ".Application_Model_Preference::GetSoundCloudTags();
|
|
||||||
} else {
|
|
||||||
$tags = Application_Model_Preference::GetSoundCloudTags();
|
|
||||||
}
|
|
||||||
|
|
||||||
$downloadable = Application_Model_Preference::GetSoundCloudDownloadbleOption() == '1';
|
if (!$this->getToken()) {
|
||||||
|
|
||||||
$track_data = array(
|
|
||||||
'track[sharing]' => 'private',
|
|
||||||
'track[title]' => $filename,
|
|
||||||
'track[asset_data]' => '@' . $filepath,
|
|
||||||
'track[tag_list]' => $tags,
|
|
||||||
'track[description]' => $description,
|
|
||||||
'track[downloadable]' => $downloadable,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isset($release)) {
|
|
||||||
$release = str_replace(" ", "-", $release);
|
|
||||||
$release = str_replace(":", "-", $release);
|
|
||||||
|
|
||||||
//YYYY-MM-DD-HH-mm-SS
|
|
||||||
$release = explode("-", $release);
|
|
||||||
$track_data['track[release_year]'] = $release[0];
|
|
||||||
$track_data['track[release_month]'] = $release[1];
|
|
||||||
$track_data['track[release_day]'] = $release[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($genre) && $genre != "") {
|
|
||||||
$track_data['track[genre]'] = $genre;
|
|
||||||
} else {
|
|
||||||
$default_genre = Application_Model_Preference::GetSoundCloudGenre();
|
|
||||||
if ($default_genre != "") {
|
|
||||||
$track_data['track[genre]'] = $default_genre;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$track_type = Application_Model_Preference::GetSoundCloudTrackType();
|
|
||||||
if ($track_type != "") {
|
|
||||||
$track_data['track[track_type]'] = $track_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
$license = Application_Model_Preference::GetSoundCloudLicense();
|
|
||||||
if ($license != "") {
|
|
||||||
$track_data['track[license]'] = $license;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = json_decode(
|
|
||||||
$this->_soundcloud->post('tracks', $track_data),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
} else {
|
|
||||||
throw new NoSoundCloundToken();
|
throw new NoSoundCloundToken();
|
||||||
|
}
|
||||||
|
if (count($tags)) {
|
||||||
|
$tags = join(" ", $tags);
|
||||||
|
$tags = $tags." ".Application_Model_Preference::GetSoundCloudTags();
|
||||||
|
} else {
|
||||||
|
$tags = Application_Model_Preference::GetSoundCloudTags();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$downloadable = Application_Model_Preference::GetSoundCloudDownloadbleOption() == '1';
|
||||||
|
|
||||||
|
$track_data = array(
|
||||||
|
'track[sharing]' => 'private',
|
||||||
|
'track[title]' => $filename,
|
||||||
|
'track[asset_data]' => '@' . $filepath,
|
||||||
|
'track[tag_list]' => $tags,
|
||||||
|
'track[description]' => $description,
|
||||||
|
'track[downloadable]' => $downloadable,
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isset($release)) {
|
||||||
|
$release = str_replace(" ", "-", $release);
|
||||||
|
$release = str_replace(":", "-", $release);
|
||||||
|
|
||||||
|
//YYYY-MM-DD-HH-mm-SS
|
||||||
|
$release = explode("-", $release);
|
||||||
|
$track_data['track[release_year]'] = $release[0];
|
||||||
|
$track_data['track[release_month]'] = $release[1];
|
||||||
|
$track_data['track[release_day]'] = $release[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($genre) && $genre != "") {
|
||||||
|
$track_data['track[genre]'] = $genre;
|
||||||
|
} else {
|
||||||
|
$default_genre = Application_Model_Preference::GetSoundCloudGenre();
|
||||||
|
if ($default_genre != "") {
|
||||||
|
$track_data['track[genre]'] = $default_genre;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$track_type = Application_Model_Preference::GetSoundCloudTrackType();
|
||||||
|
if ($track_type != "") {
|
||||||
|
$track_data['track[track_type]'] = $track_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
$license = Application_Model_Preference::GetSoundCloudLicense();
|
||||||
|
if ($license != "") {
|
||||||
|
$track_data['track[license]'] = $license;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = json_decode(
|
||||||
|
$this->_soundcloud->post('tracks', $track_data),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function uploadSoundcloud($id)
|
public static function uploadSoundcloud($id)
|
||||||
|
|
|
@ -92,5 +92,13 @@ if ($item['type'] == 2) {
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
|
||||||
<?php else : ?>
|
<?php else : ?>
|
||||||
<li class="spl_empty">Empty playlist</li>
|
<li class="spl_empty">
|
||||||
|
<?php
|
||||||
|
if ($this->obj instanceof Application_Model_Block) {
|
||||||
|
echo 'Empty smart block';
|
||||||
|
} else {
|
||||||
|
echo 'Empty playlist';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
|
@ -339,11 +339,23 @@ var AIRTIME = (function(AIRTIME){
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod.jumpToCurrentTrack = function() {
|
||||||
|
var $scroll = $sbContent.find(".dataTables_scrolling");
|
||||||
|
var scrolled = $scroll.scrollTop();
|
||||||
|
var scrollingTop = $scroll.offset().top;
|
||||||
|
var oTable = $('#show_builder_table').dataTable();
|
||||||
|
var current = $sbTable.find("."+NOW_PLAYING_CLASS);
|
||||||
|
var currentTop = current.offset().top;
|
||||||
|
|
||||||
|
$scroll.scrollTop(currentTop - scrollingTop + scrolled);
|
||||||
|
}
|
||||||
|
|
||||||
mod.builderDataTable = function() {
|
mod.builderDataTable = function() {
|
||||||
$sbContent = $('#show_builder');
|
$sbContent = $('#show_builder');
|
||||||
$lib = $("#library_content"),
|
$lib = $("#library_content"),
|
||||||
$sbTable = $sbContent.find('table');
|
$sbTable = $sbContent.find('table');
|
||||||
|
var isInitialized = false;
|
||||||
|
|
||||||
oSchedTable = $sbTable.dataTable( {
|
oSchedTable = $sbTable.dataTable( {
|
||||||
"aoColumns": [
|
"aoColumns": [
|
||||||
/* checkbox */ {"mDataProp": "allowed", "sTitle": "", "sWidth": "15px", "sClass": "sb-checkbox"},
|
/* checkbox */ {"mDataProp": "allowed", "sTitle": "", "sWidth": "15px", "sClass": "sb-checkbox"},
|
||||||
|
@ -636,6 +648,13 @@ var AIRTIME = (function(AIRTIME){
|
||||||
$("#draggingContainer").remove();
|
$("#draggingContainer").remove();
|
||||||
},
|
},
|
||||||
"fnDrawCallback": function fnBuilderDrawCallback(oSettings, json) {
|
"fnDrawCallback": function fnBuilderDrawCallback(oSettings, json) {
|
||||||
|
if (!isInitialized) {
|
||||||
|
if ($(this).find("."+NOW_PLAYING_CLASS).length > 0) {
|
||||||
|
mod.jumpToCurrentTrack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isInitialized = true;
|
||||||
var wrapperDiv,
|
var wrapperDiv,
|
||||||
markerDiv,
|
markerDiv,
|
||||||
$td,
|
$td,
|
||||||
|
@ -1021,7 +1040,7 @@ var AIRTIME = (function(AIRTIME){
|
||||||
if (AIRTIME.button.isDisabled('icon-step-forward', true) === true) {
|
if (AIRTIME.button.isDisabled('icon-step-forward', true) === true) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
var $scroll = $sbContent.find(".dataTables_scrolling"),
|
var $scroll = $sbContent.find(".dataTables_scrolling"),
|
||||||
scrolled = $scroll.scrollTop(),
|
scrolled = $scroll.scrollTop(),
|
||||||
scrollingTop = $scroll.offset().top,
|
scrollingTop = $scroll.offset().top,
|
||||||
|
@ -1029,6 +1048,8 @@ var AIRTIME = (function(AIRTIME){
|
||||||
currentTop = current.offset().top;
|
currentTop = current.offset().top;
|
||||||
|
|
||||||
$scroll.scrollTop(currentTop - scrollingTop + scrolled);
|
$scroll.scrollTop(currentTop - scrollingTop + scrolled);
|
||||||
|
*/
|
||||||
|
mod.jumpToCurrentTrack();
|
||||||
});
|
});
|
||||||
|
|
||||||
//delete overbooked tracks.
|
//delete overbooked tracks.
|
||||||
|
@ -1196,7 +1217,7 @@ var AIRTIME = (function(AIRTIME){
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return AIRTIME;
|
return AIRTIME;
|
||||||
|
|
|
@ -113,174 +113,180 @@ AIRTIME = (function(AIRTIME) {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.onReady = function() {
|
mod.onReady = function() {
|
||||||
//define module vars.
|
// define module vars.
|
||||||
$lib = $("#library_content");
|
$lib = $("#library_content");
|
||||||
$builder = $("#show_builder");
|
$builder = $("#show_builder");
|
||||||
$fs = $builder.find('fieldset');
|
$fs = $builder.find('fieldset');
|
||||||
|
|
||||||
/*
|
|
||||||
* Icon hover states for search.
|
|
||||||
*/
|
|
||||||
$builder.on("mouseenter", ".sb-timerange .ui-button", function(ev) {
|
|
||||||
$(this).addClass("ui-state-hover");
|
|
||||||
});
|
|
||||||
$builder.on("mouseleave", ".sb-timerange .ui-button", function(ev) {
|
|
||||||
$(this).removeClass("ui-state-hover");
|
|
||||||
});
|
|
||||||
|
|
||||||
$builder.find(dateStartId).datepicker(oBaseDatePickerSettings);
|
|
||||||
$builder.find(timeStartId).timepicker(oBaseTimePickerSettings);
|
|
||||||
$builder.find(dateEndId).datepicker(oBaseDatePickerSettings);
|
|
||||||
$builder.find(timeEndId).timepicker(oBaseTimePickerSettings);
|
|
||||||
|
|
||||||
oRange = AIRTIME.utilities.fnGetScheduleRange(dateStartId, timeStartId, dateEndId, timeEndId);
|
|
||||||
AIRTIME.showbuilder.fnServerData.start = oRange.start;
|
|
||||||
AIRTIME.showbuilder.fnServerData.end = oRange.end;
|
|
||||||
|
|
||||||
AIRTIME.library.libraryInit();
|
/*
|
||||||
AIRTIME.showbuilder.builderDataTable();
|
* Icon hover states for search.
|
||||||
setWidgetSize();
|
*/
|
||||||
|
$builder.on("mouseenter", ".sb-timerange .ui-button", function(ev) {
|
||||||
$libWrapper = $lib.find("#library_display_wrapper");
|
$(this).addClass("ui-state-hover");
|
||||||
$libWrapper.prepend($libClose);
|
});
|
||||||
|
$builder.on("mouseleave", ".sb-timerange .ui-button", function(ev) {
|
||||||
$builder.find('.dataTables_scrolling').css("max-height", widgetHeight - 95);
|
$(this).removeClass("ui-state-hover");
|
||||||
|
});
|
||||||
$builder.on("click", "#sb_submit", showSearchSubmit);
|
|
||||||
|
|
||||||
$builder.on("click","#sb_edit", function (ev){
|
$builder.find(dateStartId).datepicker(oBaseDatePickerSettings);
|
||||||
var schedTable = $("#show_builder_table").dataTable();
|
$builder.find(timeStartId).timepicker(oBaseTimePickerSettings);
|
||||||
|
$builder.find(dateEndId).datepicker(oBaseDatePickerSettings);
|
||||||
//reset timestamp to redraw the cursors.
|
$builder.find(timeEndId).timepicker(oBaseTimePickerSettings);
|
||||||
AIRTIME.showbuilder.resetTimestamp();
|
|
||||||
|
oRange = AIRTIME.utilities.fnGetScheduleRange(dateStartId, timeStartId,
|
||||||
$lib.show()
|
dateEndId, timeEndId);
|
||||||
.width(Math.floor(screenWidth * 0.48));
|
AIRTIME.showbuilder.fnServerData.start = oRange.start;
|
||||||
|
AIRTIME.showbuilder.fnServerData.end = oRange.end;
|
||||||
$builder.width(Math.floor(screenWidth * 0.48))
|
|
||||||
.find("#sb_edit")
|
AIRTIME.library.libraryInit();
|
||||||
.remove()
|
AIRTIME.showbuilder.builderDataTable();
|
||||||
.end()
|
setWidgetSize();
|
||||||
.find("#sb_date_start")
|
|
||||||
.css("margin-left", 0)
|
$libWrapper = $lib.find("#library_display_wrapper");
|
||||||
.end();
|
$libWrapper.prepend($libClose);
|
||||||
|
|
||||||
schedTable.fnDraw();
|
$builder.find('.dataTables_scrolling').css("max-height",
|
||||||
|
widgetHeight - 95);
|
||||||
$.ajax({
|
|
||||||
url: "/usersettings/set-now-playing-screen-settings",
|
$builder.on("click", "#sb_submit", showSearchSubmit);
|
||||||
type: "POST",
|
|
||||||
data: {settings : {library : true}, format: "json"},
|
$builder.on("click", "#sb_edit", function(ev) {
|
||||||
dataType: "json",
|
var schedTable = $("#show_builder_table").dataTable();
|
||||||
success: function(){}
|
|
||||||
});
|
// reset timestamp to redraw the cursors.
|
||||||
});
|
AIRTIME.showbuilder.resetTimestamp();
|
||||||
|
|
||||||
$lib.on("click", "#sb_lib_close", function() {
|
$lib.show().width(Math.floor(screenWidth * 0.48));
|
||||||
var schedTable = $("#show_builder_table").dataTable();
|
|
||||||
|
$builder.width(Math.floor(screenWidth * 0.48)).find("#sb_edit")
|
||||||
|
.remove().end().find("#sb_date_start")
|
||||||
|
.css("margin-left", 0).end();
|
||||||
|
|
||||||
|
schedTable.fnDraw();
|
||||||
|
|
||||||
|
$.ajax( {
|
||||||
|
url : "/usersettings/set-now-playing-screen-settings",
|
||||||
|
type : "POST",
|
||||||
|
data : {
|
||||||
|
settings : {
|
||||||
|
library : true
|
||||||
|
},
|
||||||
|
format : "json"
|
||||||
|
},
|
||||||
|
dataType : "json",
|
||||||
|
success : function() {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$lib.on("click", "#sb_lib_close", function() {
|
||||||
|
var schedTable = $("#show_builder_table").dataTable();
|
||||||
|
|
||||||
|
$lib.hide();
|
||||||
|
$builder.width(screenWidth).find(".sb-timerange").prepend(
|
||||||
|
$toggleLib).find("#sb_date_start").css("margin-left", 30)
|
||||||
|
.end().end();
|
||||||
|
|
||||||
|
$toggleLib.removeClass("ui-state-hover");
|
||||||
|
schedTable.fnDraw();
|
||||||
|
|
||||||
|
$.ajax( {
|
||||||
|
url : "/usersettings/set-now-playing-screen-settings",
|
||||||
|
type : "POST",
|
||||||
|
data : {
|
||||||
|
settings : {
|
||||||
|
library : false
|
||||||
|
},
|
||||||
|
format : "json"
|
||||||
|
},
|
||||||
|
dataType : "json",
|
||||||
|
success : function() {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$builder.find('legend').click(
|
||||||
|
function(ev, item) {
|
||||||
|
|
||||||
|
if ($fs.hasClass("closed")) {
|
||||||
|
|
||||||
|
$fs.removeClass("closed");
|
||||||
|
$builder.find('.dataTables_scrolling').css(
|
||||||
|
"max-height", widgetHeight - 150);
|
||||||
|
} else {
|
||||||
|
$fs.addClass("closed");
|
||||||
|
|
||||||
|
// set defaults for the options.
|
||||||
|
$fs.find('select').val(0);
|
||||||
|
$fs.find('input[type="checkbox"]').attr("checked",
|
||||||
|
false);
|
||||||
|
$builder.find('.dataTables_scrolling').css(
|
||||||
|
"max-height", widgetHeight - 110);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// set click event for all my shows checkbox.
|
||||||
|
$builder.on("click", "#sb_my_shows", function(ev) {
|
||||||
|
|
||||||
|
if ($(this).is(':checked')) {
|
||||||
|
$(ev.delegateTarget).find('#sb_show_filter').val(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
showSearchSubmit();
|
||||||
|
});
|
||||||
|
|
||||||
|
//set select event for choosing a show.
|
||||||
|
$builder.on("change", '#sb_show_filter', function(ev) {
|
||||||
|
|
||||||
|
if ($(this).val() !== 0) {
|
||||||
|
$(ev.delegateTarget).find('#sb_my_shows')
|
||||||
|
.attr("checked", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
showSearchSubmit();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
function checkScheduleUpdates() {
|
||||||
|
var data = {}, oTable = $('#show_builder_table').dataTable(), fn = oTable
|
||||||
|
.fnSettings().fnServerData, start = fn.start, end = fn.end;
|
||||||
|
|
||||||
|
data["format"] = "json";
|
||||||
|
data["start"] = start;
|
||||||
|
data["end"] = end;
|
||||||
|
data["timestamp"] = AIRTIME.showbuilder.getTimestamp();
|
||||||
|
data["instances"] = AIRTIME.showbuilder.getShowInstances();
|
||||||
|
|
||||||
|
if (fn.hasOwnProperty("ops")) {
|
||||||
|
data["myShows"] = fn.ops.myShows;
|
||||||
|
data["showFilter"] = fn.ops.showFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax( {
|
||||||
|
"dataType" : "json",
|
||||||
|
"type" : "GET",
|
||||||
|
"url" : "/showbuilder/check-builder-feed",
|
||||||
|
"data" : data,
|
||||||
|
"success" : function(json) {
|
||||||
|
if (json.update === true) {
|
||||||
|
oTable.fnDraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if the timeline view needs updating.
|
||||||
|
setInterval(checkScheduleUpdates, 5 * 1000); //need refresh in milliseconds
|
||||||
|
};
|
||||||
|
|
||||||
|
mod.onResize = function() {
|
||||||
|
|
||||||
|
clearTimeout(resizeTimeout);
|
||||||
|
resizeTimeout = setTimeout(setWidgetSize, 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
return AIRTIME;
|
||||||
|
|
||||||
$lib.hide();
|
|
||||||
$builder.width(screenWidth)
|
|
||||||
.find(".sb-timerange")
|
|
||||||
.prepend($toggleLib)
|
|
||||||
.find("#sb_date_start")
|
|
||||||
.css("margin-left", 30)
|
|
||||||
.end()
|
|
||||||
.end();
|
|
||||||
|
|
||||||
$toggleLib.removeClass("ui-state-hover");
|
|
||||||
schedTable.fnDraw();
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: "/usersettings/set-now-playing-screen-settings",
|
|
||||||
type: "POST",
|
|
||||||
data: {settings : {library : false}, format: "json"},
|
|
||||||
dataType: "json",
|
|
||||||
success: function(){}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$builder.find('legend').click(function(ev, item){
|
|
||||||
|
|
||||||
if ($fs.hasClass("closed")) {
|
|
||||||
|
|
||||||
$fs.removeClass("closed");
|
|
||||||
$builder.find('.dataTables_scrolling').css("max-height", widgetHeight - 150);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$fs.addClass("closed");
|
|
||||||
|
|
||||||
//set defaults for the options.
|
|
||||||
$fs.find('select').val(0);
|
|
||||||
$fs.find('input[type="checkbox"]').attr("checked", false);
|
|
||||||
$builder.find('.dataTables_scrolling').css("max-height", widgetHeight - 110);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//set click event for all my shows checkbox.
|
|
||||||
$builder.on("click", "#sb_my_shows", function(ev) {
|
|
||||||
|
|
||||||
if ($(this).is(':checked')) {
|
|
||||||
$(ev.delegateTarget).find('#sb_show_filter').val(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
showSearchSubmit();
|
|
||||||
});
|
|
||||||
|
|
||||||
//set select event for choosing a show.
|
|
||||||
$builder.on("change", '#sb_show_filter', function(ev) {
|
|
||||||
|
|
||||||
if ($(this).val() !== 0) {
|
|
||||||
$(ev.delegateTarget).find('#sb_my_shows').attr("checked", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
showSearchSubmit();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
function checkScheduleUpdates(){
|
|
||||||
var data = {},
|
|
||||||
oTable = $('#show_builder_table').dataTable(),
|
|
||||||
fn = oTable.fnSettings().fnServerData,
|
|
||||||
start = fn.start,
|
|
||||||
end = fn.end;
|
|
||||||
|
|
||||||
data["format"] = "json";
|
|
||||||
data["start"] = start;
|
|
||||||
data["end"] = end;
|
|
||||||
data["timestamp"] = AIRTIME.showbuilder.getTimestamp();
|
|
||||||
data["instances"] = AIRTIME.showbuilder.getShowInstances();
|
|
||||||
|
|
||||||
if (fn.hasOwnProperty("ops")) {
|
|
||||||
data["myShows"] = fn.ops.myShows;
|
|
||||||
data["showFilter"] = fn.ops.showFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
$.ajax( {
|
|
||||||
"dataType": "json",
|
|
||||||
"type": "GET",
|
|
||||||
"url": "/showbuilder/check-builder-feed",
|
|
||||||
"data": data,
|
|
||||||
"success": function(json) {
|
|
||||||
if (json.update === true) {
|
|
||||||
oTable.fnDraw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
//check if the timeline view needs updating.
|
|
||||||
setInterval(checkScheduleUpdates, 5 * 1000); //need refresh in milliseconds
|
|
||||||
};
|
|
||||||
|
|
||||||
mod.onResize = function() {
|
|
||||||
|
|
||||||
clearTimeout(resizeTimeout);
|
|
||||||
resizeTimeout = setTimeout(setWidgetSize, 100);
|
|
||||||
};
|
|
||||||
|
|
||||||
return AIRTIME;
|
|
||||||
|
|
||||||
} (AIRTIME || {}));
|
} (AIRTIME || {}));
|
||||||
|
|
||||||
$(document).ready(AIRTIME.builderMain.onReady);
|
$(document).ready(AIRTIME.builderMain.onReady);
|
||||||
|
|
|
@ -20,6 +20,11 @@ import traceback
|
||||||
|
|
||||||
AIRTIME_VERSION = "2.2.0"
|
AIRTIME_VERSION = "2.2.0"
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : Place these functions in some common module. Right now, media
|
||||||
|
# monitor uses the same functions and it would be better to reuse them
|
||||||
|
# instead of copy pasting them around
|
||||||
|
|
||||||
def to_unicode(obj, encoding='utf-8'):
|
def to_unicode(obj, encoding='utf-8'):
|
||||||
if isinstance(obj, basestring):
|
if isinstance(obj, basestring):
|
||||||
if not isinstance(obj, unicode):
|
if not isinstance(obj, unicode):
|
||||||
|
@ -39,7 +44,7 @@ def convert_dict_value_to_utf8(md):
|
||||||
# Airtime API Client
|
# Airtime API Client
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
class AirtimeApiClient():
|
class AirtimeApiClient(object):
|
||||||
|
|
||||||
# This is a little hacky fix so that I don't have to pass the config object
|
# This is a little hacky fix so that I don't have to pass the config object
|
||||||
# everywhere where AirtimeApiClient needs to be initialized
|
# everywhere where AirtimeApiClient needs to be initialized
|
||||||
|
@ -422,53 +427,46 @@ class AirtimeApiClient():
|
||||||
|
|
||||||
def send_media_monitor_requests(self, action_list, dry=False):
|
def send_media_monitor_requests(self, action_list, dry=False):
|
||||||
"""
|
"""
|
||||||
Send a gang of media monitor events at a time. actions_list is a list
|
Send a gang of media monitor events at a time. actions_list is a
|
||||||
of dictionaries where every dictionary is representing an action. Every
|
list of dictionaries where every dictionary is representing an
|
||||||
action dict must contain a 'mode' key that says what kind of action it
|
action. Every action dict must contain a 'mode' key that says
|
||||||
is and an optional 'is_record' key that says whether the show was
|
what kind of action it is and an optional 'is_record' key that
|
||||||
recorded or not. The value of this key does not matter, only if it's
|
says whether the show was recorded or not. The value of this key
|
||||||
present or not.
|
does not matter, only if it's present or not.
|
||||||
"""
|
"""
|
||||||
logger = self.logger
|
url = self.construct_url('reload_metadata_group')
|
||||||
try:
|
# We are assuming that action_list is a list of dictionaries such
|
||||||
url = self.construct_url('reload_metadata_group')
|
# that every dictionary represents the metadata of a file along
|
||||||
# We are assuming that action_list is a list of dictionaries such
|
# with a special mode key that is the action to be executed by the
|
||||||
# that every dictionary represents the metadata of a file along
|
# controller.
|
||||||
# with a special mode key that is the action to be executed by the
|
valid_actions = []
|
||||||
# controller.
|
# We could get a list of valid_actions in a much shorter way using
|
||||||
valid_actions = []
|
# filter but here we prefer a little more verbosity to help
|
||||||
# We could get a list of valid_actions in a much shorter way using
|
# debugging
|
||||||
# filter but here we prefer a little more verbosity to help
|
for action in action_list:
|
||||||
# debugging
|
if not 'mode' in action:
|
||||||
for action in action_list:
|
self.logger.debug("Warning: Trying to send a request element without a 'mode'")
|
||||||
if not 'mode' in action:
|
self.logger.debug("Here is the the request: '%s'" % str(action) )
|
||||||
self.logger.debug("Warning: Trying to send a request element without a 'mode'")
|
else:
|
||||||
self.logger.debug("Here is the the request: '%s'" % str(action) )
|
# We alias the value of is_record to true or false no
|
||||||
else:
|
# matter what it is based on if it's absent in the action
|
||||||
# We alias the value of is_record to true or false no
|
if 'is_record' not in action:
|
||||||
# matter what it is based on if it's absent in the action
|
action['is_record'] = 0
|
||||||
if 'is_record' not in action:
|
valid_actions.append(action)
|
||||||
action['is_record'] = 0
|
# Note that we must prefix every key with: mdX where x is a number
|
||||||
valid_actions.append(action)
|
# Is there a way to format the next line a little better? The
|
||||||
# Note that we must prefix every key with: mdX where x is a number
|
# parenthesis make the code almost unreadable
|
||||||
# Is there a way to format the next line a little better? The
|
md_list = dict((("md%d" % i), json.dumps(convert_dict_value_to_utf8(md))) \
|
||||||
# parenthesis make the code almost unreadable
|
for i,md in enumerate(valid_actions))
|
||||||
md_list = dict((("md%d" % i), json.dumps(convert_dict_value_to_utf8(md))) \
|
# For testing we add the following "dry" parameter to tell the
|
||||||
for i,md in enumerate(valid_actions))
|
# controller not to actually do any changes
|
||||||
# For testing we add the following "dry" parameter to tell the
|
if dry: md_list['dry'] = 1
|
||||||
# controller not to actually do any changes
|
self.logger.info("Pumping out %d requests..." % len(valid_actions))
|
||||||
if dry: md_list['dry'] = 1
|
data = urllib.urlencode(md_list)
|
||||||
self.logger.info("Pumping out %d requests..." % len(valid_actions))
|
req = urllib2.Request(url, data)
|
||||||
data = urllib.urlencode(md_list)
|
response = self.get_response_from_server(req)
|
||||||
req = urllib2.Request(url, data)
|
response = json.loads(response)
|
||||||
response = self.get_response_from_server(req)
|
return response
|
||||||
response = json.loads(response)
|
|
||||||
return response
|
|
||||||
except ValueError: raise
|
|
||||||
except Exception, e:
|
|
||||||
logger.error('Exception: %s', e)
|
|
||||||
logger.error("traceback: %s", traceback.format_exc())
|
|
||||||
raise
|
|
||||||
|
|
||||||
#returns a list of all db files for a given directory in JSON format:
|
#returns a list of all db files for a given directory in JSON format:
|
||||||
#{"files":["path/to/file1", "path/to/file2"]}
|
#{"files":["path/to/file1", "path/to/file2"]}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
import traceback
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Python part of radio playout (pypo)
|
Python part of radio playout (pypo)
|
||||||
|
@ -102,6 +103,24 @@ class Notify:
|
||||||
logger.debug('# Calling server to update webstream data #')
|
logger.debug('# Calling server to update webstream data #')
|
||||||
logger.debug('#################################################')
|
logger.debug('#################################################')
|
||||||
response = self.api_client.notify_webstream_data(data, media_id)
|
response = self.api_client.notify_webstream_data(data, media_id)
|
||||||
|
logger.debug("Response: " + json.dumps(response))
|
||||||
|
|
||||||
|
def run_with_options(self, options):
|
||||||
|
if options.error and options.stream_id:
|
||||||
|
self.notify_liquidsoap_status(options.error, options.stream_id, options.time)
|
||||||
|
elif options.connect and options.stream_id:
|
||||||
|
self.notify_liquidsoap_status("OK", options.stream_id, options.time)
|
||||||
|
elif options.source_name and options.source_status:
|
||||||
|
self.notify_source_status(options.source_name, options.source_status)
|
||||||
|
elif options.webstream:
|
||||||
|
self.notify_webstream_data(options.webstream, options.media_id)
|
||||||
|
elif options.media_id:
|
||||||
|
self.notify_media_start_playing(options.media_id)
|
||||||
|
elif options.liquidsoap_started:
|
||||||
|
self.notify_liquidsoap_started()
|
||||||
|
else:
|
||||||
|
logger.debug("Unrecognized option in options(%s). Doing nothing" \
|
||||||
|
% str(options))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -112,41 +131,9 @@ if __name__ == '__main__':
|
||||||
print '#########################################'
|
print '#########################################'
|
||||||
|
|
||||||
# initialize
|
# initialize
|
||||||
if options.error and options.stream_id:
|
try:
|
||||||
try:
|
n = Notify()
|
||||||
n = Notify()
|
n.run_with_options(options)
|
||||||
n.notify_liquidsoap_status(options.error, options.stream_id, options.time)
|
except Exception as e:
|
||||||
except Exception, e:
|
print( traceback.format_exc() )
|
||||||
print e
|
|
||||||
elif options.connect and options.stream_id:
|
|
||||||
try:
|
|
||||||
n = Notify()
|
|
||||||
n.notify_liquidsoap_status("OK", options.stream_id, options.time)
|
|
||||||
except Exception, e:
|
|
||||||
print e
|
|
||||||
elif options.source_name and options.source_status:
|
|
||||||
try:
|
|
||||||
n = Notify()
|
|
||||||
n.notify_source_status(options.source_name, options.source_status)
|
|
||||||
except Exception, e:
|
|
||||||
print e
|
|
||||||
elif options.webstream:
|
|
||||||
try:
|
|
||||||
n = Notify()
|
|
||||||
n.notify_webstream_data(options.webstream, options.media_id)
|
|
||||||
except Exception, e:
|
|
||||||
print e
|
|
||||||
elif options.media_id:
|
|
||||||
|
|
||||||
try:
|
|
||||||
n = Notify()
|
|
||||||
n.notify_media_start_playing(options.media_id)
|
|
||||||
except Exception, e:
|
|
||||||
print e
|
|
||||||
elif options.liquidsoap_started:
|
|
||||||
try:
|
|
||||||
n = Notify()
|
|
||||||
n.notify_liquidsoap_started()
|
|
||||||
except Exception, e:
|
|
||||||
print e
|
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ logger.addHandler(ch)
|
||||||
if (os.geteuid() != 0):
|
if (os.geteuid() != 0):
|
||||||
print 'Must be a root user.'
|
print 'Must be a root user.'
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
# loading config file
|
# loading config file
|
||||||
try:
|
try:
|
||||||
config = ConfigObj('/etc/airtime/media-monitor.cfg')
|
config = ConfigObj('/etc/airtime/media-monitor.cfg')
|
||||||
|
@ -66,12 +66,12 @@ def copy_or_move_files_to(paths, dest, flag):
|
||||||
print "Cannot find file or path: %s" % path
|
print "Cannot find file or path: %s" % path
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print "Error: ", e
|
print "Error: ", e
|
||||||
|
|
||||||
def format_dir_string(path):
|
def format_dir_string(path):
|
||||||
if(path[-1] != '/'):
|
if(path[-1] != '/'):
|
||||||
path = path+'/'
|
path = path+'/'
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def helper_get_stor_dir():
|
def helper_get_stor_dir():
|
||||||
res = api_client.list_all_watched_dirs()
|
res = api_client.list_all_watched_dirs()
|
||||||
if(res is None):
|
if(res is None):
|
||||||
|
@ -87,18 +87,18 @@ def checkOtherOption(args):
|
||||||
for i in args:
|
for i in args:
|
||||||
if(i[0] == '-'):
|
if(i[0] == '-'):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def errorIfMultipleOption(args, msg=''):
|
def errorIfMultipleOption(args, msg=''):
|
||||||
if(checkOtherOption(args)):
|
if(checkOtherOption(args)):
|
||||||
if(msg != ''):
|
if(msg != ''):
|
||||||
raise OptionValueError(msg)
|
raise OptionValueError(msg)
|
||||||
else:
|
else:
|
||||||
raise OptionValueError("This option cannot be combined with other options")
|
raise OptionValueError("This option cannot be combined with other options")
|
||||||
|
|
||||||
def printHelp():
|
def printHelp():
|
||||||
storage_dir = helper_get_stor_dir()
|
storage_dir = helper_get_stor_dir()
|
||||||
if(storage_dir is None):
|
if(storage_dir is None):
|
||||||
storage_dir = "Unknown"
|
storage_dir = "Unknown"
|
||||||
else:
|
else:
|
||||||
storage_dir += "imported/"
|
storage_dir += "imported/"
|
||||||
print """
|
print """
|
||||||
|
@ -111,15 +111,15 @@ There are two ways to import audio files into Airtime:
|
||||||
|
|
||||||
Copied or moved files will be placed into the folder:
|
Copied or moved files will be placed into the folder:
|
||||||
%s
|
%s
|
||||||
|
|
||||||
Files will be automatically organized into the structure
|
Files will be automatically organized into the structure
|
||||||
"Artist/Album/TrackNumber-TrackName-Bitrate.file_extension".
|
"Artist/Album/TrackNumber-TrackName-Bitrate.file_extension".
|
||||||
|
|
||||||
2) Use airtime-import to add a folder to the Airtime library ("watch" a folder).
|
2) Use airtime-import to add a folder to the Airtime library ("watch" a folder).
|
||||||
|
|
||||||
All the files in the watched folder will be imported to Airtime and the
|
All the files in the watched folder will be imported to Airtime and the
|
||||||
folder will be monitored to automatically detect any changes. Hence any
|
folder will be monitored to automatically detect any changes. Hence any
|
||||||
changes done in the folder(add, delete, edit a file) will trigger
|
changes done in the folder(add, delete, edit a file) will trigger
|
||||||
updates in Airtime library.
|
updates in Airtime library.
|
||||||
""" % storage_dir
|
""" % storage_dir
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
|
@ -209,7 +209,7 @@ def WatchRemoveAction(option, opt, value, parser):
|
||||||
print "Removing the watch folder failed: %s" % res['msg']['error']
|
print "Removing the watch folder failed: %s" % res['msg']['error']
|
||||||
else:
|
else:
|
||||||
print "The given path is not a directory: %s" % path
|
print "The given path is not a directory: %s" % path
|
||||||
|
|
||||||
def StorageSetAction(option, opt, value, parser):
|
def StorageSetAction(option, opt, value, parser):
|
||||||
bypass = False
|
bypass = False
|
||||||
isF = '-f' in parser.rargs
|
isF = '-f' in parser.rargs
|
||||||
|
@ -231,12 +231,12 @@ def StorageSetAction(option, opt, value, parser):
|
||||||
confirm = confirm or 'N'
|
confirm = confirm or 'N'
|
||||||
if(confirm == 'n' or confirm =='N'):
|
if(confirm == 'n' or confirm =='N'):
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if(len(parser.rargs) > 1):
|
if(len(parser.rargs) > 1):
|
||||||
raise OptionValueError("Too many arguments. This option requires exactly one argument.")
|
raise OptionValueError("Too many arguments. This option requires exactly one argument.")
|
||||||
elif(len(parser.rargs) == 0 ):
|
elif(len(parser.rargs) == 0 ):
|
||||||
raise OptionValueError("No argument found. This option requires exactly one argument.")
|
raise OptionValueError("No argument found. This option requires exactly one argument.")
|
||||||
|
|
||||||
path = parser.rargs[0]
|
path = parser.rargs[0]
|
||||||
if (path[0] == "/" or path[0] == "~"):
|
if (path[0] == "/" or path[0] == "~"):
|
||||||
path = os.path.realpath(path)
|
path = os.path.realpath(path)
|
||||||
|
@ -254,17 +254,17 @@ def StorageSetAction(option, opt, value, parser):
|
||||||
print "Setting storage folder failed: %s" % res['msg']['error']
|
print "Setting storage folder failed: %s" % res['msg']['error']
|
||||||
else:
|
else:
|
||||||
print "The given path is not a directory: %s" % path
|
print "The given path is not a directory: %s" % path
|
||||||
|
|
||||||
def StorageGetAction(option, opt, value, parser):
|
def StorageGetAction(option, opt, value, parser):
|
||||||
errorIfMultipleOption(parser.rargs)
|
errorIfMultipleOption(parser.rargs)
|
||||||
if(len(parser.rargs) > 0):
|
if(len(parser.rargs) > 0):
|
||||||
raise OptionValueError("This option does not take any arguments.")
|
raise OptionValueError("This option does not take any arguments.")
|
||||||
print helper_get_stor_dir()
|
print helper_get_stor_dir()
|
||||||
|
|
||||||
class OptionValueError(RuntimeError):
|
class OptionValueError(RuntimeError):
|
||||||
def __init__(self, msg):
|
def __init__(self, msg):
|
||||||
self.msg = msg
|
self.msg = msg
|
||||||
|
|
||||||
usage = """[-c|--copy FILE/DIR [FILE/DIR...]] [-m|--move FILE/DIR [FILE/DIR...]]
|
usage = """[-c|--copy FILE/DIR [FILE/DIR...]] [-m|--move FILE/DIR [FILE/DIR...]]
|
||||||
[--watch-add DIR] [--watch-list] [--watch-remove DIR]
|
[--watch-add DIR] [--watch-list] [--watch-remove DIR]
|
||||||
[--storage-dir-set DIR] [--storage-dir-get]"""
|
[--storage-dir-set DIR] [--storage-dir-get]"""
|
||||||
|
@ -293,7 +293,7 @@ if('-h' in sys.argv):
|
||||||
if(len(sys.argv) == 1 or '-' not in sys.argv[1]):
|
if(len(sys.argv) == 1 or '-' not in sys.argv[1]):
|
||||||
printHelp()
|
printHelp()
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
(option, args) = parser.parse_args()
|
(option, args) = parser.parse_args()
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
|
@ -306,7 +306,7 @@ except Exception, e:
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
printHelp()
|
printHelp()
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
if option.help:
|
if option.help:
|
||||||
printHelp()
|
printHelp()
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
Loading…
Reference in New Issue