diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php index 72111cbc1..5bd5949de 100644 --- a/airtime_mvc/application/controllers/LibraryController.php +++ b/airtime_mvc/application/controllers/LibraryController.php @@ -277,6 +277,7 @@ class LibraryController extends Zend_Controller_Action $streams = array(); $message = null; + $noPermissionMsg = "You don't have permission to delete selected items."; foreach ($mediaItems as $media) { @@ -294,19 +295,21 @@ class LibraryController extends Zend_Controller_Action try { Application_Model_Playlist::deletePlaylists($playlists, $user->getId()); } catch (PlaylistNoPermissionException $e) { - $this->view->message = "You don't have permission to delete selected items."; - - return; + $message = $noPermissionMsg; } try { Application_Model_Block::deleteBlocks($blocks, $user->getId()); + } catch (BlockNoPermissionException $e) { + $message = $noPermissionMsg; } catch (Exception $e) { //TODO: warn user that not all blocks could be deleted. } try { Application_Model_Webstream::deleteStreams($streams, $user->getId()); + } catch (WebstreamNoPermissionException $e) { + $message = $noPermissionMsg; } catch (Exception $e) { //TODO: warn user that not all streams could be deleted. Logging::info($e); @@ -318,7 +321,9 @@ class LibraryController extends Zend_Controller_Action if (isset($file)) { try { - $res = $file->delete(true); + $res = $file->delete(); + } catch (FileNoPermissionException $e) { + $message = $noPermissionMsg; } catch (Exception $e) { //could throw a scheduled in future exception. $message = "Could not delete some scheduled files."; diff --git a/airtime_mvc/application/forms/GeneralPreferences.php b/airtime_mvc/application/forms/GeneralPreferences.php index 9bca14349..76144df05 100644 --- a/airtime_mvc/application/forms/GeneralPreferences.php +++ b/airtime_mvc/application/forms/GeneralPreferences.php @@ -15,7 +15,7 @@ class Application_Form_GeneralPreferences extends Zend_Form_SubForm $defaultFade = Application_Model_Preference::GetDefaultFade(); if ($defaultFade == "") { - $defaultFade = '0.500000'; + $defaultFade = '0.5'; } //Station name @@ -37,8 +37,8 @@ class Application_Form_GeneralPreferences extends Zend_Form_SubForm 'required' => false, 'filters' => array('StringTrim'), 'validators' => array(array('regex', false, - array('/^[0-9]{1,2}(\.\d{1,6})?$/', - 'messages' => 'enter a time in seconds 0{.000000}'))), + array('/^[0-9]{1,2}(\.\d{1})?$/', + 'messages' => 'enter a time in seconds 0{.0}'))), 'value' => $defaultFade, 'decorators' => array( 'ViewHelper' diff --git a/airtime_mvc/application/models/Preference.php b/airtime_mvc/application/models/Preference.php index e65151ce4..115ea4aa0 100644 --- a/airtime_mvc/application/models/Preference.php +++ b/airtime_mvc/application/models/Preference.php @@ -189,8 +189,8 @@ class Application_Model_Preference $fade = self::getValue("default_fade"); if ($fade === "") { - // the default value of the fade is 00.500000 - return "00.500000"; + // the default value of the fade is 00.5 + return "00.5"; } // we need this function to work with 2.0 version on default_fade value in cc_pref @@ -204,9 +204,9 @@ class Application_Model_Preference $fade = $out; } - $fade = number_format($fade, 6); + $fade = number_format($fade, 2); //fades need 2 leading zeros for DateTime conversion - $fade = str_pad($fade, 9, "0", STR_PAD_LEFT); + $fade = rtrim(str_pad($fade, 5, "0", STR_PAD_LEFT), "0"); return $fade; } diff --git a/airtime_mvc/application/models/Schedule.php b/airtime_mvc/application/models/Schedule.php index c6776a43e..3a03a4369 100644 --- a/airtime_mvc/application/models/Schedule.php +++ b/airtime_mvc/application/models/Schedule.php @@ -292,7 +292,8 @@ SQL; ft.artist_name AS file_artist_name, ft.album_title AS file_album_title, ft.length AS file_length, - ft.file_exists AS file_exists + ft.file_exists AS file_exists, + ft.mime AS file_mime SQL; $filesJoin = <<checkUserPermissions && $this->user->canSchedule($show->getDbId()) === false) { throw new Exception("You are not allowed to schedule show {$show->getDbName()}."); } + + if ($instance->getDbRecord()) { + throw new Exception("You cannot add files to recording shows."); + } $showEndEpoch = floatval($instance->getDbEnds("U.u")); diff --git a/airtime_mvc/application/models/ShowBuilder.php b/airtime_mvc/application/models/ShowBuilder.php index 8436c3011..789d5990a 100644 --- a/airtime_mvc/application/models/ShowBuilder.php +++ b/airtime_mvc/application/models/ShowBuilder.php @@ -41,6 +41,7 @@ class Application_Model_ShowBuilder "fadein" => "", "fadeout" => "", "image" => false, + "mime" => null, "color" => "", //in hex without the '#' sign. "backgroundColor" => "", //in hex without the '#' sign. ); @@ -277,6 +278,7 @@ class Application_Model_ShowBuilder $row["cueout"] = $p_item["cue_out"]; $row["fadein"] = round(substr($p_item["fade_in"], 6), 6); $row["fadeout"] = round(substr($p_item["fade_out"], 6), 6); + $row["mime"] = $p_item["file_mime"]; $row["pos"] = $this->pos++; @@ -471,7 +473,7 @@ class Application_Model_ShowBuilder $display_items[] = $this->makeFooterRow($scheduled_items[ count($scheduled_items)-1]); } - + return array( "schedule" => $display_items, "showInstances" => $this->showInstances); diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index 41178f2e3..51693f46d 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -335,7 +335,7 @@ SQL; * @param boolean $p_deleteFile * */ - public function delete($deleteFromPlaylist=false) + public function delete() { $filepath = $this->getFilePath(); @@ -344,6 +344,13 @@ SQL; throw new DeleteScheduledFileException(); } + $userInfo = Zend_Auth::getInstance()->getStorage()->read(); + $user = new Application_Model_User($userInfo->id); + $isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER)); + if (!$isAdminOrPM && $this->getFileOwnerId() != $user->getId()) { + throw new FileNoPermissionException(); + } + $music_dir = Application_Model_MusicDir::getDirByPK($this->_file->getDbDirectory()); $type = $music_dir->getType(); @@ -352,9 +359,6 @@ SQL; Application_Model_RabbitMq::SendMessageToMediaMonitor("file_delete", $data); } - if ($deleteFromPlaylist) { - Application_Model_Playlist::DeleteFileFromAllPlaylists($this->getId()); - } // set file_exists falg to false $this->_file->setDbFileExists(false); $this->_file->save(); @@ -1213,3 +1217,4 @@ SQL; class DeleteScheduledFileException extends Exception {} class FileDoesNotExistException extends Exception {} +class FileNoPermissionException extends Exception {} diff --git a/airtime_mvc/application/models/Webstream.php b/airtime_mvc/application/models/Webstream.php index 90afbe973..ef3f32605 100644 --- a/airtime_mvc/application/models/Webstream.php +++ b/airtime_mvc/application/models/Webstream.php @@ -92,7 +92,7 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable if (count($leftOver) == 0) { CcWebstreamQuery::create()->findPKs($p_ids)->delete(); } else { - throw new Exception("Invalid user permissions"); + throw new WebstreamNoPermissionException; } } @@ -370,3 +370,6 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable return $webstream->getDbId(); } } + +class WebstreamNoPermissionException extends Exception {} + diff --git a/airtime_mvc/application/models/airtime/map/CcBlockTableMap.php b/airtime_mvc/application/models/airtime/map/CcBlockTableMap.php index 4495c9b1d..0ce86613c 100644 --- a/airtime_mvc/application/models/airtime/map/CcBlockTableMap.php +++ b/airtime_mvc/application/models/airtime/map/CcBlockTableMap.php @@ -54,7 +54,7 @@ class CcBlockTableMap extends TableMap { */ public function buildRelations() { - $this->addRelation('CcSubjs', 'CcSubjs', RelationMap::MANY_TO_ONE, array('creator_id' => 'id', ), null, null); + $this->addRelation('CcSubjs', 'CcSubjs', RelationMap::MANY_TO_ONE, array('creator_id' => 'id', ), 'CASCADE', null); $this->addRelation('CcPlaylistcontents', 'CcPlaylistcontents', RelationMap::ONE_TO_MANY, array('id' => 'block_id', ), 'CASCADE', null); $this->addRelation('CcBlockcontents', 'CcBlockcontents', RelationMap::ONE_TO_MANY, array('id' => 'block_id', ), 'CASCADE', null); $this->addRelation('CcBlockcriteria', 'CcBlockcriteria', RelationMap::ONE_TO_MANY, array('id' => 'block_id', ), 'CASCADE', null); diff --git a/airtime_mvc/application/models/airtime/map/CcSubjsTableMap.php b/airtime_mvc/application/models/airtime/map/CcSubjsTableMap.php index ffbe8cded..d4f83529a 100644 --- a/airtime_mvc/application/models/airtime/map/CcSubjsTableMap.php +++ b/airtime_mvc/application/models/airtime/map/CcSubjsTableMap.php @@ -64,7 +64,7 @@ class CcSubjsTableMap extends TableMap { $this->addRelation('CcPerms', 'CcPerms', RelationMap::ONE_TO_MANY, array('id' => 'subj', ), 'CASCADE', null); $this->addRelation('CcShowHosts', 'CcShowHosts', RelationMap::ONE_TO_MANY, array('id' => 'subjs_id', ), 'CASCADE', null); $this->addRelation('CcPlaylist', 'CcPlaylist', RelationMap::ONE_TO_MANY, array('id' => 'creator_id', ), 'CASCADE', null); - $this->addRelation('CcBlock', 'CcBlock', RelationMap::ONE_TO_MANY, array('id' => 'creator_id', ), null, null); + $this->addRelation('CcBlock', 'CcBlock', RelationMap::ONE_TO_MANY, array('id' => 'creator_id', ), 'CASCADE', null); $this->addRelation('CcPref', 'CcPref', RelationMap::ONE_TO_MANY, array('id' => 'subjid', ), 'CASCADE', null); $this->addRelation('CcSess', 'CcSess', RelationMap::ONE_TO_MANY, array('id' => 'userid', ), 'CASCADE', null); $this->addRelation('CcSubjsToken', 'CcSubjsToken', RelationMap::ONE_TO_MANY, array('id' => 'user_id', ), 'CASCADE', null); diff --git a/airtime_mvc/application/models/airtime/om/BaseCcSubjsPeer.php b/airtime_mvc/application/models/airtime/om/BaseCcSubjsPeer.php index dbd9978d7..ad60edbb4 100644 --- a/airtime_mvc/application/models/airtime/om/BaseCcSubjsPeer.php +++ b/airtime_mvc/application/models/airtime/om/BaseCcSubjsPeer.php @@ -407,6 +407,9 @@ abstract class BaseCcSubjsPeer { // Invalidate objects in CcPlaylistPeer instance pool, // since one or more of them may be deleted by ON DELETE CASCADE/SETNULL rule. CcPlaylistPeer::clearInstancePool(); + // Invalidate objects in CcBlockPeer instance pool, + // since one or more of them may be deleted by ON DELETE CASCADE/SETNULL rule. + CcBlockPeer::clearInstancePool(); // Invalidate objects in CcPrefPeer instance pool, // since one or more of them may be deleted by ON DELETE CASCADE/SETNULL rule. CcPrefPeer::clearInstancePool(); diff --git a/airtime_mvc/application/views/scripts/form/smart-block-criteria.phtml b/airtime_mvc/application/views/scripts/form/smart-block-criteria.phtml index c75791fe1..3c5ab4643 100644 --- a/airtime_mvc/application/views/scripts/form/smart-block-criteria.phtml +++ b/airtime_mvc/application/views/scripts/form/smart-block-criteria.phtml @@ -30,8 +30,22 @@
criteriasLength; $i++) {?> - modRowMap[$i]; $j++) {?> -
0) && ($this->element->getElement("sp_criteria_field_".$i."_".$j)->getAttrib('disabled') == 'disabled')) { + modRowMap[$i]; $j++) { + if ($this->modRowMap[$i] > 1 && $j != $this->modRowMap[$i]-1) $logicLabel = 'or'; + else $logicLabel = 'and'; + $disabled = $this->element->getElement("sp_criteria_field_".$i."_".$j)->getAttrib('disabled') == 'disabled'?true:false; + // determine if the next row is disabled and only display the logic label if it isn't + if ($j == $this->modRowMap[$i]-1 && $i < 25) { + $n = $i+1; + $nextIndex = $n."_0"; + } elseif ($j+1 < $this->modRowMap[$i]-1) { + $n = $j+1; + $nextIndex = $i."_".$n; + + } + $nextDisabled = $this->element->getElement("sp_criteria_field_".$nextIndex)->getAttrib('disabled') == 'disabled'?true:false; + ?> +
0) && $disabled) { echo 'style=display:none'; } ?>> element->getElement("sp_criteria_field_".$i."_".$j) ?> @@ -45,6 +59,9 @@ + > + + element->getElement("sp_criteria_field_".$i."_".$j)->hasErrors()) : ?> element->getElement("sp_criteria_field_".$i."_".$j)->getMessages() as $error): ?> diff --git a/airtime_mvc/build/schema.xml b/airtime_mvc/build/schema.xml index fc3e6a51f..1a69020d3 100644 --- a/airtime_mvc/build/schema.xml +++ b/airtime_mvc/build/schema.xml @@ -250,7 +250,7 @@ - + diff --git a/airtime_mvc/build/sql/schema.sql b/airtime_mvc/build/sql/schema.sql index d7e1107a4..d30faa09d 100644 --- a/airtime_mvc/build/sql/schema.sql +++ b/airtime_mvc/build/sql/schema.sql @@ -697,7 +697,7 @@ ALTER TABLE "cc_playlistcontents" ADD CONSTRAINT "cc_playlistcontents_block_id_f ALTER TABLE "cc_playlistcontents" ADD CONSTRAINT "cc_playlistcontents_playlist_id_fkey" FOREIGN KEY ("playlist_id") REFERENCES "cc_playlist" ("id") ON DELETE CASCADE; -ALTER TABLE "cc_block" ADD CONSTRAINT "cc_block_createdby_fkey" FOREIGN KEY ("creator_id") REFERENCES "cc_subjs" ("id"); +ALTER TABLE "cc_block" ADD CONSTRAINT "cc_block_createdby_fkey" FOREIGN KEY ("creator_id") REFERENCES "cc_subjs" ("id") ON DELETE CASCADE; ALTER TABLE "cc_blockcontents" ADD CONSTRAINT "cc_blockcontents_file_id_fkey" FOREIGN KEY ("file_id") REFERENCES "cc_files" ("id") ON DELETE CASCADE; diff --git a/airtime_mvc/public/css/styles.css b/airtime_mvc/public/css/styles.css index c47192450..1b0a12dd3 100644 --- a/airtime_mvc/public/css/styles.css +++ b/airtime_mvc/public/css/styles.css @@ -514,6 +514,9 @@ table.library-get-file-md.table-small{ /***** SMART BLOCK SPECIFIC STYLES BEGIN *****/ +.db-logic-label{ + font-size:11px; +} .sp-invisible{ visibility: hidden; } diff --git a/airtime_mvc/public/js/airtime/common/audioplaytest.js b/airtime_mvc/public/js/airtime/common/audioplaytest.js index 76bc5d7c1..f96ad09af 100644 --- a/airtime_mvc/public/js/airtime/common/audioplaytest.js +++ b/airtime_mvc/public/js/airtime/common/audioplaytest.js @@ -14,5 +14,6 @@ function isAudioSupported(mime){ //Note that checking the navigator.mimeTypes value does not work for IE7, but the alternative //is adding a javascript library to do the work for you, which seems like overkill.... return (!!audio.canPlayType && audio.canPlayType(bMime) != "") || - (mime.indexOf("mp3") != -1 && navigator.mimeTypes ["application/x-shockwave-flash"] != undefined); + (mime.indexOf("mp3") != -1 && navigator.mimeTypes ["application/x-shockwave-flash"] != undefined) || + (mime.indexOf("mp4") != -1 && navigator.mimeTypes ["application/x-shockwave-flash"] != undefined); } diff --git a/airtime_mvc/public/js/airtime/library/events/library_playlistbuilder.js b/airtime_mvc/public/js/airtime/library/events/library_playlistbuilder.js index 5392cbd49..fd9851f33 100644 --- a/airtime_mvc/public/js/airtime/library/events/library_playlistbuilder.js +++ b/airtime_mvc/public/js/airtime/library/events/library_playlistbuilder.js @@ -37,6 +37,11 @@ var AIRTIME = (function(AIRTIME) { var $nRow = $(nRow); if (aData.ftype === "audioclip") { $nRow.addClass("lib-audio"); + $image = $nRow.find('td.library_type'); + if (!isAudioSupported(aData.mime)) { + $image.html(''); + aData.image = ''; + } } else if (aData.ftype === "stream") { $nRow.addClass("lib-stream"); } else if (aData.ftype === "block") { diff --git a/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js b/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js index 67151e869..ba03586d0 100644 --- a/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js +++ b/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js @@ -29,6 +29,11 @@ var AIRTIME = (function(AIRTIME) { if (aData.ftype === "audioclip") { $nRow.addClass("lib-audio"); + $image = $nRow.find('td.library_type'); + if (!isAudioSupported(aData.mime)) { + $image.html(''); + aData.image = ''; + } } else if (aData.ftype === "stream") { $nRow.addClass("lib-stream"); } else { diff --git a/airtime_mvc/public/js/airtime/library/library.js b/airtime_mvc/public/js/airtime/library/library.js index 504fa8b59..b463610bc 100644 --- a/airtime_mvc/public/js/airtime/library/library.js +++ b/airtime_mvc/public/js/airtime/library/library.js @@ -542,7 +542,7 @@ var AIRTIME = (function(AIRTIME) { type = $("#library_display_type").find("select").val(); type = (type === undefined) ? 0 : type; aoData.push( { name: "type", value: type} ); - + $.ajax( { "dataType": 'json', "type": "POST", @@ -562,7 +562,9 @@ var AIRTIME = (function(AIRTIME) { // pl_ open_playlist_preview(playlistIndex, 0); } else if (aData.ftype === 'audioclip') { - open_audio_preview(aData.ftype, aData.audioFile, aData.track_title, aData.artist_name); + if (isAudioSupported(aData.mime)) { + open_audio_preview(aData.ftype, aData.audioFile, aData.track_title, aData.artist_name); + } } else if (aData.ftype == 'stream') { open_audio_preview(aData.ftype, aData.audioFile, aData.track_title, aData.artist_name); } else if (aData.ftype == 'block' && aData.bl_type == 'static') { diff --git a/airtime_mvc/public/js/airtime/library/spl.js b/airtime_mvc/public/js/airtime/library/spl.js index e79678201..1b5e765a4 100644 --- a/airtime_mvc/public/js/airtime/library/spl.js +++ b/airtime_mvc/public/js/airtime/library/spl.js @@ -369,29 +369,33 @@ var AIRTIME = (function(AIRTIME){ $.each($("div .big_play"), function(index, value){ if ($(value).attr('blockId') === undefined) { var mime = $(value).attr("data-mime-type"); - if (isAudioSupported(mime)) { - $(value).bind("click", openAudioPreview); - } else { - $(value).attr("class", "big_play_disabled dark_class"); - $(value).qtip({ - content: 'Your browser does not support playing this file type: "'+ mime +'"', - show: 'mouseover', - hide: { - delay: 500, - fixed: true - }, - style: { - border: { - width: 0, - radius: 4 + //If mime is undefined it is likely because the file was + //deleted from the library. This case is handled in mod.onReady() + if (mime !== undefined) { + if (isAudioSupported(mime)) { + $(value).bind("click", openAudioPreview); + } else { + $(value).attr("class", "big_play_disabled dark_class"); + $(value).qtip({ + content: 'Your browser does not support playing this file type: "'+ mime +'"', + show: 'mouseover', + hide: { + delay: 500, + fixed: true }, - classes: "ui-tooltip-dark ui-tooltip-rounded" - }, - position: { - my: "left bottom", - at: "right center" - }, - }) + style: { + border: { + width: 0, + radius: 4 + }, + classes: "ui-tooltip-dark ui-tooltip-rounded" + }, + position: { + my: "left bottom", + at: "right center" + }, + }) + } } } else { if ($(value).attr('blocktype') === 'dynamic') { diff --git a/airtime_mvc/public/js/airtime/playlist/smart_blockbuilder.js b/airtime_mvc/public/js/airtime/playlist/smart_blockbuilder.js index fc736b84a..c33ccc351 100644 --- a/airtime_mvc/public/js/airtime/playlist/smart_blockbuilder.js +++ b/airtime_mvc/public/js/airtime/playlist/smart_blockbuilder.js @@ -8,14 +8,17 @@ function setSmartBlockEvents() { /********** ADD CRITERIA ROW **********/ form.find('#criteria_add').live('click', function(){ - var div = $('dd[id="sp_criteria-element"]').children('div:visible:last').next(); - - div.show(); + var div = $('dd[id="sp_criteria-element"]').children('div:visible:last'); + + div.find('.db-logic-label').text('and').show(); + div = div.next().show(); + div.children().removeAttr('disabled'); div = div.next(); if (div.length === 0) { $(this).hide(); } + appendAddButton(); appendModAddButton(); removeButtonCheck(); @@ -24,7 +27,7 @@ function setSmartBlockEvents() { /********** ADD MODIFIER ROW **********/ form.find('a[id^="modifier_add"]').live('click', function(){ var criteria_value = $(this).siblings('select[name^="sp_criteria_field"]').val(); - + //make new modifier row var newRow = $(this).parent().clone(), newRowCrit = newRow.find('select[name^="sp_criteria_field"]'), @@ -285,6 +288,11 @@ function reindexElements() { var divs = $('#smart-block-form').find('div select[name^="sp_criteria_field"]').parent(), index = 0, modIndex = 0; + /* Hide all logic labels + * We will re-add them as each row gets indexed + */ + $('.db-logic-label').text('').hide(); + $.each(divs, function(i, div){ if (i > 0 && index < 26) { @@ -292,8 +300,14 @@ function reindexElements() { * a modifier row */ if ($(div).find('select[name^="sp_criteria_field"]').hasClass('sp-invisible')) { + if ($(div).is(':visible')) { + $(div).prev().find('.db-logic-label').text('or').show(); + } modIndex++; } else { + if ($(div).is(':visible')) { + $(div).prev().find('.db-logic-label').text('and').show(); + } index++; modIndex = 0; } @@ -337,8 +351,8 @@ function setupUI() { */ var plContents = $('#spl_sortable').children(); var shuffleButton = $('button[id="shuffle_button"]'); - - if (plContents.text() !== 'Empty playlist') { + + if (!plContents.hasClass('spl_empty')) { if (shuffleButton.hasClass('ui-state-disabled')) { shuffleButton.removeClass('ui-state-disabled'); shuffleButton.removeAttr('disabled'); diff --git a/airtime_mvc/public/js/airtime/showbuilder/builder.js b/airtime_mvc/public/js/airtime/showbuilder/builder.js index de9142190..48015f92c 100644 --- a/airtime_mvc/public/js/airtime/showbuilder/builder.js +++ b/airtime_mvc/public/js/airtime/showbuilder/builder.js @@ -369,7 +369,8 @@ var AIRTIME = (function(AIRTIME){ /* cue in */ {"mDataProp": "cuein", "sTitle": "Cue In", "bVisible": false, "sClass": "sb-cue-in"}, /* cue out */ {"mDataProp": "cueout", "sTitle": "Cue Out", "bVisible": false, "sClass": "sb-cue-out"}, /* fade in */ {"mDataProp": "fadein", "sTitle": "Fade In", "bVisible": false, "sClass": "sb-fade-in"}, - /* fade out */ {"mDataProp": "fadeout", "sTitle": "Fade Out", "bVisible": false, "sClass": "sb-fade-out"} + /* fade out */ {"mDataProp": "fadeout", "sTitle": "Fade Out", "bVisible": false, "sClass": "sb-fade-out"}, + /* Mime */ {"mDataProp" : "mime", "sTitle" : "Mime", "bVisible": false, "sClass": "sb-mime"} ], "bJQueryUI": true, @@ -549,11 +550,16 @@ var AIRTIME = (function(AIRTIME){ $image = $nRow.find('td.sb-image'); //check if the file exists. if (aData.image === true) { - $image.html('') + $nRow.addClass("lib-audio"); + if (!isAudioSupported(aData.mime)) { + $image.html(''); + } else { + $image.html('') .click(function() { open_show_preview(aData.instance, aData.pos); return false; }); + } } else { $image.html(''); diff --git a/airtime_mvc/public/js/bootstrap/bootstrap.js b/airtime_mvc/public/js/bootstrap/bootstrap.js index 7f303eb88..3ba659d60 100644 --- a/airtime_mvc/public/js/bootstrap/bootstrap.js +++ b/airtime_mvc/public/js/bootstrap/bootstrap.js @@ -574,7 +574,7 @@ }) }(window.jQuery);/* ============================================================ - * bootstrap-dropdown.js v2.1.0 + * bootstrap-dropdown.js v2.2.1 * http://twitter.github.com/bootstrap/javascript.html#dropdowns * ============================================================ * Copyright 2012 Twitter, Inc. @@ -675,8 +675,9 @@ } function clearMenus() { - getParent($(toggle)) - .removeClass('open') + $(toggle).each(function () { + getParent($(this)).removeClass('open') + }) } function getParent($this) { @@ -685,7 +686,7 @@ if (!selector) { selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 } $parent = $(selector) @@ -713,14 +714,11 @@ /* APPLY TO STANDARD DROPDOWN ELEMENTS * =================================== */ - $(function () { - $('html') - .on('click.dropdown.data-api touchstart.dropdown.data-api', clearMenus) - $('body') - .on('click.dropdown touchstart.dropdown.data-api', '.dropdown', function (e) { e.stopPropagation() }) - .on('click.dropdown.data-api touchstart.dropdown.data-api' , toggle, Dropdown.prototype.toggle) - .on('keydown.dropdown.data-api touchstart.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown) - }) + $(document) + .on('click.dropdown.data-api touchstart.dropdown.data-api', clearMenus) + .on('click.dropdown touchstart.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) + .on('click.dropdown.data-api touchstart.dropdown.data-api' , toggle, Dropdown.prototype.toggle) + .on('keydown.dropdown.data-api touchstart.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown) }(window.jQuery);/* ========================================================= * bootstrap-modal.js v2.1.0 diff --git a/python_apps/media-monitor2/media/monitor/events.py b/python_apps/media-monitor2/media/monitor/events.py index 0b2a92e14..761ffddb7 100644 --- a/python_apps/media-monitor2/media/monitor/events.py +++ b/python_apps/media-monitor2/media/monitor/events.py @@ -148,6 +148,9 @@ class BaseEvent(Loggable): owners.remove_file_owner(self.path) return ret except BadSongFile as e: return [e] + except Exception as e: + self.unexpected_exception(e) + return[e] # nothing to see here, please move along def morph_into(self, evt): diff --git a/python_apps/media-monitor2/media/monitor/manager.py b/python_apps/media-monitor2/media/monitor/manager.py index 33dc90468..a2fc47028 100644 --- a/python_apps/media-monitor2/media/monitor/manager.py +++ b/python_apps/media-monitor2/media/monitor/manager.py @@ -202,6 +202,12 @@ class Manager(Loggable): organize. """ store_paths = mmp.expand_storage(store) + # First attempt to make sure that all paths exist before adding any + # watches + for path_type, path in store_paths.iteritems(): + try: mmp.create_dir(path) + except mmp.FailedToCreateDir as e: self.unexpected_exception(e) + self.set_problem_files_path(store_paths['problem_files']) self.set_imported_path(store_paths['imported']) self.set_recorded_path(store_paths['recorded']) diff --git a/python_apps/media-monitor2/mm2.py b/python_apps/media-monitor2/mm2.py index ea1178a2f..217cfcfc8 100644 --- a/python_apps/media-monitor2/mm2.py +++ b/python_apps/media-monitor2/mm2.py @@ -104,6 +104,9 @@ def main(global_config, api_client_config, log_config, airtime_notifier = AirtimeNotifier(config, airtime_receiver) store = apiclient.setup_media_monitor() + + log.info("Initing with the following airtime response:%s" % str(store)) + airtime_receiver.change_storage({ 'directory':store[u'stor'] }) for watch_dir in store[u'watched_dirs']: @@ -115,6 +118,7 @@ def main(global_config, api_client_config, log_config, (given from the database)." % watch_dir) if os.path.exists(watch_dir): airtime_receiver.new_watch({ 'directory':watch_dir }, restart=True) + else: log.info("Failed to add watch on %s" % str(watch_dir)) bs = Bootstrapper( db=sdb, watch_signal='watch' ) diff --git a/python_apps/pypo/liquidsoap_scripts/ls_script.liq b/python_apps/pypo/liquidsoap_scripts/ls_script.liq index 1f476b919..34e56786e 100644 --- a/python_apps/pypo/liquidsoap_scripts/ls_script.liq +++ b/python_apps/pypo/liquidsoap_scripts/ls_script.liq @@ -201,9 +201,6 @@ def append_dj_inputs(master_harbor_input_port, master_harbor_input_mount_point, dj_live = mksafe(audio_to_stereo(input.harbor(id="live_dj_harbor", dj_harbor_input_mount_point, port=dj_harbor_input_port, auth=check_dj_client, max=40., on_connect=live_dj_connect, on_disconnect=live_dj_disconnect))) - master_dj = rewrite_metadata([("artist","Airtime"), ("title", "Master Dj")],master_dj) - dj_live = rewrite_metadata([("artist","Airtime"), ("title", "Live Dj")],dj_live) - ignore(output.dummy(master_dj, fallible=true)) ignore(output.dummy(dj_live, fallible=true)) switch(id="master_dj_switch", track_sensitive=false, transitions=[transition, transition, transition], [({!master_dj_enabled},master_dj), ({!live_dj_enabled},dj_live), ({true}, s)]) @@ -211,14 +208,12 @@ def append_dj_inputs(master_harbor_input_port, master_harbor_input_mount_point, master_dj = mksafe(audio_to_stereo(input.harbor(id="master_harbor", master_harbor_input_mount_point, port=master_harbor_input_port, auth=check_master_dj_client, max=40., on_connect=master_dj_connect, on_disconnect=master_dj_disconnect))) ignore(output.dummy(master_dj, fallible=true)) - master_dj = rewrite_metadata([("artist","Airtime"), ("title", "Master Dj")],master_dj) + switch(id="master_dj_switch", track_sensitive=false, transitions=[transition, transition], [({!master_dj_enabled},master_dj), ({true}, s)]) elsif dj_harbor_input_port != 0 and dj_harbor_input_mount_point != "" then dj_live = mksafe(audio_to_stereo(input.harbor(id="live_dj_harbor", dj_harbor_input_mount_point, port=dj_harbor_input_port, auth=check_dj_client, max=40., on_connect=live_dj_connect, on_disconnect=live_dj_disconnect))) - dj_live = rewrite_metadata([("artist","Airtime"), ("title", "Live Dj")],dj_live) - ignore(output.dummy(dj_live, fallible=true)) switch(id="live_dj_switch", track_sensitive=false, transitions=[transition, transition], [({!live_dj_enabled},dj_live), ({true}, s)]) else diff --git a/utils/airtime-import/airtime-import.py b/utils/airtime-import/airtime-import.py index 408bd91ac..c77a0f21e 100644 --- a/utils/airtime-import/airtime-import.py +++ b/utils/airtime-import/airtime-import.py @@ -159,6 +159,7 @@ def WatchAddAction(option, opt, value, parser): path = currentDir+path path = apc.encode_to(path, 'utf-8') if(os.path.isdir(path)): + os.chmod(path, 0765) res = api_client.add_watched_dir(path) if(res is None): exit("Unable to connect to the server.")