Merge branch 'devel' of dev.sourcefabric.org:airtime into devel
This commit is contained in:
commit
6fc41ee4bf
|
@ -9,12 +9,12 @@ class Application_Form_SmartPlaylistCriteria extends Zend_Form_SubForm
|
||||||
$criteriaOptions = array(
|
$criteriaOptions = array(
|
||||||
0 => "Select criteria",
|
0 => "Select criteria",
|
||||||
"album_title" => "Album",
|
"album_title" => "Album",
|
||||||
"artist_name" => "Artist",
|
|
||||||
"bit_rate" => "Bit Rate",
|
"bit_rate" => "Bit Rate",
|
||||||
"bpm" => "Bpm",
|
"bpm" => "Bpm",
|
||||||
"comments" => "Comments",
|
"comments" => "Comments",
|
||||||
"composer" => "Composer",
|
"composer" => "Composer",
|
||||||
"conductor" => "Conductor",
|
"conductor" => "Conductor",
|
||||||
|
"artist_name" => "Creator",
|
||||||
"disc_number" => "Disc Number",
|
"disc_number" => "Disc Number",
|
||||||
"genre" => "Genre",
|
"genre" => "Genre",
|
||||||
"isrc_number" => "ISRC",
|
"isrc_number" => "ISRC",
|
||||||
|
|
|
@ -1,35 +1,11 @@
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
setSmartPlaylistEvents();
|
setSmartPlaylistEvents();
|
||||||
|
|
||||||
$(".playlist_type_help_icon").qtip({
|
|
||||||
content: {
|
|
||||||
text: "A static playlist will save the criteria and generate the playlist content immediately." +
|
|
||||||
"This allows you to edit and view it in the Playlist Builder before adding it to a show.<br /><br />" +
|
|
||||||
"A dynamic playlist will only save the criteria. The playlist content will get generated upon " +
|
|
||||||
"adding it to a show. You will not be able to view and edit it in the Playlist Builder."
|
|
||||||
},
|
|
||||||
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"
|
|
||||||
},
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function setSmartPlaylistEvents() {
|
function setSmartPlaylistEvents() {
|
||||||
var form = $('#smart-playlist-form');
|
var form = $('#smart-playlist-form');
|
||||||
|
|
||||||
form.find('.criteria_add').live("click", function(){
|
form.find('.criteria_add').live('click', function(){
|
||||||
var div = $('dd[id="sp_criteria-element"]').children('div:visible:last').next();
|
var div = $('dd[id="sp_criteria-element"]').children('div:visible:last').next();
|
||||||
|
|
||||||
div.show();
|
div.show();
|
||||||
|
@ -42,7 +18,7 @@ function setSmartPlaylistEvents() {
|
||||||
removeButtonCheck();
|
removeButtonCheck();
|
||||||
});
|
});
|
||||||
|
|
||||||
form.find('a[id^="criteria_remove"]').live("click", function(){
|
form.find('a[id^="criteria_remove"]').live('click', function(){
|
||||||
var curr = $(this).parent();
|
var curr = $(this).parent();
|
||||||
var curr_pos = curr.index();
|
var curr_pos = curr.index();
|
||||||
var list = curr.parent();
|
var list = curr.parent();
|
||||||
|
@ -207,6 +183,30 @@ function setupUI() {
|
||||||
applyPlatformOpacityRules: false
|
applyPlatformOpacityRules: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(".playlist_type_help_icon").qtip({
|
||||||
|
content: {
|
||||||
|
text: "A static playlist will save the criteria and generate the playlist content immediately." +
|
||||||
|
"This allows you to edit and view it in the Playlist Builder before adding it to a show.<br /><br />" +
|
||||||
|
"A dynamic playlist will only save the criteria. The playlist content will get generated upon " +
|
||||||
|
"adding it to a show. You will not be able to view and edit it in the Playlist Builder."
|
||||||
|
},
|
||||||
|
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"
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function enableAndShowExtraField(valEle, index) {
|
function enableAndShowExtraField(valEle, index) {
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
def get_process_output(command):
|
||||||
|
"""
|
||||||
|
Run subprocess and return stdout
|
||||||
|
"""
|
||||||
|
p = Popen(command, shell=True, stdout=PIPE)
|
||||||
|
return p.communicate()[0].strip()
|
||||||
|
|
||||||
|
def run_process(command):
|
||||||
|
"""
|
||||||
|
Run subprocess and return "return code"
|
||||||
|
"""
|
||||||
|
p = Popen(command, shell=True)
|
||||||
|
return os.waitpid(p.pid, 0)[1]
|
||||||
|
|
||||||
|
def get_mime_type(file_path):
|
||||||
|
"""
|
||||||
|
Attempts to get the mime type but will return prematurely if the process
|
||||||
|
takes longer than 5 seconds. Note that this function should only be called
|
||||||
|
for files which do not have a mp3/ogg/flac extension.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return get_process_output("timeout 5 file -b --mime-type %s" % file_path)
|
||||||
|
|
||||||
|
def duplicate_file(file_path):
|
||||||
|
"""
|
||||||
|
Makes a duplicate of the file and returns the path of this duplicate file.
|
||||||
|
"""
|
||||||
|
fsrc = open(file_path, 'r')
|
||||||
|
fdst = tempfile.NamedTemporaryFile(delete=False)
|
||||||
|
|
||||||
|
print "Copying %s to %s" % (file_path, fdst.name)
|
||||||
|
|
||||||
|
shutil.copyfileobj(fsrc, fdst)
|
||||||
|
|
||||||
|
fsrc.close()
|
||||||
|
fdst.close()
|
||||||
|
|
||||||
|
return fdst.name
|
||||||
|
|
||||||
|
def calculate_replay_gain(file_path):
|
||||||
|
"""
|
||||||
|
This function accepts files of type mp3/ogg/flac and returns a calculated ReplayGain value in dB.
|
||||||
|
If the value cannot be calculated for some reason, then we default to 0 (Unity Gain).
|
||||||
|
|
||||||
|
http://wiki.hydrogenaudio.org/index.php?title=ReplayGain_1.0_specification
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
"""
|
||||||
|
Making a duplicate is required because the ReplayGain extraction utilities we use
|
||||||
|
make unwanted modifications to the file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
search = None
|
||||||
|
temp_file_path = duplicate_file(file_path)
|
||||||
|
|
||||||
|
if re.search(r'mp3$', temp_file_path, re.IGNORECASE) or get_mime_type(temp_file_path) == "audio/mpeg":
|
||||||
|
if run_process("which mp3gain > /dev/null") == 0:
|
||||||
|
out = get_process_output('mp3gain -q "%s" 2> /dev/null' % temp_file_path)
|
||||||
|
search = re.search(r'Recommended "Track" dB change: (.*)', out)
|
||||||
|
else:
|
||||||
|
print "mp3gain not found"
|
||||||
|
#Log warning
|
||||||
|
elif re.search(r'ogg$', temp_file_path, re.IGNORECASE) or get_mime_type(temp_file_path) == "application/ogg":
|
||||||
|
if run_process("which vorbisgain > /dev/null && which ogginfo > /dev/null") == 0:
|
||||||
|
run_process('vorbisgain -q -f "%s" 2>/dev/null >/dev/null' % temp_file_path)
|
||||||
|
out = get_process_output('ogginfo "%s"' % temp_file_path)
|
||||||
|
search = re.search(r'REPLAYGAIN_TRACK_GAIN=(.*) dB', out)
|
||||||
|
else:
|
||||||
|
print "vorbisgain/ogginfo not found"
|
||||||
|
#Log warning
|
||||||
|
elif re.search(r'flac$', temp_file_path, re.IGNORECASE) or get_mime_type(temp_file_path) == "audio/x-flac":
|
||||||
|
if run_process("which metaflac > /dev/null") == 0:
|
||||||
|
out = get_process_output('metaflac --show-tag=REPLAYGAIN_TRACK_GAIN "%s"' % temp_file_path)
|
||||||
|
search = re.search(r'REPLAYGAIN_TRACK_GAIN=(.*) dB', out)
|
||||||
|
else:
|
||||||
|
print "metaflac not found"
|
||||||
|
#Log warning
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
#Log unknown file type.
|
||||||
|
|
||||||
|
#no longer need the temp, file simply remove it.
|
||||||
|
os.remove(temp_file_path)
|
||||||
|
except Exception, e:
|
||||||
|
print e
|
||||||
|
|
||||||
|
replay_gain = 0
|
||||||
|
if search:
|
||||||
|
matches = search.groups()
|
||||||
|
if len(matches) == 1:
|
||||||
|
replay_gain = matches[0]
|
||||||
|
|
||||||
|
return replay_gain
|
||||||
|
|
||||||
|
|
||||||
|
# Example of running from command line:
|
||||||
|
# python replay_gain.py /path/to/filename.mp3
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print calculate_replay_gain(sys.argv[1])
|
|
@ -20,7 +20,14 @@ from threading import Thread
|
||||||
|
|
||||||
import mutagen
|
import mutagen
|
||||||
|
|
||||||
from api_clients import api_client
|
from api_clients import api_client as apc
|
||||||
|
|
||||||
|
def api_client(logger):
|
||||||
|
"""
|
||||||
|
api_client returns the correct instance of AirtimeApiClient. Although there is only one
|
||||||
|
instance to choose from at the moment.
|
||||||
|
"""
|
||||||
|
return apc.AirtimeApiClient(logger)
|
||||||
|
|
||||||
# loading config file
|
# loading config file
|
||||||
try:
|
try:
|
||||||
|
@ -30,14 +37,17 @@ except Exception, e:
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
def getDateTimeObj(time):
|
def getDateTimeObj(time):
|
||||||
|
# TODO : clean up for this function later.
|
||||||
|
# - use tuples to parse result from split (instead of indices)
|
||||||
|
# - perhaps validate the input before doing dangerous casts?
|
||||||
|
# - rename this function to follow the standard convention
|
||||||
|
# - rename time to something else so that the module name does not get
|
||||||
|
# shadowed
|
||||||
|
# - add docstring to document all behaviour of this function
|
||||||
timeinfo = time.split(" ")
|
timeinfo = time.split(" ")
|
||||||
date = timeinfo[0].split("-")
|
date = [ int(x) for x in timeinfo[0].split("-") ]
|
||||||
time = timeinfo[1].split(":")
|
my_time = [ int(x) for x in timeinfo[1].split(":") ]
|
||||||
|
return datetime.datetime(date[0], date[1], date[2], my_time[0], my_time[1], my_time[2], 0, None)
|
||||||
date = map(int, date)
|
|
||||||
time = map(int, time)
|
|
||||||
|
|
||||||
return datetime.datetime(date[0], date[1], date[2], time[0], time[1], time[2], 0, None)
|
|
||||||
|
|
||||||
PUSH_INTERVAL = 2
|
PUSH_INTERVAL = 2
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue