diff --git a/airtime_mvc/application/models/Datatables.php b/airtime_mvc/application/models/Datatables.php index 993c17516..e6f1ec1d1 100644 --- a/airtime_mvc/application/models/Datatables.php +++ b/airtime_mvc/application/models/Datatables.php @@ -39,15 +39,17 @@ class Application_Model_Datatables /* * query used to return data for a paginated/searchable datatable. */ - public static function findEntries($con, $displayColumns, $fromTable, $data, $dataProp = "aaData") + public static function findEntries($con, $displayColumns, $fromTable, + $data, $dataProp = "aaData") { $librarySetting = Application_Model_Preference::getCurrentLibraryTableSetting(); + //$displayColumns[] = 'owner'; // map that maps original column position to db name $current2dbname = array(); // array of search terms - $orig2searchTerm= array(); - foreach ($data as $key=>$d) { + $orig2searchTerm = array(); + foreach ($data as $key => $d) { if (strstr($key, "mDataProp_")) { list($dump, $index) = explode("_", $key); $current2dbname[$index] = $d; @@ -82,6 +84,7 @@ class Application_Model_Datatables $sql = $selectorCount." FROM ".$fromTable; $sqlTotalRows = $sql; + if (isset($searchTerms)) { $searchCols = array(); for ($i = 0; $i < $data["iColumns"]; $i++) { @@ -135,8 +138,8 @@ class Application_Model_Datatables $sql .= " OFFSET ".$data["iDisplayStart"]." LIMIT ".$displayLength; } } - try { + $r = $con->query($sqlTotalRows); $totalRows = $r->fetchColumn(0); @@ -173,12 +176,11 @@ class Application_Model_Datatables } catch (Exception $e) { Logging::debug($e->getMessage()); } - return array( - "sEcho" => intval($data["sEcho"]), + "sEcho" => intval($data["sEcho"]), "iTotalDisplayRecords" => intval($totalDisplayRows), - "iTotalRecords" => intval($totalRows), - $dataProp => $results + "iTotalRecords" => intval($totalRows), + $dataProp => $results ); } } diff --git a/airtime_mvc/application/models/PlayoutHistory.php b/airtime_mvc/application/models/PlayoutHistory.php index c4a61a78c..3ea640468 100644 --- a/airtime_mvc/application/models/PlayoutHistory.php +++ b/airtime_mvc/application/models/PlayoutHistory.php @@ -16,22 +16,22 @@ class Application_Model_PlayoutHistory private $opts; private $mDataPropMap = array( - "artist" => "file.artist_name", - "title" => "file.track_title", - "played" => "playout.played", - "length" => "file.length", - "composer" => "file.composer", + "artist" => "file.artist_name", + "title" => "file.track_title", + "played" => "playout.played", + "length" => "file.length", + "composer" => "file.composer", "copyright" => "file.copyright", ); public function __construct($p_startDT, $p_endDT, $p_opts) { - $this->con = Propel::getConnection(CcSchedulePeer::DATABASE_NAME); - $this->startDT = $p_startDT; - $this->endDT = $p_endDT; - $this->timezone = date_default_timezone_get(); + $this->con = Propel::getConnection(CcSchedulePeer::DATABASE_NAME); + $this->startDT = $p_startDT; + $this->endDT = $p_endDT; + $this->timezone = date_default_timezone_get(); $this->epoch_now = time(); - $this->opts = $p_opts; + $this->opts = $p_opts; } /* diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index 59f335c7a..319336941 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -635,9 +635,11 @@ class Application_Model_StoredFile $displayColumns = array("id", "track_title", "artist_name", "album_title", "genre", "length", "year", "utime", "mtime", "ftype", "track_number", "mood", "bpm", "composer", "info_url", "bit_rate", "sample_rate", "isrc_number", "encoded_by", "label", "copyright", "mime", - "language", "filepath" + "language", "filepath","owner" ); + //Logging::info($datatables); + $plSelect = array(); $blSelect = array(); $fileSelect = array(); @@ -647,7 +649,7 @@ class Application_Model_StoredFile if ($key === "id") { $plSelect[] = "PL.id AS ".$key; $blSelect[] = "BL.id AS ".$key; - $fileSelect[] = $key; + $fileSelect[] = "FILES.id AS $key"; $streamSelect[] = "ws.id AS ".$key; } elseif ($key === "track_title") { $plSelect[] = "name AS ".$key; @@ -664,6 +666,11 @@ class Application_Model_StoredFile $blSelect[] = "login AS ".$key; $fileSelect[] = $key; $streamSelect[] = "login AS ".$key; + } elseif ($key === "owner") { + $plSelect[] = "login AS ".$key; + $blSelect[] = "login AS ".$key; + $fileSelect[] = "sub.login AS $key"; + $streamSelect[] = "login AS ".$key; } //same columns in each table. else if (in_array($key, array("length", "utime", "mtime"))) { @@ -705,7 +712,8 @@ class Application_Model_StoredFile $plTable = "({$plSelect} FROM cc_playlist AS PL LEFT JOIN cc_subjs AS sub ON (sub.id = PL.creator_id))"; $blTable = "({$blSelect} FROM cc_block AS BL LEFT JOIN cc_subjs AS sub ON (sub.id = BL.creator_id))"; - $fileTable = "({$fileSelect} FROM cc_files AS FILES WHERE file_exists = 'TRUE')"; + $fileTable = "({$fileSelect} FROM cc_files AS FILES LEFT JOIN cc_subjs AS sub ON (sub.id = FILES.owner_id) WHERE file_exists = 'TRUE')"; + //$fileTable = "({$fileSelect} FROM cc_files AS FILES WHERE file_exists = 'TRUE')"; $streamTable = "({$streamSelect} FROM cc_webstream AS ws LEFT JOIN cc_subjs AS sub ON (sub.id = ws.creator_id))"; $unionTable = "({$plTable} UNION {$blTable} UNION {$fileTable} UNION {$streamTable}) AS RESULTS"; diff --git a/airtime_mvc/public/js/airtime/library/library.js b/airtime_mvc/public/js/airtime/library/library.js index 736e7023d..c2d5f8e70 100644 --- a/airtime_mvc/public/js/airtime/library/library.js +++ b/airtime_mvc/public/js/airtime/library/library.js @@ -9,32 +9,32 @@ var AIRTIME = (function(AIRTIME) { visibleChosenItems = {}; var criteriaTypes = { - 0 : "", + 0 : "", "album_title" : "s", "artist_name" : "s", - "bit_rate" : "n", - "bpm" : "n", - "comments" : "s", - "composer" : "s", - "conductor" : "s", - "utime" : "n", - "mtime" : "n", - "lptime" : "n", + "bit_rate" : "n", + "bpm" : "n", + "comments" : "s", + "composer" : "s", + "conductor" : "s", + "utime" : "n", + "mtime" : "n", + "lptime" : "n", "disc_number" : "n", - "genre" : "s", + "genre" : "s", "isrc_number" : "s", - "label" : "s", - "language" : "s", - "length" : "n", - "lyricist" : "s", - "mood" : "s", - "name" : "s", - "orchestra" : "s", - "rating" : "n", + "label" : "s", + "language" : "s", + "length" : "n", + "lyricist" : "s", + "mood" : "s", + "name" : "s", + "orchestra" : "s", + "rating" : "n", "sample_rate" : "n", "track_title" : "s", - "track_num" : "n", - "year" : "n" + "track_num" : "n", + "year" : "n" }; if (AIRTIME.library === undefined) { @@ -387,30 +387,31 @@ var AIRTIME = (function(AIRTIME) { //put hidden columns at the top to insure they can never be visible on the table through column reordering. "aoColumns": [ - /* ftype */ {"sTitle": "", "mDataProp": "ftype", "bSearchable": false, "bVisible": false}, - /* Checkbox */ {"sTitle": "", "mDataProp": "checkbox", "bSortable": false, "bSearchable": false, "sWidth": "25px", "sClass": "library_checkbox"}, - /* Type */ {"sTitle": "", "mDataProp": "image", "bSearchable": false, "sWidth": "25px", "sClass": "library_type", "iDataSort": 0}, - /* Title */ {"sTitle": "Title", "mDataProp": "track_title", "sClass": "library_title", "sWidth": "170px"}, - /* Creator */ {"sTitle": "Creator", "mDataProp": "artist_name", "sClass": "library_creator", "sWidth": "160px"}, - /* Album */ {"sTitle": "Album", "mDataProp": "album_title", "sClass": "library_album", "sWidth": "150px"}, - /* Genre */ {"sTitle": "Genre", "mDataProp": "genre", "bVisible": false, "sClass": "library_genre", "sWidth": "100px"}, - /* Year */ {"sTitle": "Year", "mDataProp": "year", "bVisible": false, "sClass": "library_year", "sWidth": "60px"}, - /* Length */ {"sTitle": "Length", "mDataProp": "length", "sClass": "library_length", "sWidth": "80px"}, - /* Upload Time */ {"sTitle": "Uploaded", "mDataProp": "utime", "sClass": "library_upload_time", "sWidth": "125px"}, - /* Last Modified */ {"sTitle": "Last Modified", "mDataProp": "mtime", "bVisible": false, "sClass": "library_modified_time", "sWidth": "125px"}, - /* Track Number */ {"sTitle": "Track", "mDataProp": "track_number", "bVisible": false, "sClass": "library_track", "sWidth": "65px"}, - /* Mood */ {"sTitle": "Mood", "mDataProp": "mood", "bVisible": false, "sClass": "library_mood", "sWidth": "70px"}, - /* BPM */ {"sTitle": "BPM", "mDataProp": "bpm", "bVisible": false, "sClass": "library_bpm", "sWidth": "50px"}, - /* Composer */ {"sTitle": "Composer", "mDataProp": "composer", "bVisible": false, "sClass": "library_composer", "sWidth": "150px"}, - /* Website */ {"sTitle": "Website", "mDataProp": "info_url", "bVisible": false, "sClass": "library_url", "sWidth": "150px"}, - /* Bit Rate */ {"sTitle": "Bit Rate", "mDataProp": "bit_rate", "bVisible": false, "sClass": "library_bitrate", "sWidth": "80px"}, - /* Sample Rate */ {"sTitle": "Sample", "mDataProp": "sample_rate", "bVisible": false, "sClass": "library_sr", "sWidth": "80px"}, - /* ISRC Number */ {"sTitle": "ISRC", "mDataProp": "isrc_number", "bVisible": false, "sClass": "library_isrc", "sWidth": "150px"}, - /* Encoded */ {"sTitle": "Encoded", "mDataProp": "encoded_by", "bVisible": false, "sClass": "library_encoded", "sWidth": "150px"}, - /* Label */ {"sTitle": "Label", "mDataProp": "label", "bVisible": false, "sClass": "library_label", "sWidth": "125px"}, - /* Copyright */ {"sTitle": "Copyright", "mDataProp": "copyright", "bVisible": false, "sClass": "library_copyright", "sWidth": "125px"}, - /* Mime */ {"sTitle": "Mime", "mDataProp": "mime", "bVisible": false, "sClass": "library_mime", "sWidth": "80px"}, - /* Language */ {"sTitle": "Language", "mDataProp": "language", "bVisible": false, "sClass": "library_language", "sWidth": "125px"} + /* ftype */ { "sTitle" : "" , "mDataProp" : "ftype" , "bSearchable" : false , "bVisible" : false } , + /* Checkbox */ { "sTitle" : "" , "mDataProp" : "checkbox" , "bSortable" : false , "bSearchable" : false , "sWidth" : "25px" , "sClass" : "library_checkbox" } , + /* Type */ { "sTitle" : "" , "mDataProp" : "image" , "bSearchable" : false , "sWidth" : "25px" , "sClass" : "library_type" , "iDataSort" : 0 } , + /* Title */ { "sTitle" : "Title" , "mDataProp" : "track_title" , "sClass" : "library_title" , "sWidth" : "170px" } , + /* Creator */ { "sTitle" : "Creator" , "mDataProp" : "artist_name" , "sClass" : "library_creator" , "sWidth" : "160px" } , + /* Album */ { "sTitle" : "Album" , "mDataProp" : "album_title" , "sClass" : "library_album" , "sWidth" : "150px" } , + /* Genre */ { "sTitle" : "Genre" , "mDataProp" : "genre" , "bVisible" : false , "sClass" : "library_genre" , "sWidth" : "100px" } , + /* Year */ { "sTitle" : "Year" , "mDataProp" : "year" , "bVisible" : false , "sClass" : "library_year" , "sWidth" : "60px" } , + /* Length */ { "sTitle" : "Length" , "mDataProp" : "length" , "sClass" : "library_length" , "sWidth" : "80px" } , + /* Upload Time */ { "sTitle" : "Uploaded" , "mDataProp" : "utime" , "sClass" : "library_upload_time" , "sWidth" : "125px" } , + /* Last Modified */ { "sTitle" : "Last Modified" , "mDataProp" : "mtime" , "bVisible" : false , "sClass" : "library_modified_time" , "sWidth" : "125px" } , + /* Track Number */ { "sTitle" : "Track" , "mDataProp" : "track_number" , "bVisible" : false , "sClass" : "library_track" , "sWidth" : "65px" } , + /* Mood */ { "sTitle" : "Mood" , "mDataProp" : "mood" , "bVisible" : false , "sClass" : "library_mood" , "sWidth" : "70px" } , + /* BPM */ { "sTitle" : "BPM" , "mDataProp" : "bpm" , "bVisible" : false , "sClass" : "library_bpm" , "sWidth" : "50px" } , + /* Composer */ { "sTitle" : "Composer" , "mDataProp" : "composer" , "bVisible" : false , "sClass" : "library_composer" , "sWidth" : "150px" } , + /* Website */ { "sTitle" : "Website" , "mDataProp" : "info_url" , "bVisible" : false , "sClass" : "library_url" , "sWidth" : "150px" } , + /* Bit Rate */ { "sTitle" : "Bit Rate" , "mDataProp" : "bit_rate" , "bVisible" : false , "sClass" : "library_bitrate" , "sWidth" : "80px" } , + /* Sample Rate */ { "sTitle" : "Sample" , "mDataProp" : "sample_rate" , "bVisible" : false , "sClass" : "library_sr" , "sWidth" : "80px" } , + /* ISRC Number */ { "sTitle" : "ISRC" , "mDataProp" : "isrc_number" , "bVisible" : false , "sClass" : "library_isrc" , "sWidth" : "150px" } , + /* Encoded */ { "sTitle" : "Encoded" , "mDataProp" : "encoded_by" , "bVisible" : false , "sClass" : "library_encoded" , "sWidth" : "150px" } , + /* Label */ { "sTitle" : "Label" , "mDataProp" : "label" , "bVisible" : false , "sClass" : "library_label" , "sWidth" : "125px" } , + /* Copyright */ { "sTitle" : "Copyright" , "mDataProp" : "copyright" , "bVisible" : false , "sClass" : "library_copyright" , "sWidth" : "125px" } , + /* Mime */ { "sTitle" : "Mime" , "mDataProp" : "mime" , "bVisible" : false , "sClass" : "library_mime" , "sWidth" : "80px" } , + /* Language */ { "sTitle" : "Language" , "mDataProp" : "language" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" } , + /* Owner */ { "sTitle" : "Owner" , "mDataProp" : "owner" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" } ], "bProcessing": true, diff --git a/python_apps/media-monitor2/media/monitor/metadata.py b/python_apps/media-monitor2/media/monitor/metadata.py index e7a450219..7405d3b12 100644 --- a/python_apps/media-monitor2/media/monitor/metadata.py +++ b/python_apps/media-monitor2/media/monitor/metadata.py @@ -161,6 +161,7 @@ class Metadata(Loggable): # Forcing the unicode through try : fpath = fpath.decode("utf-8") except : pass + if not mmp.file_playable(fpath): raise BadSongFile(fpath) try : full_mutagen = mutagen.File(fpath, easy=True) except Exception : raise BadSongFile(fpath) self.path = fpath diff --git a/python_apps/media-monitor2/media/monitor/pure.py b/python_apps/media-monitor2/media/monitor/pure.py index ac9fd127b..005178157 100644 --- a/python_apps/media-monitor2/media/monitor/pure.py +++ b/python_apps/media-monitor2/media/monitor/pure.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import copy +import subprocess import os import shutil import re @@ -449,6 +450,21 @@ def owner_id(original_path): except Exception: raise return owner_id +def file_playable(pathname): + + #when there is an single apostrophe inside of a string quoted by + #apostrophes, we can only escape it by replace that apostrophe with '\''. + #This breaks the string into two, and inserts an escaped single quote in + #between them. We run the command as pypo because otherwise the target file + #is opened with write permissions, and this causes an inotify ON_CLOSE_WRITE + #event to be fired :/ + + command = ("sudo -u pypo airtime-liquidsoap -c 'output.dummy" + \ + "(audio_to_stereo(single(\"%s\")))' > /dev/null 2>&1") % \ + pathname.replace("'", "'\\''") + return_code = subprocess.call(command, shell=True) + return (return_code == 0) + if __name__ == '__main__': import doctest doctest.testmod() diff --git a/python_apps/media-monitor2/media/update/replaygain.py b/python_apps/media-monitor2/media/update/replaygain.py index ef3d51039..ef15262f0 100644 --- a/python_apps/media-monitor2/media/update/replaygain.py +++ b/python_apps/media-monitor2/media/update/replaygain.py @@ -87,34 +87,34 @@ def calculate_replay_gain(file_path): temp_file_path = duplicate_file(file_path) file_type = get_file_type(file_path) + nice_level = '15' if file_type: if file_type == 'mp3': if run_process("which mp3gain > /dev/null") == 0: - out = get_process_output('mp3gain -q "%s" 2> /dev/null' % temp_file_path) + out = get_process_output('nice -n %s mp3gain -q "%s" 2> /dev/null' % (nice_level, temp_file_path)) search = re.search(r'Recommended "Track" dB change: (.*)', out) else: logger.warn("mp3gain not found") elif file_type == 'vorbis': 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) + run_process('nice -n %s vorbisgain -q -f "%s" 2>/dev/null >/dev/null' % (nice_level,temp_file_path)) out = get_process_output('ogginfo "%s"' % temp_file_path) search = re.search(r'REPLAYGAIN_TRACK_GAIN=(.*) dB', out) else: logger.warn("vorbisgain/ogginfo not found") elif file_type == 'flac': if run_process("which metaflac > /dev/null") == 0: - out = get_process_output('metaflac --show-tag=REPLAYGAIN_TRACK_GAIN "%s"' % temp_file_path) + out = get_process_output('nice -n %s metaflac --show-tag=REPLAYGAIN_TRACK_GAIN "%s"' % (nice_level, temp_file_path)) search = re.search(r'REPLAYGAIN_TRACK_GAIN=(.*) dB', out) - else: - logger.warn("metaflac not found") - else: - pass + else: logger.warn("metaflac not found") - #no longer need the temp, file simply remove it. - os.remove(temp_file_path) except Exception, e: logger.error(str(e)) + finally: + #no longer need the temp, file simply remove it. + try: os.remove(temp_file_path) + except: pass replay_gain = 0 if search: